Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Cross-Platform-Entwicklung (https://www.delphipraxis.net/91-cross-platform-entwicklung/)
-   -   Umrechnung UTC in lokale Zeit plattformabhängig? (https://www.delphipraxis.net/188351-umrechnung-utc-lokale-zeit-plattformabhaengig.html)

bra 23. Feb 2016 13:52

Umrechnung UTC in lokale Zeit plattformabhängig?
 
Ich bin mal wieder auf ein Problem gestoßen und weiss nicht, ob das ein Problem von Delphi ist oder der jeweiligen Plattform:

Folgender Code:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
const
  c1900T1700 = '1900-01-01T17:00:00.000Z';
  c1950T1700 = '1950-01-01T17:00:00.000Z';
  c1970T1700 = '1970-01-01T17:00:00.000Z';
  c1990T1700 = '1990-01-01T17:00:00.000Z';
  c2016T1700 = '2016-01-01T17:00:00.000Z';
  c1900T1700a = '1900-07-01T17:00:00.000Z';
  c1950T1700a = '1950-07-01T17:00:00.000Z';
  c1970T1700a = '1970-07-01T17:00:00.000Z';
  c1990T1700a = '1990-07-01T17:00:00.000Z';
  c2016T1700a = '2016-07-01T17:00:00.000Z';
  cGerman = 'dd.mm.yyyy hh:nn:ss';
begin
  Memo1.Lines.Clear;
  Memo1.Lines.Add('Winterzeit UTC');
  Memo1.Lines.Add(Format('%s -> %s', [c1900T1700, FormatDateTime(cGerman, ISO8601ToDate(c1900T1700))]));
  Memo1.Lines.Add(Format('%s -> %s', [c1950T1700, FormatDateTime(cGerman, ISO8601ToDate(c1950T1700))]));
  Memo1.Lines.Add(Format('%s -> %s', [c1970T1700, FormatDateTime(cGerman, ISO8601ToDate(c1970T1700))]));
  Memo1.Lines.Add(Format('%s -> %s', [c1990T1700, FormatDateTime(cGerman, ISO8601ToDate(c1990T1700))]));
  Memo1.Lines.Add(Format('%s -> %s', [c2016T1700, FormatDateTime(cGerman, ISO8601ToDate(c2016T1700))]));
  Memo1.Lines.Add('Sommerzeit UTC');
  Memo1.Lines.Add(Format('%s -> %s', [c1900T1700a, FormatDateTime(cGerman, ISO8601ToDate(c1900T1700a))]));
  Memo1.Lines.Add(Format('%s -> %s', [c1950T1700a, FormatDateTime(cGerman, ISO8601ToDate(c1950T1700a))]));
  Memo1.Lines.Add(Format('%s -> %s', [c1970T1700a, FormatDateTime(cGerman, ISO8601ToDate(c1970T1700a))]));
  Memo1.Lines.Add(Format('%s -> %s', [c1990T1700a, FormatDateTime(cGerman, ISO8601ToDate(c1990T1700a))]));
  Memo1.Lines.Add(Format('%s -> %s', [c2016T1700a, FormatDateTime(cGerman, ISO8601ToDate(c2016T1700a))]));

  Memo1.Lines.Add('Winterzeit lokal');
  Memo1.Lines.Add(Format('%s -> %s', [c1900T1700, FormatDateTime(cGerman, TTimeZone.Local.ToLocalTime(ISO8601ToDate(c1900T1700)))]));
  Memo1.Lines.Add(Format('%s -> %s', [c1950T1700, FormatDateTime(cGerman, TTimeZone.Local.ToLocalTime(ISO8601ToDate(c1950T1700)))]));
  Memo1.Lines.Add(Format('%s -> %s', [c1970T1700, FormatDateTime(cGerman, TTimeZone.Local.ToLocalTime(ISO8601ToDate(c1970T1700)))]));
  Memo1.Lines.Add(Format('%s -> %s', [c1990T1700, FormatDateTime(cGerman, TTimeZone.Local.ToLocalTime(ISO8601ToDate(c1990T1700)))]));
  Memo1.Lines.Add(Format('%s -> %s', [c2016T1700, FormatDateTime(cGerman, TTimeZone.Local.ToLocalTime(ISO8601ToDate(c2016T1700)))]));
  Memo1.Lines.Add('Sommerzeit lokal');
  Memo1.Lines.Add(Format('%s -> %s', [c1900T1700a, FormatDateTime(cGerman, TTimeZone.Local.ToLocalTime(ISO8601ToDate(c1900T1700a)))]));
  Memo1.Lines.Add(Format('%s -> %s', [c1950T1700a, FormatDateTime(cGerman, TTimeZone.Local.ToLocalTime(ISO8601ToDate(c1950T1700a)))]));
  Memo1.Lines.Add(Format('%s -> %s', [c1970T1700a, FormatDateTime(cGerman, TTimeZone.Local.ToLocalTime(ISO8601ToDate(c1970T1700a)))]));
  Memo1.Lines.Add(Format('%s -> %s', [c1990T1700a, FormatDateTime(cGerman, TTimeZone.Local.ToLocalTime(ISO8601ToDate(c1990T1700a)))]));
  Memo1.Lines.Add(Format('%s -> %s', [c2016T1700a, FormatDateTime(cGerman, TTimeZone.Local.ToLocalTime(ISO8601ToDate(c2016T1700a)))]));
end;
Liefert auf Windows, iOS und Android jeweils andere Ergebnisse (alle auf MEZ eingestellt):

Windows:
Winterzeit UTC
1900-01-01T17:00:00.000Z -> 01.01.1900 17:00:00
1950-01-01T17:00:00.000Z -> 01.01.1950 17:00:00
1970-01-01T17:00:00.000Z -> 01.01.1970 17:00:00
1990-01-01T17:00:00.000Z -> 01.01.1990 17:00:00
2016-01-01T17:00:00.000Z -> 01.01.2016 17:00:00
Sommerzeit UTC
1900-07-01T17:00:00.000Z -> 01.07.1900 17:00:00
1950-07-01T17:00:00.000Z -> 01.07.1950 17:00:00
1970-07-01T17:00:00.000Z -> 01.07.1970 17:00:00
1990-07-01T17:00:00.000Z -> 01.07.1990 17:00:00
2016-07-01T17:00:00.000Z -> 01.07.2016 17:00:00
Winterzeit lokal
1900-01-01T17:00:00.000Z -> 01.01.1900 18:00:00
1950-01-01T17:00:00.000Z -> 01.01.1950 18:00:00
1970-01-01T17:00:00.000Z -> 01.01.1970 18:00:00
1990-01-01T17:00:00.000Z -> 01.01.1990 18:00:00
2016-01-01T17:00:00.000Z -> 01.01.2016 18:00:00
Sommerzeit lokal
1900-07-01T17:00:00.000Z -> 01.07.1900 19:00:00
1950-07-01T17:00:00.000Z -> 01.07.1950 19:00:00
1970-07-01T17:00:00.000Z -> 01.07.1970 19:00:00
1990-07-01T17:00:00.000Z -> 01.07.1990 19:00:00
2016-07-01T17:00:00.000Z -> 01.07.2016 19:00:00


iOS:
Winterzeit UTC
1900-01-01T17:00:00.000Z -> 01.01.1900 17:00:00
1950-01-01T17:00:00.000Z -> 01.01.1950 17:00:00
1970-01-01T17:00:00.000Z -> 01.01.1970 17:00:00
1990-01-01T17:00:00.000Z -> 01.01.1990 17:00:00
2016-01-01T17:00:00.000Z -> 01.01.2016 17:00:00
Sommerzeit UTC
1900-07-01T17:00:00.000Z -> 01.07.1900 17:00:00
1950-07-01T17:00:00.000Z -> 01.07.1950 17:00:00
1970-07-01T17:00:00.000Z -> 01.07.1970 17:00:00
1990-07-01T17:00:00.000Z -> 01.07.1990 17:00:00
2016-07-01T17:00:00.000Z -> 01.07.2016 17:00:00
Winterzeit lokal
1900-01-01T17:00:00.000Z -> 01.01.1900 18:00:00
1950-01-01T17:00:00.000Z -> 01.01.1950 18:00:00
1970-01-01T17:00:00.000Z -> 01.01.1970 18:00:00
1990-01-01T17:00:00.000Z -> 01.01.1990 18:00:00
2016-01-01T17:00:00.000Z -> 01.01.2016 18:00:00
Sommerzeit lokal
1900-07-01T17:00:00.000Z -> 01.07.1900 18:00:00
1950-07-01T17:00:00.000Z -> 01.07.1950 18:00:00
1970-07-01T17:00:00.000Z -> 01.07.1970 18:00:00
1990-07-01T17:00:00.000Z -> 01.07.1990 19:00:00
2016-07-01T17:00:00.000Z -> 01.07.2016 19:00:00

Android:
Winterzeit UTC
1900-01-01T17:00:00.000Z -> 01.01.1900 17:00:00
1950-01-01T17:00:00.000Z -> 01.01.1950 17:00:00
1970-01-01T17:00:00.000Z -> 01.01.1970 17:00:00
1990-01-01T17:00:00.000Z -> 01.01.1990 17:00:00
2016-01-01T17:00:00.000Z -> 01.01.2016 17:00:00
Sommerzeit UTC
1900-07-01T17:00:00.000Z -> 01.07.1900 17:00:00
1950-07-01T17:00:00.000Z -> 01.07.1950 17:00:00
1970-07-01T17:00:00.000Z -> 01.07.1970 17:00:00
1990-07-01T17:00:00.000Z -> 01.07.1990 17:00:00
2016-07-01T17:00:00.000Z -> 01.07.2016 17:00:00
Winterzeit lokal
1900-01-01T17:00:00.000Z -> 01.01.1900 17:00:00
1950-01-01T17:00:00.000Z -> 01.01.1950 17:00:00
1970-01-01T17:00:00.000Z -> 01.01.1970 18:00:00
1990-01-01T17:00:00.000Z -> 01.01.1990 18:00:00
2016-01-01T17:00:00.000Z -> 01.01.2016 18:00:00
Sommerzeit lokal
1900-07-01T17:00:00.000Z -> 01.07.1900 17:00:00
1950-07-01T17:00:00.000Z -> 01.07.1950 17:00:00
1970-07-01T17:00:00.000Z -> 01.07.1970 18:00:00
1990-07-01T17:00:00.000Z -> 01.07.1990 19:00:00
2016-07-01T17:00:00.000Z -> 01.07.2016 19:00:00


Ist das jetzt ein Problem der Delphi-Routine TTimeZone.Local.ToLocalTime oder liefern hier die einzelnen Plattformen unterschiedliche Zeitzonen-Informationen zurück?

himitsu 23. Feb 2016 14:18

AW: Umrechnung UTC in lokale Zeit plattformabhängig?
 
Einige Systeme berücksichtigen halt, daß es die Sommerzeit da noch nicht gab und man sich den Sch*** erst später ausgedacht hatte.
Aber wenn man es dann ganz genau nimmt, müsste man auch noch den Standort berücksichten, denn das hängt von den Ländern ab.

Sir Rufo 23. Feb 2016 14:21

AW: Umrechnung UTC in lokale Zeit plattformabhängig?
 
Wir müssen erst einmal schauen, was denn die korrekte Zeit sein müsste.

Die Sommerzeit gab es in Deutschland 1916-1918, 1940-1949, 1980-heute.
(siehe https://de.wikipedia.org/wiki/Sommerzeit)

Somit liefert iOS die korrekten Werte für die angegebenen Zeiten.

Bei Android kann man vermuten, dass die Zeittabellen erst ab 1970 vorhanden sind.
Bei Windows ist da weiß der Geier was hinterlegt, aber für die aktuellen Zeiten sollte das stimmen.

(Zu der Problematik Sommerzeit vor 1970 siehe auch https://en.wikipedia.org/wiki/Tz_database)

bra 24. Feb 2016 10:11

AW: Umrechnung UTC in lokale Zeit plattformabhängig?
 
Ich habe es jetzt so gelöst, dass ich 1900-01-01 einfach durch 2000-01-01 ersetze, in der Hoffnung das das bei den meisten Zeitzonen keine Probleme macht. Hauptsächlich wird ja eh die europäische verwendet.

Aber da sieht man mal wieder die Tücken der plattformübergreifenden Entwicklung ;D

Sir Rufo 24. Feb 2016 10:22

AW: Umrechnung UTC in lokale Zeit plattformabhängig?
 
Ich verwende gerne einen eigenen Typen (record) dafür.

Der bekommt dann den ganzen lustigen SchnickSchnack verpasst um sehr einfach damit arbeiten zu können.

Dem kann man dann auch ein bestimmtes Verhalten unterjubeln (so wie du das jetzt machst oder wenn das doch nicht reichen sollte eben eine eigene Tabelle mit den Werten vor 1970) ohne dass der Rest der Anwendung geändert werden muss.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:49 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 by Thomas Breitkreuz