Streng genommen lautet die Antwort kurz und bündig: NEIN!
Der christliche gregorianische Kalender und der daraus abgeleitete ISO-Kalender sind im Hinblick auf Äras und Jahreszahlen nicht gleich. Was sind die Folgen für Java-Datumsbibliotheken?
Im entsprechenden ISO-Dokument findet sich nirgends ein Hinweis auf eine Ära wie AD = Anno Domini (auf Deutsch: nach Christi Geburt). Im Gegenteil werden ein Jahr 0 und auch negative Jahre ausdrücklich zugelassen, unter der Maßgabe, daß sich die Partner im Datenaustausch darauf geeinigt haben, die Schalttagsregeln des gregorianischen Kalenders proleptisch, also auch rückwirkend vor der Einführung des Kalenders 1582 anzuwenden. Ein Jahr 0 oder gar negative Jahre gibt es im christlichen Kalender nicht. Stattdessen gibt es nur positive Jahreszahlen UND eine Ära-Angabe wie v.Chr. oder n.Chr. Das ISO-Jahr 0 entspricht dann 1 v.Chr., das ISO-Jahr -1 dem historischen Jahr 2 v.Chr. und so weiter. Soweit, so klar.
Hieraus könnte der Schluß gezogen werden, daß eine Java-Implementierung eines ISO-konformen Datums keine Ära-Angaben unterstützen sollte. Das würde dem nicht-religiösen weltlichen Charakter der ISO-Definition am besten entsprechen. Für den christlichen Kalender könnte dann ein separater Datumstyp mit Ära-Unterstützung implementiert werden. Leider sieht die Verwendungspraxis anders aus. Erstens gibt es diejenigen Menschen, die aus religiösen Motiven noch das Ära-Konzept verwenden möchten (ausdrücklicher Bezug auf den postulierten Zeitpunkt von Jesu Geburt). Zweitens und noch wichtiger läßt sich die Tatsache nicht leugnen, daß der christliche Kalender vor Einführung des ISO-Standards in der Praxis die Norm war und daher viele historische Zeitangaben herumschwirren, die mindestens beim Formatieren und Parsen eine Unterstützung des Ära-Konzepts brauchen.
Im Zusammenhang mit historischen Datumsangaben gibt es noch eine Besonderheit: Je nach Land wurde der gregorianische Kalender zu verschiedenen Zeitpunkten eingeführt, oft als Ablösung des julianischen Kalenders (mit durch 4 teilbaren Schaltjahren von Cäsar eingeführt). Zum jeweiligen Umstellungszeitpunkt wurde zwar die Wochentagsregelung beibehalten, aber es verschwanden mehrere Tage. In Italien folgte bekanntlich auf Donnerstag, den 4.Oktober 1582 (julianisch) der Freitag mit dem gregorianischen Datum 15. Oktober 1582. In England erfolgte die Umstellung 1752 (da sogar mit einem 11-Tage-Sprung). Und so weiter… Zuletzt erfolgte 1949 in China die Umstellung auf den gregorianischen Kalender. Es ist unschwer zu sehen, daß ein ISO-Datum wie “1582-10-09″ im historischen Kontext nicht als “9. Oktober 1582 n.Chr.” formatiert werden darf, sondern vielmehr als “30. September 1582 n.Chr.” formatiert werden muß. Mit anderen Worten: Sobald in der Darstellung eine Ära auftaucht, muß das historisch korrekte Datum verwendet werden, nicht das ISO-Datum, wenn es sich um ein Datum vor der Einführung des gregorianischen Kalenders handelt.
Wie löst Java das Dilemma zwischen der weltlichen ISO-Definition und dem tatsächlichen religiösen oder historischen Gebrauch?
Das JDK mit der Klasse GregorianCalendar definiert überhaupt keinen ISO-Typ. Somit ist das beschriebene Dilemma nicht vorhanden (aber zu einem hohen Preis). Diese Klasse ist ein Hybrid aus julianischem und gregorianischem Kalender und bietet über die Methode “public void setGregorianChange(Date date)” die Möglichkeit an, den Umstellungszeitpunkt individuell zu setzen. Allerdings gibt es keine Möglichkeit, das auch länderspezifisch zu tun. Ähnlich verhalten sich das Unicode-Konsortium und die IBM-Bibliothek ICU4J. In den Unicode-Ressourcen fehlt ein echter ISO-Bezug. Stattdessen wird so getan, als ob ISO auch eine gregorianische Ära kennen würde. Eine Differenzierung zwischen ISO und christlichem oder historischem Kalender fehlt. Entsprechend ist auf den ersten Blick nicht von vornherein klar, ob eine Datumsangabe julianisch oder per ISO-Norm gemeint ist. Sehr verwirrend für Anwender!
Joda-Time definiert anders als das JDK einen eigenen Typ namens GJChronology. Das ist schon viel besser, da hier im Verwendungskontext klar ist, was Datumsangaben bedeuten. Einen kleinen Wermutstropfen gibt es aber noch: Die Joda-Klasse ISOChronology kennt trotzdem eine Ära. Dies mag zwar auf den ersten Blick diejenigen freuen, die eine Ära in der Darstellung sehen möchten, aber das geschieht zum Preis von historisch evtl. falschen Datumsangaben. Gefährlich, auch wenn die Joda-Dokumentation diesen Mangel klar darstellt und von der Verwendung im historischen Kontext abrät. Auch ist eine länderspezifische Konfiguration des Umstellungszeitpunkts nicht möglich.
Was macht Threeten (JSR 310)? Noch gibt es kein HistoricDate. Aber ein solcher Datumstyp ist angedacht und wird nach den neuesten Meldungen (Issue-Tracker auf GitHub) wohl erst für Java 9 realisiert werden. Im Prinzip ist es das gleiche Verfahren wie in Joda… Und auch die LocalDate-Klasse von Threeten, die als ISO-Datum deklariert wird, kennt eine Ära (Nachteile siehe Joda).
Welchen Weg wird mein ProjektTime4J einschlagen? Einen dritten Weg.
1. Es wird keinen separaten historischen Datumstyp geben (=> einfacheres API).
2. Die Klasse IsoDate wird an und für sich keine Ära kennen. Sie wird auch keinen gregorianischen Umstellungszeitpunkt verwalten, sondern nur von Jahr, Monat und Tag im proleptischen gregorianischen Kalender (ISO-Kontext) abhängig sein.
3. IsoDate wird eine lokale Erweiterung definieren, über die ein Anwender separat neben dem eigentlichen ISO-Datum ein historisches Datumsmodell abhängig vom Land erzeugen kann. Anschließend kann mit Hilfe des historischen Datumsmodells eine beliebige historisch korrekte Ausgabe des ISO-Datums erfolgen.
Dieses Verfahren bietet folgende Vorteile:
- Die meisten Verwender eines ISO-Datums brauchen sich nicht um Äras zu kümmern (und tun es auch nicht). Die IsoDate-Klasse hat einen klar weltlichen Charakter passend zum modernen Gebrauch.
- Christlich-religiös motivierte Menschen und Historiker werden trotzdem bedient, denn sobald sie in der Formatierung eines IsoDate-Objekts nach einer Ära fragen, erfolgt automatisch im Hintergrund die Erzeugung des passenden historischen Datumsmodells und die Umstellung auf eine historisch korrekte Ausgabe.
- Auch kann in der Formatierung für den gregorianischen Umstellungszeitpunkt eine Ländereinstellung berücksichtigt werden, die für die Sprachausgabe der Textelemente sowieso notwendig ist.
- Und zu guter Letzt kann die natürliche Ordnung von IsoDate rein zeitlich UND konsistent mit equals() bleiben, so daß einer Verwendung von IsoDate als Schlüssel in einer java.util.SortedMap oder in einem java.util.SortedSet nichts entgegensteht. Denn der gregorianische Umstellungszeitpunkt (englisch: cut-over) wird als Zustand nicht in IsoDate, sondern in einem separaten Objekt verwaltet. Die JDK-Klasse GregorianCalendar oder die Joda-GJChronology haben notwendig diesen Zustand intern und können deshalb entweder nicht mit einer java.util.TreeMap kooperieren oder definieren eine Sortierung, die nicht nur zeitlich ist!
Time4J beschreitet also gänzlich neue Pfade auch auf diesem Gebiet.