Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Wann beginnt bei einem Jahr x die Sommerzeit ? (https://www.delphipraxis.net/178490-wann-beginnt-bei-einem-jahr-x-die-sommerzeit.html)

hoika 10. Jan 2014 16:38

Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Hallo #,

aus ptb.de

Zitat:

Die mitteleuropäische Sommerzeit (MESZ) beginnt jeweils am letzten Sonntag im Monat März um 2 Uhr mitteleuropäischer Zeit. An diesem Tag werden die Uhren um 2 Uhr um eine Stunde auf 3 Uhr vorgestellt. Ziel der Zeitumstellung ist die bessere Ausnutzung der Tageshelligkeit.

Die Sommerzeit endet jeweils am letzten Sonntag im Monat Oktober um 3 Uhr mitteleuropäischer Sommerzeit. An diesem Tag werden die Uhren um 3 Uhr auf 2 Uhr zurückgestellt. Bei dieser doppelt erscheinenden Stunde wird die erste Stunde als 2A und die zweite Stunde als 2B bezeichnet.

Wir sind faul:

Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
var
  tz : TTimeZoneInformation;
  tdtTimeStart : TDateTime;
  tdtTimeEnd  : TDateTime;
  sText       : string;
begin
  GetTimeZoneInformation(tz);

  tz.DaylightDate.wYear := 2014;
  tz.StandardDate.wYear := 2014;

  tdtTimeStart := SystemTimeToDateTime(tz.DaylightDate);
  tdtTimeEnd  := SystemTimeToDateTime(tz.StandardDate);

  sText := 'Start: '+DateToStr(tdtTimeStart)+#13#10+
           'Ende: '+DateToStr(tdtTimeEnd);

  MessageBox(0, PChar(sText), '', 0);
end;
Aber: Es kommt 5.3. raus beim Start.

Ich könnte dass bissel auch per Funktion schreiben,
will ich aber nicht ;) oder muss ich doch ???


Heiko

hathor 10. Jan 2014 16:52

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
http://delphiforfun.org/Programs/Mat...cs/DSTCalc.htm

himitsu 10. Jan 2014 17:53

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Du solltest mal die Dokumentation lesen.
http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx

5.3. heißt nicht, daß es der 05.03. ist :!:

Denn Jahr = 0, also ist das ein relativer Datumswert.
Nur wenn Jahr einen Wert enthält, ist es ein absolutes Datum, was man so direkt verwenden kann.

05.03.0000 = 3. Monat und 5. "Woche"
wDayOfWeek gibt den Wochentag an und davon muß der 5 in diesem Monat verwendet werden.

Union 10. Jan 2014 18:06

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Auch nicht ganz. In DayLightDate bedeuten die Felder Folgendes:
  • wYear - Wenn 0, dann treffen die weiteren Regeln zu. Wenn <> 0 handelt es sich um ein festes Datum, z.b. einmalige Umstellung.
  • wHour - Umstellungsstunde
  • wMinute - Umstellungsminute
  • wDayOfWeek - Wochentag (0 = Sonntag)
  • wDay - Am wievielten durch wDayOfWeek angegebener Wochentag des Monats erfolgt die Umstellung(1-5, 5 bedeutet letzter)
Wichtig ist: Es handelt sich um eine reine Informationsstruktur über die Konfigurationsregelen der Zeitzone. Die Errechnung eines konkreten Datums muß selber gemacht werden!

hoika 10. Jan 2014 18:08

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Hallo,

war ein langer Tag heute,
der erste Link klappt bei 2014 nicht mal mit dem Taschenrechner,
der zweite ist ja noch komplizierter ...
ich baue mir jetzt eine eigene Funktion.

Select StartSommerZeit From RDB$DataBase ...

Heiko

himitsu 10. Jan 2014 20:08

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
So?

siehe erstes IF im ConvertDate

Delphi-Quellcode:
uses
  Windows, SysUtils, DateUtils, Math;

