Kürzlich stolperte ich über folgende Bug-Meldung in Joda-Time, einer vielgelobten Datums- und Zeitbibliothek für Java. Da konnte jemand eine von Microsoft Outlook stammende Zeitzonen-ID mit dem String-Inhalt “W. Europe Standard Time” nicht in Joda verarbeiten, während laut Autor angeblich die Verarbeitung mit der im JDK eingebauten traditionellen java.util.Calendar-Bibliothek funktionierte.
Explizit zum Anschauen, Folgende Calendar-Joda-Brücke sollte gehen:
Calendar calStart = Calendar.getInstance(getTimeZone());
calStart.setTime(startDate.toDate());
return new DateTime(calStart);
Während hingegegen Joda so abbricht:
return startDate.withZone(DateTimeZone.forTimeZone(getTimeZone()));
-> “The datetime zone id ‘W. Europe Standard Time’ is not recognised”
Die Antwort von Stephen Colebourne, dem Autor von Joda-Time und dem aktuellen Co-Spec-Leader von Threeten und des JSR-310, des designierten Nachfolgers von Joda-Time und java.util.Calendar, ließ natürlich nicht lange auf sich warten:
“W. Europe Standard Time” is not a real timezone id. They look like this -
http://joda-time.sourceforge.net/timezones.html
So, either the id you are using is manually created (some part of your code
is creating a SimpleTimeZone) or there is some other mechanism picking up
the id.To fix this, you need to use an ID recognized by Joda-Time, such as “WET”
(West Europe Time). If you can’t do that, you’ll have to keep using the
Calendar, or write a subclass of DateTimeZone that handles your zone.
Mit anderen Worten und auf Deutsch: Es war eine ungültige Zeitzonenkennung mit Verweis auf die unter der Joda-Zeitzonentabelle aufgelisteten unterstützten Kennungen. Entsprechend hat S. Colebourne das Bug-Ticket als “Invalid” (Ungültig) geschlossen. Preisfrage: Wer hat recht?
Zunächst erscheint in dieser Detailfrage die allernorts meist in Grund und Boden kritisierte java.util.Calendar-Bibliothek als der Gewinner, denn angeblich (und von S. Colebourne in seiner wahrscheinlich zu schnellen Antwort nicht bestritten) sollte Calendar mit einer erfolgreichen Verarbeitung daherkommen. Wirklich? Schauen wir uns die Sache doch näher an. Wenn “W. Europe Standard Time” scheinbar geht und wir uns vor Augen halten, daß diese Kennung immerhin von einem weltweit viel und erfolgreich genutzten Mail-Programm namens MS-Outlook stammt und damit eigentlich nicht falsch sein kann, dann sollte umgekehrt eine so sinnfreie Kennung wie “abc” von java.util.TimeZone abgelehnt werden, nicht wahr? Beispiel:
TimeZone tz1 =
TimeZone.getTimeZone(“W. Europe Standard Time”); // Outlook
TimeZone tz2 =
TimeZone.getTimeZone(“?”); // Was ist das? Eine gute Frage!
TimeZone tz3 =
TimeZone.getTimeZone(
“Ich bin keine Zeitzone, aber ein Hund – wauwau!”);
System.out.println(tz1);
System.out.println(tz2);
System.out.println(tz3);
Bricht dieses kleine Programm ab? NEIN! Was ist das Ergebnis? Wir erhalten folgende Konsolenausgaben:
sun.util.calendar.ZoneInfo[id="GMT",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]
sun.util.calendar.ZoneInfo[id="GMT",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]
sun.util.calendar.ZoneInfo[id="GMT",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]
Mit anderen Worten: Die java.util.Calendar-Bibliothek fabriziert jedesmal die gleiche Zeitzone, nämlich eine reine UTC-Zeitzone ohne irgendeinen Offset und ohne Sommerzeit-Winterzeit-Einstellungen. Das war mit Sicherheit nicht die Absicht des Bug-Autors. Vielmehr dürfte er die Zeitzone “Europe/Berlin” erwartet haben, bei der die Konsolenausgabe so aussähe:
sun.util.calendar.ZoneInfo[id="Europe/Berlin",offset=3600000,dstSavings=3600000,useDaylight=true,transitions=143,
lastRule=java.util.SimpleTimeZone[id=Europe/Berlin,offset=3600000,dstSavings=3600000,useDaylight=true,
startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,
endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]]
Oh je, jetzt bei einem zweiten Blick erscheint die java.util.Calendar/-TimeZone-Bibliothek als geradezu hinterhältig, leitet sie doch alle Beteiligten in die Irre und wiegt den Benutzer in falscher Sicherheit. Schuld ist hier ein Fallback-Mechanismus, indem eine Ersatz- oder Standardzeitzone gewählt wird, wenn die vom Benutzer angegebene Zeitzonenkennung nicht erkannt wird. Es ist übel, und Joda-Time erscheint auch hier wie so oft als Gewinner im Vergleich mit dem JDK, wird der Benutzer wenigstens informiert, daß irgendetwas mit seinen Angaben nicht stimmt.
Soweit der zweite Blick. Gibt es noch einen dritten Blick? Ja! Zwei Fakten geben zu denken. Erstens ist ein Programmabbruch wie von Joda-Time immer etwas unschön und sollte nur dann akzeptabel sein, wenn es für das Programm wirklich keinen Ausweg mehr gibt. Zweitens ist die Kennung “W. Europe Standard Time” keineswegs sinnfrei, ist sie doch immerhin eine reguläre Ausgabe eines Standard-Programms wie Microsoft Outlook. Was hat es damit genau auf sich?
Zeitzonenkennungen wie “Europe/Berlin” stammen von der von Arthur David Olson und Paul Eggert entwickelten Zeitzonendatenbank TZDB (die jetzt von IANA verwaltet wird). Diese Zeitzonendatenbank wird von den allermeisten Akteuren im Internet verwendet – mit Ausnahme von Microsoft! Generell muß man sagen, daß Zeitzonenkennungen und auch Zeitzonennamen durch keinen internationalen Standard oder durch irgendein Abkommen geregelt sind. Das ist schlecht für Entwickler. Microsoft hat tatsächlich seine eigenen Windows-Zeitzonenkennungen erfunden (und es ist sein gutes Recht, denn es gibt ja leider keinen Standard hierfür).
Schon vielfach haben Java-Entwickler die fehlende Unterstützung von Java für solche Windows-Zeitzonenkennungen in diversen Bug-Tickets moniert, zum Beispiel 4762673 oder 6501839. Aus diesen Tickets ist auch nicht ersichtlich, ob und wann Sun (jetzt Oracle) jemals eine Lösung anzubieten gedenkt. Dabei gibt es doch einen Ausweg, nämlich die Auswertung der CLDR-Datenbank (vom Unicode-Konsortium verwaltet), die eine Abbildung von Windows-Zeitzonenkennungen (und Länder-Codes) auf Olson-Zeitzonenkennungen enthält. Könnte das JDK (oder Joda-Time) das auswerten, wäre die Verarbeitung von ”W. Europe Standard Time” automatisiert und in der Regel ohne Programmabbruch möglich.
Nach diesem dritten Blick schneidet Joda-Time zwar immer noch besser als java.util.Calendar ab, erscheint aber leider nicht mehr in so rosigem Licht, was den fehlenden Ressourcen von S. Colebourne geschuldet sein dürfte. Es gibt also auch bei Zeitzonen, einem Paradegebiet von Joda/Threeten, größeren Verbesserungsbedarf.