AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Wann beginnt bei einem Jahr x die Sommerzeit ?
Thema durchsuchen
Ansicht
Themen-Optionen

Wann beginnt bei einem Jahr x die Sommerzeit ?

Ein Thema von hoika · begonnen am 10. Jan 2014 · letzter Beitrag vom 14. Jan 2014
Antwort Antwort
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.400 Beiträge
 
Delphi 12 Athens
 
#1

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?

  Alt 13. Jan 2014, 10:51
Schön ist ja, daß es nicht nur diese eine Regelung gibt und andere Länder die Sommerzeit zu einem anderem Termin beginnen und beenden.
In den USA machen die es z.B. 2-3 Wochen früher und Mexiko hinkt uns eine Woche hinterher.
Und einige Länder kennen solche eine schwachsinnige Zeitumstellung überhaupt nicht.

Da wäre es schon "intelligenter" wenn man aus der aktuellen Zoneninfo die passenden Daten verwendet.



Jetzt muß nur noch jemand kommen und schauen wie das eigentlich unter Mac, iOS, Android und Co. ausschaut,
denn diese WinAPI wird dort wohl nicht ganz funktionieren.


Wozu muß man das aber eigentlich wissen?
Mit zeitlichen Sprüngen muß man ja so oder so rechnen, angefangen beim Schaltjahr, bis hin zu den "heimlichen" Schaltsekunden,
über falsch gehende Uhren, welche urplöztlich syncronisiert werden und die unterschiedlichen Netzwerklatenzen zwischen PC und Zeitserver.
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (13. Jan 2014 um 12:15 Uhr)
  Mit Zitat antworten Zitat
Furtbichler
(Gast)

n/a Beiträge
 
#2

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?

  Alt 13. Jan 2014, 12:08
Da wäre es schon "intelligenter" wenn man aus der aktuellen Zoneninfo die passenden Daten verwendet.
Ja natürlich, aber wenn ich mir den Thread bisher anschaue, vor allen Dingen die eingangs erwähnten Wünsche sowie Definitionen der ptb, halte ich die weltweitgültige Version zwar für Endgeil, aber hier vielleicht etwas überkandidelt.

Wobei: Wenn man sie hat (und sie funktioniert und hat Unittests), ist Ruhe im Karton.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#3

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?

  Alt 13. Jan 2014, 13:51
Hier mal eine Variante zum Berechnen der variablen Tage

Der Aufruf erfolgt dann so
Delphi-Quellcode:
uses
  DayLightSaving;

var
  LStartDate, LEndDate : TDate;
begin
  LStartDate := TDayLightSaving.GetDate( 2014, 3, domLast, dowSunday );
  LEndDate := TDayLightSaving.GetDate( 2014, 10, domLast, dowSunday );
end;
Dabei habe ich bewusst nicht die Werte für wDayOfWeek oder wDay aus der Windows-API übernommen. Diese müssen also zunächst übersetzt werden in den richtigen ENUM-Wert für
Delphi-Quellcode:
    TDLSDayOfWeek = ( dowSunday, dowMonday, dowTuesday, dowWednesday, dowThursday, dowFriday, dowSaturyday );
    TDLSDayOfMonth = ( domFirst, domSecond, domThird, domForth, domLast );
Delphi-Quellcode:
unit DayLightSaving;

interface

{.$DEFINE USE_ANONYMOUS}

  uses
    DateUtils;

  type
    TDLSDayOfWeek = ( dowSunday, dowMonday, dowTuesday, dowWednesday, dowThursday, dowFriday, dowSaturyday );
    TDLSDayOfMonth = ( domFirst, domSecond, domThird, domForth, domLast );

{$IFDEF USE_ANONYMOUS}
    TDLSDateFunction = reference to function( const AYear, AMonth : Word; ADayOfWeek : TDLSDayOfWeek ) : TDate;
{$ELSE}

    IDLSDateFunction = interface
      ['{10C582CE-AE7E-4489-9D98-B147C37F6427}']
      function GetDate( const AYear, AMonth : Word; ADayOfWeek : TDLSDayOfWeek ) : TDate;
    end;

    TDLSNthDateFunction = class( TInterfacedObject, IDLSDateFunction )
    var
      FN : Integer;
    public
      constructor Create( N : Integer );
      function GetDate( const AYear : Word; const AMonth : Word; ADayOfWeek : TDLSDayOfWeek ) : TDate;
    end;

    TDLSLastDateFunction = class( TInterfacedObject, IDLSDateFunction )
    public
      function GetDate( const AYear : Word; const AMonth : Word; ADayOfWeek : TDLSDayOfWeek ) : TDate;
    end;
{$ENDIF}

    TDayLightSaving = class
    private const
      // System.DateUtils.DayOfTheWeek
      DayOfTheWeekValue : array [TDLSDayOfWeek] of Integer = ( DaySunday, DayMonday, DayTuesday, DayWednesday, DayThursday, DayFriday, DaySaturday );
      class function GetDateFromLastWeekDayOfMonth( const AYear, AMonth : Word; ADayOfWeek : TDLSDayOfWeek ) : TDate;
      class function GetDateFromNthWeekDayOfMonth( const AYear, AMonth : Word; ADayOfWeek : TDLSDayOfWeek; N : Integer ) : TDate;
{$IFDEF USE_ANONYMOUS}
      class var _DateFunctions : array [TDLSDayOfMonth] of TDLSDateFunction;
{$ELSE}
      class var _DateFunctions : array [TDLSDayOfMonth] of IDLSDateFunction;
{$ENDIF}
    protected
      class constructor Create;
    public
      class function GetDate( const AYear, AMonth : Word; ADayOfMonth : TDLSDayOfMonth; ADayOfWeek : TDLSDayOfWeek ) : TDate;
    end;