type
  TTimeZoneInformationHelper = record helper for TTimeZoneInformation
  public const
    CurrentYear = 0;
    NextDates  = 1;
  private
    procedure ConvertDate(var Date: TSystemTime; IsDaylight, DoNextDates: Boolean; RelDate: TSystemTime);
    function GetDate(Index: Integer): TDateTime;
    function GetDateStr(Index: Integer): string;
  public
    procedure ReadInfo(Year: Word=NextDates; DoConvertDates: Boolean=True);
    procedure ConvertDates(DoNextDates: Boolean=False); overload;
    procedure ConvertDates(DoNextDates: Boolean; RelDate: TSystemTime); overload;

    property GetStandardDate: TDateTime index 0 read GetDate;
    property GetDaylightDate: TDateTime index 1 read GetDate;
    property GetStandardDateStr: string index 0 read GetDateStr;
    property GetDaylightDateStr: string index 1 read GetDateStr;
  end;

{ TTimeZoneInformationHelper }

procedure TTimeZoneInformationHelper.ConvertDate(var Date: TSystemTime; IsDaylight, DoNextDates: Boolean; RelDate: TSystemTime);
var
  NextZone: TTimeZoneInformation;
  NewDate: TDateTime;
begin
  if Date.wYear = 0 then begin
    Date.wYear := RelDate.wYear;
    if Date.wDay < 5 then
      Date.wDay := DayOf(EncodeDayOfWeekInMonth(Date.wYear, Date.wMonth, Date.wDay, IfThen(Date.wDayOfWeek = 0, 7, Date.wDayOfWeek)))
    else begin
      NewDate  :=      EncodeDayOfWeekInMonth(Date.wYear, Date.wMonth, 1,        IfThen(Date.wDayOfWeek = 0, 7, Date.wDayOfWeek));
      while MonthOf(NewDate) = MonthOf(IncWeek(NewDate)) do
        NewDate := IncWeek(NewDate);
      Date.wDay := DayOf(NewDate);
    end;
  end;
  if DoNextDates and (SystemTimeToDateTime(RelDate) > SystemTimeToDateTime(Date)) then begin
    NextZone.ReadInfo(RelDate.wYear + 1, True);
    if IsDaylight then
      Date := NextZone.DaylightDate
    else
      Date := NextZone.StandardDate;
  end;
end;

procedure TTimeZoneInformationHelper.ConvertDates(DoNextDates: Boolean);
var
  Current: TSystemTime;
begin
  GetLocalTime(Current);
  ConvertDates(DoNextDates, Current);
end;

procedure TTimeZoneInformationHelper.ConvertDates(DoNextDates: Boolean; RelDate: TSystemTime);
begin
  ConvertDate(Self.StandardDate, False, DoNextDates, RelDate);
  ConvertDate(Self.DaylightDate, True, DoNextDates, RelDate);
end;

function TTimeZoneInformationHelper.GetDate(Index: Integer): TDateTime;
begin
  if Index = 0 then
    Result := SystemTimeToDateTime(Self.StandardDate)
  else
    Result := SystemTimeToDateTime(Self.DaylightDate);
end;

function TTimeZoneInformationHelper.GetDateStr(Index: Integer): string;
begin
  Result := DateTimeToStr(GetDate(Index));
end;

procedure TTimeZoneInformationHelper.ReadInfo(Year: Word; DoConvertDates: Boolean);
begin
  if Year in [CurrentYear, NextDates] then begin
    if GetTimeZoneInformation(Self) = TIME_ZONE_ID_INVALID then
      RaiseLastOSError;
  end else
    if not GetTimeZoneInformationForYear(Year, nil, Self) then
      RaiseLastOSError;

  if DoConvertDates then
    ConvertDates(Year = NextDates);
end;
Delphi-Quellcode:
var
  TZI: TTimeZoneInformation;
begin
  TZI.ReadInfo;
  ShowMessage('Start: ' + TZI.GetStandardDateStr + sLineBreak + 'Ende: ' + TZI.GetDaylightDateStr);

Furtbichler 11. Jan 2014 10:24

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Wäre es möglich, das das so einfach geht?
Delphi-Quellcode:
Function AnfangDerSommerzeit(Jahr : Word) : TDateTime;
Begin
  result := EncodeDate(Jahr,4,1);
