德尔斐时间数学
我有一个非常不寻常的问题(对我来说)。我正在编写一个应用程序,它将允许用户通过显式日期(将我的日期更改为6/3/1955)或者使用按钮递增(向前1个月)来更改其系统时间。
我写这篇文章是为了帮助我的一些用户测试某些需要像这样跳转的软件,以便模拟计费系统的实际使用情况。
在Delphi中更改时间当然非常容易:
SetDateTime(2008,05,21,16,07,21,00);
但是我不确定Delphi(2006)是否有内置的日期数学帮助器,这是我最不喜欢的事情之一:)
对解决此问题的最佳方法有何建议?我宁愿保持本地性,因为winapi datetime调用很糟糕。
谢谢!
解决方案
VCL的类型(TDate和TDateTime)为双精度类型,可以在算术运算中使用。
另请参见EncodeDate和DecodeDate
DateUtils单元中有很多帮助者。
SysUtils单元中有很多帮助程序(如gabr所指出的,在DateUtils中也有)。
如gabr和mliesen所述,请看一下DateUtils和SysUtils单元,其中包括有用的功能。
- IncDay-添加或者减去天数。
- IncMonth-加或者减数个月。
- IncWeek-加上或者减去几周。
- IncYear-增加或者减去几年。
- EncodeDate-从年,月和日参数中返回TDateTime值。
如果当前月份的日期在未来的月份中不存在,我们想怎么办?假设1月31日+ 1个月?如果我们增加年份并且开始日期是leap年的2月29日,则会遇到相同的问题。因此,不可能有一个通用的IncMonth或者IncYear函数在所有日期上都能稳定工作。
对于感兴趣的任何人,我都衷心推荐朱利安·巴克纳尔(Julian Bucknall)的文章,介绍这种计算类型固有的复杂性
如何计算两个日期之间的月数和天数。
以下是唯一可能不会在通用日期数学中引入异常的通用日期增量函数。但这只能通过将责任转移给程序员(可能对他/她正在编程的特定应用程序有确切要求)的责任来实现。
IncDay添加或者减去天数。
IncWeek加或者减数周。
但是,如果必须使用内置函数,则至少要确保它们执行了我们希望它们执行的操作。看一下DateUtils和SysUtils单位。拥有这些功能的源代码是Delphi最酷的方面之一。话虽如此,这是内置函数的完整列表:
IncDay添加或者减去天数。
IncWeek加或者减数周。
IncMonth加或者减数个月。
IncYear增加或者减去几年。
至于问题的第二部分,如何使用TDatetime设置系统日期和时间,以下从另一篇帖子中偷偷摸摸的代码将完成这项工作:
procedure SetSystemDateTime(aDateTime: TDateTime); var lSystemTime: TSystemTime; lTimeZone: TTimeZoneInformation; begin GetTimeZoneInformation(lTimeZone); aDateTime := aDateTime + (lTimeZone.Bias / 1440); DateTimeToSystemTime(aDateTime, lSystemTime); setSystemTime(lSystemTime); end;