Einzelnen Beitrag anzeigen

hoika

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

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?

  Alt 13. Jan 2014, 18: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 18:32 Uhr)
  Mit Zitat antworten Zitat