Delphi – 相当于需要C#DateTime.IsDaylightSavingTime()方法
我需要以某种方式确定某个TDateTime值是否在我的时区的夏令时范围内(在C#中与DateTime.IsDaylightSavingTime()方法相同).
我知道在Delphi中没有类似的功能,因为Delphi TDateTime不包含有关时区的信息,但我想有一些方法可以使用Win32 API来实现. 我看过Win32 API GetTimeZoneInformation和GetTimeZoneInformationForYear函数,但我不太明白如何使用它们,所以我想请你帮忙.提前感谢任何提示. 编辑: 例: 在我的时区(中欧)夏令时开始于今年 我需要一个带标题的函数: function IsDaylightSavingTime(input: TDateTime): boolean; 如果输入日期在2010年3月28日2:00到2010年10月31日3:00之间,则返回true,否则返回false. (这个例子仅适用于2010年,但我需要它可以工作多年.) 再一次,我知道单独保存在TDateTime中的信息是不够的,但我认为通过一些Win32 API函数,我应该能够获得Windows设置中有关当前时区的信息. 解决方法
它并不像听起来那么容易,因为:
1)DST和标准时间之间的切换日期对于所有国家都不相同 2)DST和标准时间之间的转换日期与所有年份的同一国家的算法不同(例如,在中欧,它之前是4月的第一个星期日,IIRC,现在是3月的最后一个星期日).美国从4月的第一个星期日变为2007年3月的第二个星期日. 所以 – 一个简单的日期是不够的,你还需要一个地理位置. 但是,如果您能够接受这样的事实,那么您可以将自己限制为可以根据CURRENT语言环境(国家/地区)的CURRENT年的CURRENT算法计算的切换日期,并且这可能对于日期中的日期都是错误的.未来和过去,您可以使用TIME_ZONE_INFORMATION中的信息来计算切换日期: USES Windows,SysUtils,DateUtils; FUNCTION GetDaylightSavingsSwitchOverDates(Year : Cardinal ; VAR Start,Stop : TDateTime) : BOOLEAN; VAR TZ : TTimeZoneInformation; FUNCTION DecodeSwitchOverDate(Year : Cardinal ; CONST Time : TSystemTime) : TDateTime; VAR I : Cardinal; BEGIN Result:=EncodeDateTime(Year,Time.wMonth,1,Time.wHour,Time.wMinute,Time.wSecond,0); IF Time.wDay=5 THEN BEGIN Result:=DateOf(EndOfTheMonth(Result))+TimeOf(Result); WHILE PRED(DayOfWeek(Result))<>Time.wDayOfWeek DO Result:=IncDay(Result,-1) END ELSE BEGIN WHILE PRED(DayOfWeek(Result))<>Time.wDayOfWeek DO Result:=IncDay(Result); FOR I:=1 TO PRED(Time.wDay) DO Result:=IncWeek(Result) END END; BEGIN IF GetTimeZoneInformation(TZ)=TIME_ZONE_ID_UNKNOWN THEN Result:=FALSE ELSE BEGIN Start:=DecodeSwitchOverDate(Year,TZ.DaylightDate); Stop:=DecodeSwitchOverDate(Year,TZ.StandardDate); Result:=TRUE END END; FUNCTION StartOfDST(Year : Cardinal) : TDateTime; VAR Stop : TDateTime; BEGIN IF NOT GetDaylightSavingsSwitchOverDates(Year,Result,Stop) THEN Result:=0 END; FUNCTION EndOfDST(Year : Cardinal) : TDateTime; VAR Start : TDateTime; BEGIN IF NOT GetDaylightSavingsSwitchOverDates(Year,Start,Result) THEN Result:=0 END; 在我的PC(中欧时区)上循环使用2000年到2020年,我得到以下日期: DST in 2000: Sun 26 Mar 2000 02:00:00 through Sun 29 Oct 2000 03:00:00 DST in 2001: Sun 25 Mar 2001 02:00:00 through Sun 28 Oct 2001 03:00:00 DST in 2002: Sun 31 Mar 2002 02:00:00 through Sun 27 Oct 2002 03:00:00 DST in 2003: Sun 30 Mar 2003 02:00:00 through Sun 26 Oct 2003 03:00:00 DST in 2004: Sun 28 Mar 2004 02:00:00 through Sun 31 Oct 2004 03:00:00 DST in 2005: Sun 27 Mar 2005 02:00:00 through Sun 30 Oct 2005 03:00:00 DST in 2006: Sun 26 Mar 2006 02:00:00 through Sun 29 Oct 2006 03:00:00 DST in 2007: Sun 25 Mar 2007 02:00:00 through Sun 28 Oct 2007 03:00:00 DST in 2008: Sun 30 Mar 2008 02:00:00 through Sun 26 Oct 2008 03:00:00 DST in 2009: Sun 29 Mar 2009 02:00:00 through Sun 25 Oct 2009 03:00:00 DST in 2010: Sun 28 Mar 2010 02:00:00 through Sun 31 Oct 2010 03:00:00 DST in 2011: Sun 27 Mar 2011 02:00:00 through Sun 30 Oct 2011 03:00:00 DST in 2012: Sun 25 Mar 2012 02:00:00 through Sun 28 Oct 2012 03:00:00 DST in 2013: Sun 31 Mar 2013 02:00:00 through Sun 27 Oct 2013 03:00:00 DST in 2014: Sun 30 Mar 2014 02:00:00 through Sun 26 Oct 2014 03:00:00 DST in 2015: Sun 29 Mar 2015 02:00:00 through Sun 25 Oct 2015 03:00:00 DST in 2016: Sun 27 Mar 2016 02:00:00 through Sun 30 Oct 2016 03:00:00 DST in 2017: Sun 26 Mar 2017 02:00:00 through Sun 29 Oct 2017 03:00:00 DST in 2018: Sun 25 Mar 2018 02:00:00 through Sun 28 Oct 2018 03:00:00 DST in 2019: Sun 31 Mar 2019 02:00:00 through Sun 27 Oct 2019 03:00:00 DST in 2020: Sun 29 Mar 2020 02:00:00 through Sun 25 Oct 2020 03:00:00 但由于算法在列出的年份中从我的语言环境发生了变化,因此这些年中至少有一些是不正确的. 那么你的功能是: FUNCTION IsDaylightSavingTime(Input : TDateTime) : BOOLEAN; VAR Start,Stop : TDateTime; BEGIN Result:=GetDaylightSavingsSwitchOverDates(YearOf(Input),Stop) AND (Input>=Start) AND (Input<Stop) END; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |