*日期的核心算法
参考链接:
日历参考链接
import {logClass} from "Components/Decorator/Decorator";
interface IDay {
dayNum:number;
isSignIn?: boolean;
isShowSignIn: boolean;
}
@logClass
class DateItem {
/**
* @param dayNum 日数, 如果和 new Date().getDate() 相等则是今天
* @param isSignIn=false 是否签到
* @param isShowSignIn=false 是否显示是否签到,大于今日和这个月的日期应该都不显示
*/
dayNum:number;
isSignIn?: boolean;
isShowSignIn: boolean;
constructor(day:IDay) {
this.dayNum=day.dayNum;
this.isSignIn=day.isSignIn;
this.isShowSignIn=day.isShowSignIn;
};
}
export default DateItem;
import * as React from 'react';
import DateItem from './DateItem'
import _ from 'lodash'
export interface IDatePickerProps{
DefaultDate:string[];
}
export interface IDatePickerState {
year:number;//年份
month:number;//月份
date:Date,//当前时间点
nowadays:number;//当日
thisMonth:number;//当月
day:number;//本月第一天是星期数
days:number,//本月总有多少天
list:DateItem[],//天数+第一天星期数的数组
twoDimArr:DateItem[][],//list分割成的二维数组
}
interface IYMD {//年月日接口
year:number;
month:number;
day?:number;
}
const l=console.log;
const weeks = ["日", "一", "二", "三", "四", "五", "六"];
class DatePicker extends React.Component{
constructor(props: Readonly){
super(props);
this.initState=this.initState.bind(this);
this.handleDateItemClick=this.handleDateItemClick.bind(this);
this.handleNextMonth=this.handleNextMonth.bind(this);
this.handlePreMonth=this.handlePreMonth.bind(this);
this.toDayClick=this.toDayClick.bind(this);
}
componentWillMount(): void {
this.initState({year:0,month:0});
}
// @autoBindThis
initState(ymd:IYMD){
const date=new Date();
l(`${ymd}`);
//获取天数
const year=ymd.year||date.getFullYear();//年
const month=ymd.month||date.getMonth()+1;//月
l(`${year}年${month}月`);
let date2 = new Date(year, month, 0);
let days = date2.getDate(); // 本月有多少天
l(`本月有${days}天.`);
//本月第一天是星期几
date2.setDate(1);
let day = date2.getDay(); // 本月第一天是星期几
l(`本月第一天是星期${day}.`);
let list = [];
const nowadays = date.getDate(); // 本日
const thisMonth = date.getMonth() + 1; // 本月
let isShowSignIn:boolean = false; //是否可以点击
const date2GtDate = date2 > date;//传入的年月是不是在当前日期前
const isThisMonth = month === thisMonth; // 传入的月month,选择的日期的月份是否是本月
//得到一个星期数+本月天数的长度数组
for (let i = 0; i < days + day; i++) {
const dayNum = i - day + 1;
//判断是否可以签到
if (date2GtDate) {
isShowSignIn = false;
} else {
if (isThisMonth && i >= day + nowadays) {
isShowSignIn = false;
} else {
isShowSignIn = true;
}
}
//添加日期的编号
if (i < day) {
list.push(new DateItem({ dayNum: 0, isShowSignIn }));
} else {
list.push(new DateItem({ dayNum, isShowSignIn }));
}
}
let twoDimArr=this.getTwoDimensional(list,isShowSignIn);
this.setState({
year,
month,
date,
nowadays,
thisMonth,
day,
days,
list,
twoDimArr,
});
}
getTwoDimensional(list:DateItem[],isShowSignIn:boolean):DateItem[][]{
let twoDimensionArr= _.chunk(list,7);
let twoDimLength=twoDimensionArr.length;
let to=7-twoDimensionArr[twoDimLength-1].length;
// 循环尾部补空格
for (let i = 0; i < to; i++) {
twoDimensionArr[twoDimLength - 1].push(new DateItem({ dayNum: 0, isShowSignIn }));
}
return twoDimensionArr
}
//上一月
// @autoBindThis
handlePreMonth(){
alert("000");
let prevMonth = this.state.month + -1;
let prevYear = this.state.year;
if (prevMonth < 1) {
prevMonth = 12;
prevYear -= 1;
}
this.initState({year:prevYear,month:prevMonth});
}
//下一个月
//@autoBindThis
handleNextMonth(){
let nextMonth = this.state.month + 1;
let nextYear = this.state.year;
if (nextMonth > 12) {
nextMonth = 1;
nextYear += 1;
}
this.initState({
year: nextYear,
month: nextMonth,
});
};
toDayClick(e:any) {
this.initState({year:0,month:0});
e.stopPropagation();
}
// 点击每个日期
//@autoBindThis
handleDateItemClick (dateItem:DateItem, i:number, j:number){
const { year, month, date, nowadays } = this.state;
const { isShowSignIn, isSignIn, dayNum } = dateItem;
if (dayNum === 0) return;
const selectDate = new Date(`${year}-${month}-${dayNum}`);
if (nowadays === dayNum) {
l("签到");
} else if (selectDate < date) {
l("补签");
}
if (!isShowSignIn || isSignIn)
// 不能签到的日期和已签到的日期直接返回
return;
this.setState(state => {
const twoDimArr = state.twoDimArr.slice();
twoDimArr[i][j].isSignIn = true;
return {twoDimArr};
});
};
render(): React.ReactNode {
const {year,month,nowadays,twoDimArr,thisMonth}=this.state;
return (
{year}年-{month}月
{weeks.map(el => (
{el}
))}
{this.state.twoDimArr.map((el, i) => {
return (
{el.map((dateItem, j) => {
const dayNum = dateItem.dayNum;
const isSignIn = dateItem.isSignIn;
const isShowSignIn = dateItem.isShowSignIn;
return (
{
e.stopPropagation();
this.handleDateItemClick(dateItem, i, j)}}
>
{dayNum}
{!!isShowSignIn && (
{!!isSignIn ? `已签到` : `未签到`}
)}
);
})}
);
})}
);
}
}
export default DatePicker;