我需要某种方法来确定某些TDateTime值是否在我的时区的“夏令时”范围内(在C#中,DateTime.IsDaylightSavingTime()方法也是如此)。

我知道在Delphi中没有类似的功能,因为Delphi TDateTime不包含有关时区的信息,但是我想有某种方法可以使用Win32 API进行此操作。

我看过Win32 API的GetTimeZoneInformationGetTimeZoneInformationForYear函数,但是我不太了解如何使用它们,因此我想向您寻求帮助。在此先感谢您提供任何提示。

编辑:

例子:

在我所在的时区(中欧),夏令时从今年开始
3月28日凌晨2点,到2010年10月31日凌晨3点结束。

我需要一个带有标题的函数:

function IsDaylightSavingTime(input: TDateTime): boolean;

如果输入日期介于2010年3月28日2:00和2010年10月31日3:00之间,则返回true;否则,返回false

(该示例仅适用于2010年,但我需要它可以正常工作所有年份。)

再一次,我知道仅保存在TDateTime中的信息是不够的,但是我认为使用某些Win32 API函数,我应该能够获取例如Windows设置中有关当前时区的信息。

最佳答案

这并不像听起来那么容易,因为:

1)在所有国家/地区,夏令时与标准时间之间的转换日期都不相同

2)夏令时和标准时间之间的转换日期对于同一国家/地区而言,并非历年来都是相同的算法(例如,在中欧,以前是4月的第一个星期日,IIRC,现在是3月的最后一个星期日)。从2007年开始,美国从4月的第一个星期日更改为3月的第二个星期日。

所以-简单的日期是不够的,您还需要地理位置。

但是,如果您可以接受这一事实,则将自己限制在可以根据当前ojirt_rstrong年(对于当前ojirr_rstrong区域设置(国家/地区))的 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),Start,Stop) AND (Input>=Start) AND (Input<Stop)
  END;

关于Delphi-等效于C#DateTime.IsDaylightSavingTime()方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3448983/

10-14 17:53
查看更多