implementation

  uses
    SysUtils;

  { TDayLightSaving }

  class function TDayLightSaving.GetDateFromLastWeekDayOfMonth( const AYear, AMonth : Word; ADayOfWeek : TDLSDayOfWeek ) : TDate;
    begin
      Result := EncodeDate( AYear, AMonth, 1 ); // Erster Tag im Monat
      Result := IncMonth( Result, 1 ); // Erster Tag im Folgemonat
      Result := IncDay( Result, -1 ); // Letzer Tag im Monat
      Result := Result - ( DaysPerWeek + DayOfTheWeek( Result ) - DayOfTheWeekValue[ADayOfWeek] ) mod DaysPerWeek;
    end;

  class function TDayLightSaving.GetDateFromNthWeekDayOfMonth( const AYear, AMonth : Word; ADayOfWeek : TDLSDayOfWeek; N : Integer ) : TDate;
    begin
      Result := EncodeDate( AYear, AMonth, 1 ); // Erster Tag im Monat
      Result := Result + DaysPerWeek * ( N - 1 ) + ( DaysPerWeek - DayOfTheWeek( Result ) + DayOfTheWeekValue[ADayOfWeek] ) mod DaysPerWeek;
    end;

{$IFDEF USE_ANONYMOUS}

  class constructor TDayLightSaving.Create;
    begin
      TDayLightSaving._DateFunctions[domFirst] := function( const AYear, AMonth : Word; ADayOfWeek : TDLSDayOfWeek ) : TDate
          begin
            Result := GetDateFromNthWeekDayOfMonth( AYear, AMonth, ADayOfWeek, 1 );
          end;
      TDayLightSaving._DateFunctions[domSecond] := function( const AYear, AMonth : Word; ADayOfWeek : TDLSDayOfWeek ) : TDate
          begin
            Result := GetDateFromNthWeekDayOfMonth( AYear, AMonth, ADayOfWeek, 2 );
          end;
      TDayLightSaving._DateFunctions[domThird] := function( const AYear, AMonth : Word; ADayOfWeek : TDLSDayOfWeek ) : TDate
          begin
            Result := GetDateFromNthWeekDayOfMonth( AYear, AMonth, ADayOfWeek, 3 );
          end;
      TDayLightSaving._DateFunctions[domForth] := function( const AYear, AMonth : Word; ADayOfWeek : TDLSDayOfWeek ) : TDate
          begin
            Result := GetDateFromNthWeekDayOfMonth( AYear, AMonth, ADayOfWeek, 4 );
          end;
      TDayLightSaving._DateFunctions[domLast] := function( const AYear, AMonth : Word; ADayOfWeek : TDLSDayOfWeek ) : TDate
          begin
            Result := GetDateFromLastWeekDayOfMonth( AYear, AMonth, ADayOfWeek );
          end;
    end;

  class function TDayLightSaving.GetDate( const AYear, AMonth : Word; ADayOfMonth : TDLSDayOfMonth; ADayOfWeek : TDLSDayOfWeek ) : TDate;
    begin
      Result := _DateFunctions[ADayOfMonth]( AYear, AMonth, ADayOfWeek );
    end;
{$ELSE}

  class constructor TDayLightSaving.Create;
    begin
      TDayLightSaving._DateFunctions[domFirst] := TDLSNthDateFunction.Create( 1 );
      TDayLightSaving._DateFunctions[domSecond] := TDLSNthDateFunction.Create( 2 );
      TDayLightSaving._DateFunctions[domThird] := TDLSNthDateFunction.Create( 3 );
      TDayLightSaving._DateFunctions[domForth] := TDLSNthDateFunction.Create( 4 );
      TDayLightSaving._DateFunctions[domLast] := TDLSLastDateFunction.Create;
    end;

  class function TDayLightSaving.GetDate( const AYear, AMonth : Word; ADayOfMonth : TDLSDayOfMonth; ADayOfWeek : TDLSDayOfWeek ) : TDate;
    begin
      Result := _DateFunctions[ADayOfMonth].GetDate( AYear, AMonth, ADayOfWeek );
    end;

  { TDLSNthDateFunction }

  constructor TDLSNthDateFunction.Create( N : Integer );
    begin
      inherited Create;
      FN := N;
    end;

  function TDLSNthDateFunction.GetDate( const AYear, AMonth : Word; ADayOfWeek : TDLSDayOfWeek ) : TDate;
    begin
      Result := TDayLightSaving.GetDateFromNthWeekDayOfMonth( AYear, AMonth, ADayOfWeek, FN );
    end;

  { TDLSLastDateFunction }

  function TDLSLastDateFunction.GetDate( const AYear, AMonth : Word; ADayOfWeek : TDLSDayOfWeek ) : TDate;
    begin
      Result := TDayLightSaving.GetDateFromLastWeekDayOfMonth( AYear, AMonth, ADayOfWeek );
    end;