//  return result - DayOfWeek(Result); // Letzter Sonntag im März
  result := result - DayOfWeek(Result);
End;

Function EndeDerSommerzeit(Jahr : Word) : TDateTime;
Begin
  result := EncodeDate(Jahr,11,1);
//  return result - DayOfWeek(Result); // Letzter Sonntag im Oktober
  result := result - DayOfWeek(Result);
End;

Codix32 11. Jan 2014 12:15

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Zitat:

Zitat von Furtbichler (Beitrag 1243128)
Wäre es möglich, das das so einfach geht?
Delphi-Quellcode:
Function AnfangDerSommerzeit(Jahr : Word) : TDateTime;
Begin
  result := EncodeDate(Jahr,4,1);
  return result - DayOfWeek(Result); // Letzter Sonntag im März
End;

Function EndeDerSommerzeit(Jahr : Word) : TDateTime;
Begin
  result := EncodeDate(Jahr,11,1);
  return result - DayOfWeek(Result); // Letzter Sonntag im Oktober
End;


Hilfe Furtbichler,

was macht denn das 'return' da drin?
Ist das 'return' nicht eher was für C++ ?

Das erinnert mich irgendwie auch an Basic, aber ehrlich, ich verstehe die Funktion so nicht.

Ich habe Deine Funktion in meinem Delphi getestet und so geht sie dann:
Delphi-Quellcode:
Function TForm1.AnfangDerSommerzeit(Jahr : Word) : TDateTime;
Begin
   result := EncodeDate(Jahr,4,1);
   result:= (result - DayOfWeek(Result))+1; // Letzter Sonntag im März
End;

Function TForm1.EndeDerSommerzeit(Jahr : Word) : TDateTime;
Begin
   result := EncodeDate(Jahr,11,1);
   result:= (result - DayOfWeek(Result))+1; // Letzter Sonntag im Oktober
End;
Hm, da stellt sich mir noch die Frage, ob die Funktion zwei Resultate blitzschnell und fürs Auge unbemerkt liefert, oder ob das erste 'result' in der Funktion verbleibt...

Klaus01 11. Jan 2014 13:57

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Zitat:

Zitat von Codix32 (Beitrag 1243138)

Hm, da stellt sich mir noch die Frage, ob die Funktion zwei Resultate blitzschnell und fürs Auge unbemerkt liefert, oder ob das erste 'result' in der Funktion verbleibt...

Das erste result wird doch überschrieben.
Mit result wird ja auch nicht aus der Funktion herausgesprungen, daher zählt das was als letztes, bevor die Funktion verlassen wird, in result geschrieben wird.

Grüße
Klaus

Furtbichler 11. Jan 2014 15:26

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Zitat:

Zitat von Codix32 (Beitrag 1243138)
was macht denn das 'return' da drin?

:oops: C# verdorben, sorry.

Das 'result' ist einfach eine lokale Variable, die Du verwenden kannst. Wie Klaus01 schon richtig schrieb, entspricht sie dem Resultat. Eine Sprunganweisung ist mit der Zuweisung nicht verbunden.

Codix32 11. Jan 2014 17:34

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Zitat:

was macht denn das 'return' da drin?
C# verdorben, sorry.

Das 'result' ist einfach eine lokale Variable, die Du verwenden kannst. Wie Klaus01 schon richtig schrieb, entspricht sie dem Resultat. Eine Sprunganweisung ist mit der Zuweisung nicht verbunden.
Danke Furtbichler und Klaus01.

Union 11. Jan 2014 18:27

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Man kann return seit einiger Zeit auch in Delphi benutzen, als exit <Value>.

himitsu 11. Jan 2014 19:10

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Wer ist denn auf diese kranke Idee gekommen die schöne Delphisyntax mit dieser komischer C-Syntax zu verschandeln?

Furtbichler 11. Jan 2014 20:47

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Zitat:

Zitat von himitsu (Beitrag 1243205)
Wer ist denn auf diese kranke Idee gekommen ...?

Wie meinen, der Herr? Höre ich da etwa Neid auf eine richtige Programmiersprache (C#) in einer IDE, die nicht ständig abschmiert und Sprachelementen, die vollständig und korrekt umgesetzt sind? :mrgreen:

Um deine Frage zu beantworten (da dein Scrollrad ja defekt ist). Icke.

PS: Ach, Du hast das ja mit C verwechselt. Stimmt, das wäre dann wirklich *krank*.

himitsu 11. Jan 2014 21:10

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
C-Sprachen sind doch alle das Selbe :roll:

Wobei ich den meinte, der das in den Compiler reingebaut hat, bzw. der die Idee dazu hatte.

Furtbichler 11. Jan 2014 21:16

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Zitat:

Zitat von himitsu (Beitrag 1243218)
C-Sprachen sind doch alle das Selbe :roll:

Alles eine Frage der Gewohnheit. Mittlerweile finde ich Delphi old-school und umständlich (ggü C# und .NET). Im Vergleich zu C(++) natürlich nicht. Aber wir kommen vom Thema ab. Die Diskussion C vs. Delphi gabs ja grad vor kurzem.

himitsu 11. Jan 2014 21:50

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Joar, stell dir mal vor die sind dann irgendwann mal gleich, weil jeder alles vom Anderen geklaut hat ... dann hat man ja nix mehr zum Meckern.

Furtbichler 12. Jan 2014 12:49

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Zitat:

Zitat von himitsu (Beitrag 1243221)
Joar, stell dir mal vor die sind dann irgendwann mal gleich, weil jeder alles vom Anderen geklaut hat ... dann hat man ja nix mehr zum Meckern.

Das ist eine völlig neue Sichtweise. :thumb:

Codix32 12. Jan 2014 21:52

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
@Furtbichler,

die Funktion ist ungenau.

Für das Jahr 2018 kriege ich den 1.04.2018 als Sommerzeitbeginn,
weil der 1.04.2018 ein Sonntag ist.

Delphi-Quellcode:
Function AnfangDerSommerzeit(Jahr : Word) : TDateTime;
Begin
   result := EncodeDate(Jahr,4,1);
   result := (result - DayOfWeek(Result))+1;
End;

Sir Rufo 12. Jan 2014 22:17

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Zitat:

Zitat von Codix32 (Beitrag 1243339)
@Furtbichler,

die Funktion ist ungenau.

Für das Jahr 2018 kriege ich den 1.04.2018 als Sommerzeitbeginn,
weil der 1.04.2018 ein Sonntag ist.

Delphi-Quellcode:
Function AnfangDerSommerzeit(Jahr : Word) : TDateTime;
Begin
   result := EncodeDate(Jahr,4,1);
   result := (result - DayOfWeek(Result))+1;
End;

Es ist auch nur ein kleiner Fehler drin (das war der Intelligenztest :mrgreen:)
Delphi-Quellcode:
Function AnfangDerSommerzeit(Jahr : Word) : TDateTime;
Begin
   result := EncodeDate(Jahr,4,1) - 1; // letzter Tag im März, statt erster Tag im April :o)
   result := (result - DayOfWeek(Result))+1;
End;

Codix32 12. Jan 2014 22:45

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Zitat:

Zitat von Sir Rufo (Beitrag 1243345)
Zitat:

Zitat von Codix32 (Beitrag 1243339)
@Furtbichler,

die Funktion ist ungenau.

Für das Jahr 2018 kriege ich den 1.04.2018 als Sommerzeitbeginn,
weil der 1.04.2018 ein Sonntag ist.

Delphi-Quellcode:
Function AnfangDerSommerzeit(Jahr : Word) : TDateTime;
Begin
   result := EncodeDate(Jahr,4,1);
   result := (result - DayOfWeek(Result))+1;
End;

Es ist auch nur ein kleiner Fehler drin (das war der Intelligenztest :mrgreen:)
Delphi-Quellcode:
Function AnfangDerSommerzeit(Jahr : Word) : TDateTime;
Begin
   result := EncodeDate(Jahr,4,1) - 1; // letzter Tag im März, statt erster Tag im April :o)
   result := (result - DayOfWeek(Result))+1;
End;

Ups, danke Sir Rufo,

ich hab gerade so was gemacht und vom Aussehen her gefällt mir es nicht:
Delphi-Quellcode:
Function AnfangDerSommerzeit(Jahr : Word) : TDateTime;
Begin
 if DayOfweek(EncodeDate(Jahr,4,1)) > 1 then
   result := EncodeDate(Jahr,4,1)
 else
   result := EncodeDate(Jahr,3,31);

   result := (result - DayOfWeek(Result))+1;
End;

Furtbichler 13. Jan 2014 06:28

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Zitat:

Zitat von Codix32 (Beitrag 1243346)
Ups, danke Sir Rufo,

Dem schließe ich mich an.
Zitat:

ich hab gerade so was gemacht und vom Aussehen her gefällt mir es nicht:
Lass es doch so wie von Sir Rufo korrigiert.
Meine erste Version war übrigens:
Delphi-Quellcode:
Result := EncodeDate(Year,4,1);
Repeat
  Result := Result - 1;
Until DayOfWeek(Result)=1;
Ich persönlich finde die Schleife leichter verständlich: Nimm den 1.April und zähle dann Rückwärts bis zum letzten Sonntag im März.

Nach kurzem Studium der DateUtils würde ich doch folgende Version nehmen:
Delphi-Quellcode:
Function LastSundayInMarch(Year : Word) : TDateTime;
Begin
  Result := EncodeDate(Year,4,1);
  Result := Result - DateUtils.DayOfTheWeek(Result);
End;
Gut zu wissen, das 'DayOfTheWeek' und 'DayOfWeek' unterschiedliche Ergebnisse liefern :wall:

hoika 13. Jan 2014 06:37

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Hallo,

ich habe das jetzt ähnlich umgesetzt,
also mit einer Schleife, die ab dem 31.3. solange rückwärts zählt,
bis ein Sonntag rauskommt (es sei denn, der 31.3. ist bereits ein Sonntag).

Und ich habe auch Unit-Tests dazugepackt ;)

Übrigens:
Das mit dem Result :=
gibt es meines Wissens bereits seit Turbo-Pascal.


Heiko

Furtbichler 13. Jan 2014 06:56

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Zitat:

Zitat von hoika (Beitrag 1243353)
Und ich habe auch Unit-Tests dazugepackt ;)

