// Zum übergebenen Jahr Datum für Beginn und Ende der Sommerzeit ermitteln.
// Bei erfolgreicher Ermittlung ist der Rückgabewert True.
// In Start befindet sich das Datum für den Beginn der Sommerzeit,
// in Stop das Datum, an dem die Sommerzeit endet.
function SommerWinterOrientierung(Year: Cardinal;
var Start, Stop: TDateTime): Boolean;
var
// Zeitzohneninformationen des Betriebssystems.
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms725481%28v=vs.85%29.aspx
TZ: TTimeZoneInformation;
// Datumsübersetzung aus übergebenem Jahr und Systemzeitinformationen
// zu Beginn bzw. Ende der Sommerzeit aus den Zeitzohneninformationen
// des Betriebssystems.
function DecodeSwitchOverDate(Year: Cardinal;
const Time: TSystemTime): TDateTime;
var
I: Cardinal;
begin
// Ausgehend vom übergebenem Jahr und Zeitangaben, einen TDateTime-Wert erstellen.
// http://www.delphibasics.co.uk/RTL.asp?Name=EncodeDateTime
// Beispiel: EncodeDateTime(2017, 04 , 1, 2 , 10 , 30 , 0);
// Steht für 1. April 2017, 02:10:30,000 Uhr.
// Time enthält hier entweder den Beginn der Sommerzeit oder das Ende der Sommerzeit
// ohne eine konkrete Jahresangabe.
// Für Westeuropa sinngemäß: Sommerzeit: 5. Donnerstag im März, 2 Uhr.
// Winterzeit: 5. Donnerstag im Oktober, 3 Uhr.
// Die tatsächliche Zeitumstellung findet dann immer in der Nacht vom
// davorliegenden Sonntag auf Montag statt.
Result := EncodeDateTime(Year, Time.wMonth, 1, Time.wHour, Time.wMinute, Time.wSecond, 0);
// 02:00 Uhr am letzten Donnerstag im Oktober sieht wie folgt aus:
// wHour = 2, wMonth = 10, wDayOfWeek = 4, wDay = 5.
// [QUOTE="Microsoft"]
// Using this notation,
// specify 02:00 on the first Sunday in April as follows:
// wHour = 2, wMonth = 4, wDayOfWeek = 0, wDay = 1.
// Specify 02:00 on the last Thursday in October as follows:
// wHour = 2, wMonth = 10, wDayOfWeek = 4, wDay = 5.
// [/QUOTE]
// Ist der Wochentag der 5. Donnerstag im Monat?
if Time.wDay = 5
then
begin
// Datum zum Ende des Monats zum bisher ermittelten Datum
// plus die Uhrzeit aus dem ermittelten Datum.
Result := DateOf(EndOfTheMonth(Result)) + TimeOf(Result);
// Ist der Wochentag vor dem ermittelten Datum <> dem Wochentag zum
// Beginn bzw. Ende der Sommerzeit, dann wird solange ein Tag abgezogen,
// bis die Wochentage übereinstimmen.
while PRED(DayOfWeek(Result)) <> Time.wDayOfWeek
do
Result := IncDay(Result, -1)
end
else
begin
// Ist der Wochentag vor dem ermittelten Datum <> dem Wochentag zum
// Beginn bzw. Ende der Sommerzeit, dann wird solange ein Tag addiert,
// bis die Wochentage übereinstimmen.
while PRED(DayOfWeek(Result)) <> Time.wDayOfWeek
DO
Result := IncDay(Result);
// wDay ist das x. Vorkommen des Tages aus Time im Monat.
// Von 1 bis (x - 1) zum ermittelten Datum eine Woche addieren.
for I := 1
to PRED(Time.wDay)
do
Result := IncWeek(Result)
end
end;
begin
// Zeitzoneninformationen des Betriebssystems abfragen.
// Sofern keine gültigen Zeitzoneninformationen gefunden werden konnten,
// wird als Ergebnis False geliefert.
if GetTimeZoneInformation(TZ) = TIME_ZONE_ID_UNKNOWN
then
Result := false
else
begin
// Beginn der Sommerzeit für das aktuelle Jahr ermitteln.
Start := DecodeSwitchOverDate(Year, TZ.DaylightDate);
// Ende der Sommerzeit für das aktuelle Jahr ermitteln.
Stop := DecodeSwitchOverDate(Year, TZ.StandardDate);
// True zurückgeben, da die Ermittlung der gewünschten Daten erfolgreich war.
Result := true
end
end;
// Datum feststellen, an dem die Sommerzeit beginnt.
function StartOfDST(Year: Cardinal): TDateTime;
var
Stop: TDateTime;
begin
if not SommerWinterOrientierung(Year, Result, Stop)
then
Result := 0
// Wenn keine Ermittlung möglich 0 zurückgeben.
end;
// Datum feststellen, zu dem die Sommerzeit endet.
function EndOfDST(Year: Cardinal): TDateTime;
var
Start: TDateTime;
begin
if not SommerWinterOrientierung(Year, Start, Result)
then
Result := 0
// Wenn keine Ermittlung möglich 0 zurückgeben.
end;
// Abfragen, ob sich das übergebene Datum innerhalb der Sommerzeit befindet.
function IsDaylightSavingTime(Input: TDateTime): Boolean;
var
Start, Stop: TDateTime;
begin
Result := SommerWinterOrientierung(YearOf(Input), Start, Stop)
AND (Input >= Start)
AND (Input < Stop)
end;