{$ENDIF}

end.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo (13. Jan 2014 um 16:58 Uhr) Grund: Jetzt auch für Delphi-Versionen ohne Anonyme Methoden :o)
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.277 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?

  Alt 13. Jan 2014, 17:28
Hallo,

ich hole mir nichts aus Windows.
Die Einstellungen werden vom Nutzer konfiguriert.
Da unser Produkt nur in good old Germany läuft, kann ich mir das leisten

Delphi-Quellcode:
function ErmitteltLetztenSonntagDesMonats(const AJahr, AMonat: Word): TDateTime;
const
  C_So = 7;
var
  tdtDatum : TDateTime;
begin
  Result := 0.0;

  { Start = letzter Tag des Monats }
  tdtDatum := EncodeDate(AJahr, AMonat, DaysInAMonth(AJahr, AMonat));
  if DayOfTheWeek(tdtDatum)=C_So then
  begin
    Result := tdtDatum;
  end
  else
  begin
    repeat
      tdtDatum := tdtDatum-1.0;
      if DayOfTheWeek(tdtDatum)=C_So then
      begin
        Result := tdtDatum;
        break;
      end;
    until False;
  end;
end { ErmitteltLetztenSonntagDesMonats } ;

procedure ErmittleSommerzeit(const AJahr: Word; out tdtStart, tdtEnde: TDateTime);
begin
  tdtStart := ErmitteltLetztenSonntagDesMonats(AJahr, 3);
  tdtEnde := ErmitteltLetztenSonntagDesMonats(AJahr, 10);
end { ErmittleSommerzeit } ;

{*
  Zeit nach GMT (Greenwich Mean Time) konvertieren
  in der Sommerzeit wird eine Stunde abgezogen

  @param  ADateTime  gegebenes Datum/Uhrzeit
  @return  GMT-Zeit
}

function DateTimeNachGMT(const ADateTime: TDateTime): TDateTime;
var
  wJahr : Word;
  wDummy : Word;
  tdtDatum : TDateTime;

  tdtSommerzeitStart : TDateTime;
  tdtSommerzeitEnde : TDateTime;
begin
  DecodeDate(ADateTime, wJahr, wDummy, wDummy);
  tdtDatum := DateOf(ADateTime);

  ErmittleSommerzeit(wJahr, tdtSommerzeitStart, tdtSommerzeitEnde);

  if (tdtDatum>=tdtSommerzeitStart) and
     (tdtDatum<=tdtSommerzeitEnde) then
  begin
    Result := IncHour(ADateTime, -1);
  end
  else
  begin
    Result := ADateTime;
  end;
end { DateTimeNachGMT } ;

procedure TTestCaseX.ErmittleSommerzeit;
var
  wJahr : Word;
  tdtStart : TDateTime;
  tdtEnde : TDateTime;
begin
  wJahr := 2000;
  MyDateUtils.ErmittleSommerzeit(wJahr, tdtStart, tdtEnde);
  Check(tdtStart=EncodeDate(2000,3,26));
  Check(tdtEnde=EncodeDate(2000,10,29));

  wJahr := 2014;
  MyDateUtils.ErmittleSommerzeit(wJahr, tdtStart, tdtEnde);
  Check(tdtStart=EncodeDate(2014,3,30));
  Check(tdtEnde=EncodeDate(2014,10,26));
end;

procedure TTestCaseX.DateTimeNachGMT;
var
  tdtDateTime1 : TDateTime;
  tdtDateTime2 : TDateTime;
  tdtDateTime3 : TDateTime;
begin
  { vor der Sommerzeit }
  tdtDateTime1 := EncodeDate(2000,3,25)+EncodeTime(22,0,0,0);
  tdtDateTime2 := MyDateUtils.DateTimeNachGMT(tdtDateTime1);
  Check(tdtDateTime2=tdtDateTime1);

  { erster Tag der Sommerzeit }
  tdtDateTime1 := EncodeDate(2000,3,26)+EncodeTime(22,0,0,0);
  tdtDateTime2 := MyDateUtils.DateTimeNachGMT(tdtDateTime1);
  tdtDateTime3 := EncodeDate(2000,3,26)+EncodeTime(21,0,0,0);
  Check(tdtDateTime2=tdtDateTime3);

  { vorletzter Tag der Sommerzeit }
  tdtDateTime1 := EncodeDate(2000,10,28)+EncodeTime(22,0,0,0);
  tdtDateTime2 := MyDateUtils.DateTimeNachGMT(tdtDateTime1);
  tdtDateTime3 := EncodeDate(2000,10,28)+EncodeTime(21,0,0,0);
  Check(tdtDateTime2=tdtDateTime3);

  { letzter Tag der Sommerzeit }
  tdtDateTime1 := EncodeDate(2000,10,29)+EncodeTime(22,0,0,0);
  tdtDateTime2 := MyDateUtils.DateTimeNachGMT(tdtDateTime1);
  tdtDateTime3 := EncodeDate(2000,10,29)+EncodeTime(21,0,0,0);
  Check(tdtDateTime2=tdtDateTime3);

  { erster Tag der Winterzeit }
  tdtDateTime1 := EncodeDate(2000,10,30)+EncodeTime(22,0,0,0);
  tdtDateTime2 := MyDateUtils.DateTimeNachGMT(tdtDateTime1);
  tdtDateTime3 := EncodeDate(2000,10,30)+EncodeTime(22,0,0,0);
  Check(tdtDateTime2=tdtDateTime3);
end { DateTimeNachGMT }  ;

Die Performance-"Problem" mit der Schleife sind verglichen mit dem Code,
der noch dahintersteckt, minimal.
Unit-Tests laufen über DUnit.
Ich habe das gekürzt:
Check(tdtDateTime2=tdtDateTime3); heisst eigentlich Check(tdtDateTime2=tdtDateTime3, 'Fehler XXX'); usw.

Heiko
Heiko

Geändert von hoika (13. Jan 2014 um 17:32 Uhr)
  Mit Zitat antworten Zitat
hathor
(Gast)

n/a Beiträge
 
#5

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?

  Alt 13. Jan 2014, 22:37
Ergebnis:

Beginn Sommerzeit: 30.3.2014
Beginn Winterzeit: 26.10.2014


Delphi-Quellcode:
procedure MM(s:string);
begin
  Form1.Memo1.lines.add(s);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
year, month, day : word;
begin
 year:= 2014;
 month:=3;
 day:= 31 - (5*year div 4 + 4) mod 7;
MM('Beginn Sommerzeit: '+inttostr(day)+'.'+inttostr(month)+'.'+inttostr(year));
 month:=10;
 day:= 31 - (5*year div 4 + 1) mod 7;
MM('Beginn Winterzeit: '+inttostr(day)+'.'+inttostr(month)+'.'+inttostr(year));
end;
  Mit Zitat antworten Zitat
Furtbichler
(Gast)

n/a Beiträge
 
#6

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?

  Alt 14. Jan 2014, 06:33
Deine Funktion liefert für die Jahre vor 1900 und ab 2100 ein falsches Ergebnis.
Meine Testfunktion;
Delphi-Quellcode:
Function DateIsLastSundayInMarch (aDate : TDateTime) : Boolean;
Begin
  Result := (DateUtils.DayOfTheWeek(aDate) = DaySunday) // It is a sunday
        and (MonthOf(aDate) = 3) // in march
        and (MonthOf(aDate+7) = 4); // and the following sunday is in april
End;
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.277 Beiträge
 
Delphi 10.4 Sydney
 
#7

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?

  Alt 14. Jan 2014, 06:59
Hallo Furtbichler,

meine ?


#Hathor
Beginn Sommerzeit: 30.3.2014
Beginn Winterzeit: 26.10.2014

Das ist doch aber richtig ?
Der letzte Sonntag im März,
der letzte Sonntag im Oktober.



Heiko
Heiko

Geändert von hoika (14. Jan 2014 um 07:02 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.400 Beiträge
 
Delphi 12 Athens
 
#8

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?

  Alt 14. Jan 2014, 08:34
Deine Funktion liefert für die Jahre vor 1900 und ab 2100 ein falsches Ergebnis.
1900 gab es noch keine Sommerzeit.
(erst ab 1916)
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:57 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz