其实这个部分的函数大部分都是依赖于几个基础判断函数,其他函数使用不同参数解析为这几个基础判断函数所需的参数,然后返回这几个基础函数的调用结果而已.例如IsToday是返回的IsSameDay的结果,参数1为IsToday函数的参数,参数2为系统函数Date;还有Tomorrow和Yesterday还有Today,这三个方法里都是使用系统预定义函数Date获取当前时间,Today直接返回这个函数的结果,而Tommorrow和Yesterday则是返回Date函数的结果+1和-1.
同时我们还发现,这几个基础函数其实都是先预定义一些合法值范围的数组常量或其它类型的常量,在基础函数中先对参数解析,然后根据条件判断其值是否在预定义的常量中,并返回判断的结果值(如果需要返回天数或星期数之类的,也是根据参数返回对应预定义数组常量下标内元素值,或预定义的常量).
以下是我写的部分代码示例,因为整个单元文件代码字数太多,无法在一篇文章中存放,所以我把对应的单元文件.pas和窗体文件.dfm放在了代码分享处,想查看所有源码的请移步Misc functions部分函数使用示例及说明
procedure TFMain.btnDaysInMonthClick(Sender: TObject); var dBefore: TDateTime; begin //DaysInMonth:返回日期参数所在年的总天数 dBefore := StrToDateTime(sDate, FDateFormatSetting); //我们来看看DaysInMonth的实现System.DateUtils 第657行 { function DaysInMonth(const AValue: TDateTime): Word; var LYear, LMonth, LDay: Word; begin //DaysInAMonth定义在System.DateUtils第665行 //因为DaysInAMonth参数为拆分后的年和月,所以第一步先把日期拆分成年\月\日三个参数 //DaysInAMonth里面的实现类同与DaysInAYear,根据平年闰年返回预定义数组的某个下标值 //下面这个数组定义在System.SysUtils第2770行 //MonthDays: array [Boolean] of TDayTable = // ((31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31), // (31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)); DecodeDate(AValue, LYear, LMonth, LDay); Result := DaysInAMonth(LYear, LMonth); end; } MMOResult.Lines.Add('(DaysInMonth)日期参数[' + sDate + '],本年度本月份共有:' + IntToStr(DaysInMonth(dBefore)) + '天'); end; procedure TFMain.btnDaysInAMonthClick(Sender: TObject); var dBefore: TDateTime; nYear, nMonth, nDay: Word; begin //DaysInAMonth:返回年份参数+中月份参数的总天数 dBefore := StrToDateTime(sDate, FDateFormatSetting); DecodeDate(dBefore, nYear, nMonth, nDay); //我们来看看DaysInAMonth的实现System.DateUtils 第665行 { function DaysInAMonth(const AYear, AMonth: Word): Word; begin //这里根据平年或闰年+月份,返回一个预定义的数组下标值 Result := MonthDays[(AMonth = 2) and IsLeapYear(AYear), AMonth]; end; } MMOResult.Lines.Add('(DaysInAMonth)年份参数[' + IntToStr(nYear) + ']月份参数[' + IntToStr(nMonth) + '],本年度本月份共有:' + IntToStr(DaysInAMonth(nYear, nMonth)) + '天'); end; procedure TFMain.btnTodayClick(Sender: TObject); begin //Today:返回当天日期 //我们来看看Today的实现System.DateUtils 第686行 { function Today: TDateTime; begin //这里的Date其实也是一个方法,定义在System.SysUtils第18812行 //内部调用了GetLocalTime这个API,并且使用EncodeDate对返回值进行格式化,只保留日期部分 Result := Date; end; } MMOResult.Lines.Add('(Today)今日为:' + FormatDateTime('yyyy-MM-dd HH:nn:ss', Today, FDateFormatSetting)); end; procedure TFMain.btnYesterdayClick(Sender: TObject); begin //Yesterday:返回昨日日期 //我们来看看Yesterday的实现System.DateUtils 第691行 { function Yesterday: TDateTime; begin //这里其实是返回了Date-1的一个时间 //从Today我们看出Date是调用windowsAPI获取本机时间,并格式化成日期 //我们还知道Delphi中时间的其实是一个浮点数,整数位是从1899年12月31日到现在的总天数 //小数位为一天24小时的百分比 //所以这里获取到今天-1,就是昨天(Date函数返回的是一个日期,不包含时间部分) Result := Date - 1; end; } MMOResult.Lines.Add('(Yesterday)昨日为:' + FormatDateTime('yyyy-MM-dd HH:nn:ss', Yesterday, FDateFormatSetting)); end; procedure TFMain.btnTomorrowClick(Sender: TObject); begin //Tomorrow:返回明日日期 //我们来看看Tomorrow的实现System.DateUtils 第696行 { function Tomorrow: TDateTime; begin //不得不说DELPHI开发团队很聪明,他们还是采用的这种当前日期+1的方式来处理的.这里就不在讲解 Result := Date + 1; end; } MMOResult.Lines.Add('(Tomorrow)明日为:' + FormatDateTime('yyyy-MM-dd HH:nn:ss', Tomorrow, FDateFormatSetting)); end; procedure TFMain.btnIsTodayClick(Sender: TObject); var dBefore: TDateTime; begin //IsToday:判断传入的日期是否为今天 dBefore := StrToDateTime(sDate, FDateFormatSetting); //我们来看看IsToday的实现System.DateUtils 第696行 { function IsToday(const AValue: TDateTime): Boolean; begin //IsSameDay定义在System.DateUtils第706行,判断参数1是否大于等于参数二,并且小于参数2+1 //其实在这里我感觉写这段代码的人很聪明,最起码比我聪明,我就没想到这个处理方式 //第一个参数是我们传入的日期,第二个参数是系统当前日期,注意是日期,不带时间的日期 //假如今天是2015-08-13,我们传入的是2015-08-13 20:44:28 //那么IsSameDay里面的判断就是 //结果=(2015-08-13 20:44:28 >= 2015-08-13 00:00:00) and (2015-08-13 20:44:28 < 2015-08-13 00:00:00 + 1) //所以这里无论咱们传入的是纯日期格式,还是日期+时间格式,都不会出现判断错误问题,很牛 Result := IsSameDay(AValue, Date); end; } if IsToday(dBefore) then MMOResult.Lines.Add('(IsToday)日期参数[' + sDate + '],为今日') else MMOResult.Lines.Add('(IsToday)日期参数[' + sDate + '],非今日'); end; procedure TFMain.btnIsSameDayClick(Sender: TObject); var dBefore, dPar2: TDateTime; begin //IsSameDay:判断参数1和参数2是否是同一天 dBefore := StrToDateTime(sDate, FDateFormatSetting); dPar2 := dBefore + 1 / 24; //我们来看看IsSameDay的实现System.DateUtils 第706行 { function IsSameDay(const AValue, ABasis: TDateTime): Boolean; begin //这里其实是跟IsToday的判断差不多 //Trunc函数为取得参数的整数部分 //我们也知道TDateTime类型的整数部分代表日,所以这里的判断类似IsToday Result := (AValue >= Trunc(ABasis)) and (AValue < Trunc(ABasis) + 1); end; } if IsSameDay(dBefore, dPar2) then MMOResult.Lines.Add('(IsSameDay)日期参数1[' + sDate + '],参数2[' + FormatDateTime('yyyy-MM-dd HH:nn:ss', dPar2, FDateFormatSetting) + '],为同一天') else MMOResult.Lines.Add('(IsSameDay)日期参数1[' + sDate + '],参数2[' + FormatDateTime('yyyy-MM-dd HH:nn:ss', dPar2, FDateFormatSetting) + '],非同一天'); end;