Zeig mal! :thumb:

Union 13. Jan 2014 08:32

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Damit die Funktion allgmein einsetzbar wird, sollten aber keine Konstanten für, Monat, Wochentag und Sequenz verwendet werden sondern die aus der TTimeZoneInformation Struktur.

himitsu 13. Jan 2014 09:11

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Zitat:

Zitat von Union (Beitrag 1243364)
Damit die Funktion allgmein einsetzbar wird, sollten aber keine Konstanten für, Monat, Wochentag und Sequenz verwendet werden sondern die aus der TTimeZoneInformation Struktur.

Du meinst so ähnlich, wie in #6 ?

Union 13. Jan 2014 09:14

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Ja. In den letzten Beispielen wurde ja immer konstant mit April, Sonntag und "letzter" gearbeitet.

himitsu 13. Jan 2014 10:51

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
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.

Furtbichler 13. Jan 2014 12:08

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Zitat:

Zitat von himitsu (Beitrag 1243399)
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.

Sir Rufo 13. Jan 2014 13:51

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
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
Delphi-Quellcode:
wDayOfWeek
oder
Delphi-Quellcode:
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.

hoika 13. Jan 2014 17:28

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
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

hathor 13. Jan 2014 22:37

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
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;

Furtbichler 14. Jan 2014 06:33

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
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;

hoika 14. Jan 2014 06:59

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
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

himitsu 14. Jan 2014 08:34

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Zitat:

Zitat von Furtbichler (Beitrag 1243558)
Deine Funktion liefert für die Jahre vor 1900 und ab 2100 ein falsches Ergebnis.

1900 gab es noch keine Sommerzeit.
(erst ab 1916)


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:44 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz