思ったほど簡単ではありません。理由は次のとおりです。
1)DSTと標準時の間の切り替え日は、すべての国で同じではありません
2)DSTと標準時の間の切り替え日は、すべての年で同じ国の同じアルゴリズムではありません(たとえば、中央ヨーロッパでは、以前は4月の第1日曜日、IIRCでしたが、現在は3月の最終日曜日です)。2007年以降、米国は4月の第1日曜日から3月の第2日曜日に変更されました。
つまり、単純な日付では不十分であり、地理的な場所も必要になります。
ただし、実際に対応できる場合は、現在のロケール(国)の現在の年の現在のアルゴリズムから計算できる切り替え日に制限し、これは両方の日付で間違っている可能性があります。将来および過去の場合、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;