Zusammenfassung der Revisionen (neue Yuan-Probleme) nach Java-Version

Einführung

Der überarbeitete Yuan wurde am 1. Mai 2019 und der neue Yuan am 1. April als "Reiwa" angekündigt. ~~ Die Ankündigung des neuen Yuan ist für den 1. April vor einem Monat geplant ~~ ** (4/1 Überprüfung) ** Verwandte Artikel sind "Unterstützung neuer Yuan-Probleme in Java", aber Java SE 8 (im Folgenden einfach als Java 8 bezeichnet). Da die Datums- und Uhrzeit-API von nicht unterstützt wird und viele alte Informationen in anderen Blogs enthalten sind, habe ich beschlossen, sie erneut zusammenzufassen, um sie so umfassend und praktisch wie möglich zu gestalten.

** (3/24 Nachschrift) ** Der Blog-Beitrag von Oracle "[Eine neue (japanische) Ära für Java!]" (Https://blogs.oracle.com/java-platform-group/a-new-japanese) am 21. März 2019 (US-Zeit) -era-for-java) "(japanische Übersetzung) wurde veröffentlicht. Es wurde angekündigt, dass die für den 16. April 2019 (US-Zeit) geplante Update-Veröffentlichung die neue Yuan-Ausgabe unterstützen wird. In diesem Artikel wird erläutert, wie Sie so weit wie möglich damit umgehen, auch wenn Sie kein Upgrade durchführen können. ** (Bewertet am 27.04.) ** Oracle JDK 7u221, 8u211, 11.0.3, für das eine kommerzielle Lizenz erforderlich ist, wurde veröffentlicht, und OpenJDK 7u221, 8u212-b03, 11.0.3 + 7 spiegelt auch die Unterstützung der neuen Originalausgabe "Reiwa" wider. Dies wurde auch in Oracle JDK / OpenJDK 12.0.1 berücksichtigt, das derzeit die neueste Version ist und kein LTS ist (kurzfristiger Support). Daher sollte es möglich sein, ohne große Überlegungen damit umzugehen, indem anschließend ein Upgrade durchgeführt wird.

Annahme

** (Bewertet am 17.04.) **

Schlussfolgerung (Antwortpolitik)

Da es danach länger dauern wird, denke ich, dass die Standard-API-Antwortrichtlinie für Revisionen für jede Version wie folgt lautet. ** (Bewertet am 17.04.) **

** (Bewertet am 17.04.) ** Eigentlich nicht nur die Standard-API, sondern auch zum Beispiel "Drucken Sie im April (auch an Daten nach Mai) nicht die neue Originalausgabe! ) ”Usw. müssen möglicherweise unabhängig von den Geschäftsanforderungen implementiert werden, aber in diesem Artikel wird dies im Prinzip nicht behandelt.

Ausführungsbeispiel

Von der japanischen Kalenderkorrespondenz wollen wir grundsätzlich in der Lage sein, die Daten zu formatieren und zu analysieren, die wahrscheinlich häufig verwendet werden. ** (4/1 Bewertung) ** Da der neue Yuan als "Reiwa" und das Alphabet als "R" angekündigt wurde, haben wir ihn einschließlich der darauf basierenden Ausführungsbeispiele überprüft.

$Echo Reiwa| native2ascii
\u4ee4\u548c

Daher wird dies im Wesentlichen in {JRE_HOME} /lib/calendars.properties angegeben.

calendar.japanese.eras: \
	name=Meiji,abbr=M,since=-3218832000000;  \
	name=Taisho,abbr=T,since=-1812153600000; \
	name=Showa,abbr=S,since=-1357603200000;  \
	name=Heisei,abbr=H,since=600220800000;   \
	name=\u4ee4\u548c,abbr=R,since=1556668800000

java.util.Date/Calendarを使った例

Es kann gesagt werden, dass es sich um eine traditionelle [schwer zu verwendende Implementierung] handelt (https://www.coppermine.jp/note/2019/01/java-util-date/) java.util.Date. com / javase / jp / 8 / docs / api / java / util / Date.html) und java.util.Calendar Ein Beispiel für die Verwendung von (/util/Calendar.html) lautet wie folgt.

DateCalendarTest.java


import java.text.*;
import java.util.*;

public class DateCalendarTest {

	public static void main(String... args) throws ParseException {
		Locale locale = new Locale("ja", "JP", "JP");
		DateFormat kanjiFormat = new SimpleDateFormat("GGGGy Jahr M Monat d Tag", locale);
		DateFormat asciiFormat = new SimpleDateFormat("Gyy.MM.dd", locale);

		//Ausgabe des aktuellen Datums
		Calendar now = Calendar.getInstance();
		System.out.println(kanjiFormat.format(now.getTime()));
		System.out.println(asciiFormat.format(now.getTime()));

		Calendar cal = Calendar.getInstance();
		cal.clear();

		//Datumsausgabe vor Überarbeitung
		cal.set(2019, Calendar.APRIL, 30, 23, 59, 59);
		Date lastHeiseiDate = cal.getTime();
		System.out.println(kanjiFormat.format(lastHeiseiDate));
		System.out.println(asciiFormat.format(lastHeiseiDate));

		//Datumsausgabe nach Überarbeitung
		cal.set(2019, Calendar.MAY, 1, 0, 0, 0);
		Date firstNewEraDate = cal.getTime();
		System.out.println(kanjiFormat.format(firstNewEraDate));
		System.out.println(asciiFormat.format(firstNewEraDate));

		//Nicht strenge Datumsanalyse
		System.out.println(kanjiFormat.parse("1. Mai 2019"));
		System.out.println(asciiFormat.parse("H31.05.01"));

		//Streng genommen tritt während der Analyse ein Fehler auf
		kanjiFormat.setLenient(false);
		try {
			kanjiFormat.parse("1. Mai 2019");
		} catch (ParseException e) {
			System.err.println(e.getMessage());
		}
		asciiFormat.setLenient(false);
		try {
			asciiFormat.parse("H31.05.01");
		} catch (ParseException e) {
			System.err.println(e.getMessage());
		}
	}
}

** (3/26 Nachschrift) ** Als Referenz ist "Gebietsschema (" ja "," JP "," JP ")" das Gebietsschema, das den japanischen Kalender darstellt. Dies ist jedoch ein [Sonderfall zur Aufrechterhaltung der Kompatibilität]. (https://docs.oracle.com/javase/jp/8/docs/api/java/util/Locale.html#special_cases_constructor) und aus Java 7 Locale.forLanguageTag (" ja-JP-u- ") Es kann als ca-japanese ") angegeben werden.

Das erwartete Verhalten zu diesem Zeitpunkt sollte wie folgt sein.

1. April 2019
H31.04.01
30. April 2019
H31.04.30
1. Mai, 1. Jahr von Reiwa
R01.05.01
Wed May 01 00:00:00 JST 2019
Wed May 01 00:00:00 JST 2019
Unparseable date: "1. Mai 2019"
Unparseable date: "H31.05.01"

Darüber hinaus ermöglicht die nicht strenge Datumsanalyse (Standard) sogar offensichtlich seltsame Datumsfelder wie "13 Monate" und "-1 Tag". Abhängig von den oben beschriebenen Geschäftsanforderungen kann DateFormat # setLenient (false) ) Oder Sie müssen den Bereich für jedes Feld separat überprüfen. Es wird____geben.

Sehen wir uns den Betrieb und die Vorsichtsmaßnahmen für jede Version an. Java 6 Grundsätzlich funktioniert jede Nebenversion wie erwartet. Selbst wenn "Gebietsschema (" ja "," JP "," JP ")" angegeben ist, kann das Kanji je nach Betriebssystem verstümmelt sein. Soweit ich es versucht habe, hat es richtig funktioniert, wenn die Windows-Spracheinstellung Japanisch war. Die Spracheinstellung von Windows ist auf Englisch eingestellt, und in der macOS X-Umgebung wird sie zu "31? 4? 30?". Dies scheint ein Problem bei der Ausgabe von Japanisch auf die Konsole im Allgemeinen zu sein, aber bitte seien Sie vorsichtig. Java 7, 8 Grundsätzlich funktioniert jede Nebenversion wie erwartet. ** (Bewertet am 27.04.) ** Offiziell unterstützt in Oracle JDK 7u221 / 8u211, OpenJDK 7u221, 8u212-b03 oder höher.

Java 9 oder höher

Durch Ändern mit JDK-8048123 wird calendars.properties ausgeblendet und die Systemeigenschaft jdk.calendar.japanese.supplemental.era festgelegt Es ist als Alternative konzipiert. Mach Folgendes:

$ java -Djdk.calendar.japanese.supplemental.era="name=Reiwa,abbr=R,since=1556668800000" DateCalendarTest

** (Bewertet am 27.04.) ** Ähnlich wie bei der später beschriebenen Datums- und Uhrzeit-API ignoriert Java 11 und höher die oben genannten Systemeigenschaftsspezifikationen. Darüber hinaus werden Oracle JDK 11.0.3 und OpenJDK 11.0.3 + 7 oder höher offiziell unterstützt, sodass keine Spezifikation erforderlich ist.

Bei der Ausführung lautet das Ergebnis wie folgt.

1. April 2019
2019.04.01
30. April 2019
2019.04.30
1. Mai, 1. Jahr von Reiwa
R01.05.01
Wed May 01 00:00:00 JST 2019
Exception in thread "main" java.text.ParseException: Unparseable date: "H31.05.01"
        at java.base/java.text.DateFormat.parse(DateFormat.java:388)
        at DateCalendarTest.main(DateCalendarTest.java:33)

Du hast eine Ausnahme. In der vorherigen Ausgabe ist der Teil, der "H31.04.30" sein sollte, "2019.04.30". ("R01.05.01" mit explizit angegebenen Systemeigenschaften wird ausgegeben)

** (1/8 Bewertung) ** ~~ Ich habe Java 12-ea + 25 und 13-ea + 1 ausprobiert (Early Access zeigt die Build-Nummer an), aber das Ergebnis ist das gleiche, also [Als Fehler melden](https://bugreport.java .com / bugreport /), aber derzeit in einem Format wie "NYY.MM.DD" (JIS X 0301-Notation) % 97% A5% E6% 9C% AC_ (JIS_X_0301))) ist [SimpleDateFormat](https://docs.oracle.com/javase/jp/8/docs/api/java/text/SimpleDateFormat] nach Java 9 Es ist besser zu denken, dass .html) nicht formatiert und analysiert werden kann. ~~ ~~ Es gibt kein Problem, wenn Sie nur das Kanji der ursprünglichen Ausgabe verwenden. Die Verwendung der folgenden Datums- und Uhrzeit-API kann vorerst eine Problemumgehung sein. ~~ "[[JDK-8216204] Falsches SimpleDateFormat-Verhalten mit dem japanischen imperialen Kalender](https://bugs.openjdk.java.net/browse/JDK-8216204?focusedCommentId=14234290&page=com.atlassian.jira.plugin.system.issuetabpanels: Ich habe einen Kommentar in comment-tabpanel # comment-14234290) "erhalten, aber es war kein Fehler, sondern eine Spezifikationsänderung von Java 9. Wenn die Ausgabe mit Java 8 oder früher identisch sein soll, können Sie die Systemeigenschaft java.locale.providers auf "COMPAT, CLDR" setzen.

$ java -Djava.locale.providers=COMPAT,CLDR -Djdk.calendar.japanese.supplemental.era="name=Reiwa,abbr=R,since=1556668800000" DateCalendarTest

** (1/13 Nachschrift) ** CLDR ist in Java 8 standardmäßig nicht aktiviert und die Kompatibilitätseinstellung lautet -Djava.locale.providers = COMPAT, SPI. -3704069.html # JDK-8008577). Wenn Sie also interessiert sind, können Sie es als solches festlegen.

Referenzinformationen

Beispiel mit Datums- und Uhrzeit-API

Die in Java 8 eingeführte Datums- und Uhrzeit-API [basiert auf ISO 8601](https: //www.coppermine) ersetzt oder migriert die alten java.util.Date und java.util.Calendar. .jp / note / 2019/01 / basis-of-iso8601 /). Ein Beispiel dafür ist wie folgt. ** (6/15 Bewertung) **

DateAndTime8Test.java


import java.util.Locale;
import java.time.LocalDate;
import java.time.chrono.*;
import java.time.format.*;

public class DateAndTime8Test {

	public static void main(String... args) {
		DateTimeFormatter kanjiFormat = DateTimeFormatter.ofPattern("GGGGy Jahr M Monat d Tag", Locale.JAPAN);
		DateTimeFormatter asciiFormat = DateTimeFormatter.ofPattern("GGGGGyy.MM.dd", Locale.JAPAN);

		//Ausgabe des aktuellen Datums
		JapaneseDate today = JapaneseDate.now();
		System.out.println(kanjiFormat.format(today));
		System.out.println(asciiFormat.format(today));

		//Datumsausgabe vor Überarbeitung
		JapaneseDate lastHeiseiDate = JapaneseDate.of(2019, 4, 30);
		System.out.println(kanjiFormat.format(lastHeiseiDate));
		System.out.println(asciiFormat.format(lastHeiseiDate));

		//Datumsausgabe nach Überarbeitung
		JapaneseDate firstNewEraDate = JapaneseDate.of(2019, 5, 1);
		System.out.println(kanjiFormat.format(firstNewEraDate));
		System.out.println(asciiFormat.format(firstNewEraDate));

		//Nicht strenge Datumsanalyse
		DateTimeFormatter kanjiParseFormat = kanjiFormat.withChronology(JapaneseChronology.INSTANCE)
				.withResolverStyle(ResolverStyle.LENIENT);
		System.out.println(kanjiParseFormat.parse("1. Mai 2019", LocalDate::from));
		//* In alphabetischer Schreibweise"y"Wenn Sie nicht mit einer Ziffer analysieren, beträgt die ursprüngliche Ausgabe bis zu 11 Jahre+Seit 100 Jahren behandelt
		DateTimeFormatter asciiParseFormat = DateTimeFormatter.ofPattern("GGGGGy.MM.dd", Locale.JAPAN)
				.withChronology(JapaneseChronology.INSTANCE)
				.withResolverStyle(ResolverStyle.LENIENT);
		System.out.println(asciiParseFormat.parse("H31.05.01", LocalDate::from));
		// System.out.println(asciiParseFormat.parse("R01.05.01", LocalDate::from)); //Erst nach offizieller Veröffentlichung

		//Streng genommen tritt während der Analyse ein Fehler auf
		kanjiParseFormat = kanjiParseFormat.withResolverStyle(ResolverStyle.STRICT);
		try {
			kanjiParseFormat.parse("1. Mai 2019");
		} catch (DateTimeParseException e) {
			System.err.println(e.getMessage());
		}
		asciiParseFormat = asciiParseFormat.withResolverStyle(ResolverStyle.STRICT);
		try {
			asciiParseFormat.parse("H31.05.01");
		} catch (DateTimeParseException e) {
			System.err.println(e.getMessage());
		}
	}
}

Nur für den Fall, es ist fest codiert wie JapaneseEra.HEISEI Dieser Teil kann erst in der Version unterstützt werden, in der die Revisionsunterstützung offiziell eingegeben wurde. ** (Bewertet am 27.9.) ** JapaneseEra.REIWA ist jetzt öffentlich Ist von Java 13](https://bugs.openjdk.java.net/browse/JDK-8193826) im September veröffentlicht. Das Gebietsschema kann übrigens in DateTimeFormatter weggelassen werden, hängt jedoch vom Betriebssystem und den Spracheinstellungen ab. Da "Heisei" anstelle von "Heisei" ausgegeben wird, wird empfohlen, dies explizit anzugeben.

** (6/15 Nachschrift) ** Bei alphabetischen Mustern wie "GGGGGyy.MM.dd" funktioniert die Formatierung korrekt, die Analyse muss jedoch nach April, als sie offiziell veröffentlicht wurde, für Daten im neuen Genre veröffentlicht werden. DateTimeParseException](https://docs.oracle.com/javase/jp/8/docs/api/java/time/format/DateTimeParseException.html) wird auftreten. Machen Sie außerdem nicht "GGGGGy.MM.dd" und ** "y" einstellig, wie von @ kazuki43zoo in den Kommentaren und Artikel erläutert. Bitte beachten Sie, dass bis zum 11. Jahr der ursprünglichen Ausgabe +100 Jahre ** behandelt werden. Obwohl dies nicht intuitiv ist, habe ich mit Experten bestätigt, dass dies kein Bug, sondern [IsoChronology] ist (https://docs.oracle.com/javase/jp/8/docs/api/java/time/). Es wurde der Schluss gezogen, dass dies wahrscheinlich darauf zurückzuführen ist, dass die Spezifikationen auf der Grundlage von chrono / IsoChronology.html formuliert wurden. Wenn eine strikte Analyse einschließlich der Anzahl der Ziffern erforderlich ist, ist es möglicherweise besser, reguläre Ausdrücke zusammen zu verwenden.

Das erwartete Verhalten zu diesem Zeitpunkt sollte wie folgt sein.

1. April 2019
H31.04.01
30. April 2019
H31.04.30
1. Mai, 1. Jahr von Reiwa
R01.05.01
2019-05-01
2019-05-01
Text '1. Mai 2019' could not be parsed: year, month, and day not valid for Era
Text 'H31.05.01' could not be parsed: year, month, and day not valid for Era

こちらも先のjava.util.Date/Calendarの例と同様に、解析には注意が必要です。 Der Standardwert ist ResolverStyle.SMART, "13. März" und "- Wir erlauben nicht "1 Tag", aber wir können "2020" usw. nicht analysieren, daher denke ich, dass es oft nicht den Geschäftsanforderungen entspricht. Hier werden nur die nicht strenge Datumsanalyse (LENIENT) und die strenge Datumsanalyse (STRICT) angegeben. Je nach Situation können jedoch detailliertere Überprüfungen erforderlich sein.

Sehen wir uns den Betrieb und die Vorsichtsmaßnahmen für jede Version an. Beachten Sie, dass die Systemeigenschaften von calendars.properties und jdk.calendar.japanese.supplemental.era von Java 9 oder höher auf dieselbe Weise wie im Beispiel mit java.util.Date / Calendar angegeben werden müssen.

Java 8 ** (Bewertet am 27.04.) ** Offiziell unterstützt von Oracle JDK 8u221 und OpenJDK 8u222-b03. 8GA~8u31

Exception in thread "main" java.lang.NullPointerException
        at java.time.chrono.JapaneseEra.privateEraFrom(JapaneseEra.java:271)
        at java.time.chrono.JapaneseDate.toPrivateJapaneseDate(JapaneseDate.java:502)
        at java.time.chrono.JapaneseDate.<init>(JapaneseDate.java:333)
        at java.time.chrono.JapaneseDate.now(JapaneseDate.java:197)
        at java.time.chrono.JapaneseDate.now(JapaneseDate.java:166)
        at DateAndTime8Test.main(DateAndTime8Test.java:13)

Plötzlich ist eine Ausnahme aufgetreten. ** (1/15 Überprüfung) ** ~~ Es scheint, dass der japanische Kalender zu Beginn der Java 8-Version nicht korrekt behandelt werden konnte. (NullPointerException tritt auch in JapaneseDate.of und JapaneseDate.from auf.) ~~ Zu Beginn der Java 8-Version ist es aufgrund eines Fehlers in JDK-8044671 aufgrund des Hinzufügens des ursprünglichen Problems zu calendars.properties nicht möglich, den japanischen Kalender korrekt zu behandeln. Es scheint, dass es enden wird.

8u40~8u151

1. April 2019
H31.04.01
30. April 2019
H31.04.30
1. Mai 31
301.05.01
2019-05-01
2019-05-01
Text '1. Mai 2019' could not be parsed: year, month, and day not valid for Era
Text 'H31.05.01' could not be parsed: year, month, and day not valid for Era

Ich möchte, dass es "1. Mai, 1. Jahr", aber "1. Mai, 31. Mai" oder "R01.05.01" ist, aber es ist "301.05.01". Es scheint, dass in calendars.properties verwendet wird, aber ansonsten kann es nicht richtig gelesen werden und die ursprüngliche Ausgabe wird als "3" behandelt. ** (1/15 Überprüfung) ** Aufgrund eines Fehlers in JDK-8054214 wurde das hinzugefügte ursprüngliche Problem als numerischer Wert ausgegeben. Und es scheint.

8u152~8u212

1. April 2019
H31.04.01
30. April 2019
H31.04.30
1. Mai, 1. Jahr von Reiwa
R01.05.01
2019-05-01
2019-05-01
Text '1. Mai 2019' could not be parsed: year, month, and day not valid for Era
Text 'H31.05.01' could not be parsed: year, month, and day not valid for Era

Die Ausgabe war wie erwartet! Um den japanischen Kalender mit der Datums- und Uhrzeit-API von Java 8 zu verwalten, ist es daher besser, so viel wie möglich eine neuere Version zu verwenden.

Es gibt jedoch eine Einschränkung. Im Beispielcode sind "DateTimeFormatter.ofPattern" ("GGGGy Jahr M Monat d Tag") und "G" vier Vollformat. Es wurde von java / time / format / TextStyle.html # FULL) angegeben und als "1. Mai, 1. Jahr von Reiwa" ausgegeben. Wenn bis zu 3 "G" vorhanden sind, wird dies als [Kurzformat] behandelt (https://docs.oracle.com/javase/jp/8/docs/api/java/time/format/TextStyle.html#SHORT). Es wird jedoch "R1 1. Mai" ausgegeben. (Kein Problem bis "Heisei")

8u221~ ** (6/15 Postscript) ** Offiziell unterstützt von Oracle JDK 8u221 und OpenJDK 8u222-b03. Wenn Sie den japanischen Kalender mit der Datums- und Uhrzeit-API verwenden, ist es daher grundsätzlich besser, spätere Versionen zu verwenden. Dies liegt daran, dass das Parsen mit alphabetischen Mustern wie "GGGGGy.MM.dd" für Daten im neuen Genre (z. B. "R01.05.01") nur dann korrekt funktioniert, wenn es später veröffentlicht wird.

Mal sehen, wie es in Java 9 und höher funktioniert. Mach Folgendes:

$ java -Djdk.calendar.japanese.supplemental.era="name=Reiwa,abbr=R,since=1556668800000" DateAndTime8Test

Java 9 Grundsätzlich funktioniert jede Nebenversion wie erwartet. Java 9 hat jedoch die gleichen Vorsichtsmaßnahmen wie das vorherige 8u152 ~. Geben Sie daher beim Schreiben in Kanji vier "GGGG" im DateTimeFormatter an.

Java 10 Grundsätzlich funktioniert jede Nebenversion wie erwartet. Selbst wenn der DateTimeFormatter auf 3 "G" gekürzt wird, wurde er so korrigiert, dass er als "1. Mai, 1. Jahr von Reiwa" ausgegeben wird.

Java 11, 12, 13 ** (Überprüft am 27. April) ** Offiziell unterstützt von Oracle JDK 11.0.3 / 12.0.1, OpenJDK 11.0.3 + 7 / 12.0.1, und die Implementierung von Platzhaltern wurde ersetzt, sodass das Folgende nicht gilt ..

1. April 2019
H31.04.01
30. April 2019
H31.04.30
Originalausgabe 1. Mai, 1 ..
N01.05.01
2019-05-01
2019-05-01
Text '1. Mai 2019' could not be parsed: year, month, and day not valid for Era
Text 'H31.05.01' could not be parsed: year, month, and day not valid for Era

Anstelle der in den Systemeigenschaften angegebenen "Rewa" und "R" werden "Gengo" und "N" ausgegeben. Dies liegt daran, dass es durch den Inhalt von Als Platzhalter implementiert überschrieben wird. (Umgekehrt ist dies auch dann der Fall, wenn Sie die Systemeigenschaft jdk.calendar.japanese.supplemental.era nicht angeben.) ** (Überprüft am 27.04.) ** Das neue Problem wurde überarbeitet, nachdem es in Oracle JDK 11.0.3 / 12.0.1 und OpenJDK 11.0.3 + 7 / 12.0.1 angekündigt und offiziell unterstützt wurde. Daher sind auch die folgenden Tipps nicht erforderlich.

Tipps (Tipps?)

Bisher wurde angenommen, dass die Systemeigenschaft jdk.calendar.japanese.supplemental.era auf "1556668800000" festgelegt ist, die voraussichtlich am 1. Mai 2019 beginnt. Wenn Sie jedoch ein Ziel auch für 1 Millisekunde angeben, wird es platziert. Ich konnte die Implementierung des Inhabers weiter überschreiben. ** (4/27 postscript) ** Wir haben einen Kommentar von @mazkasa erhalten und die Anzeige lautet CalendarNameProvider /CalendarNameProvider.html) ist ein unkomplizierter Ansatz, bei dem auch das Gebietsschema berücksichtigt wird. Die Implementierung des Platzhalters wird ebenfalls ersetzt.

Mal sehen, wie es in JShell funktioniert. Beginnen Sie wie folgt.

$ jshell -s -R-Djdk.calendar.japanese.supplemental.era="name=Reiwa,abbr=R,since=1556668800001"
-> import java.time.chrono.*
-> import java.time.format.*
-> var kanjiFormat = DateTimeFormatter.ofPattern("GGGGy Jahr M Monat d Tag", Locale.JAPAN)
-> var asciiFormat = DateTimeFormatter.ofPattern("GGGGGyy.MM.dd", Locale.JAPAN)
-> var firstNewEraDate = JapaneseDate.of(2019, 5, 1)
-> System.out.println(kanjiFormat.format(firstNewEraDate))
1. Mai, 1. Jahr von Reiwa
-> System.out.println(asciiFormat.format(firstNewEraDate))
R01.05.01
-> /exit

なお、旧来のjava.util.Date/Calendarではオーバーライドできず、プレースホルダ実装のままとなりました。(もちろん翌日の5月2日を指定すれば動きますが意味はありません) Die Datums- und Uhrzeit-API sollte die Spezifikation solcher unregelmäßigen Systemeigenschaften nicht berücksichtigen. Grundsätzlich ist es daher besser, nach Bekanntgabe des offiziellen Problems auf die Fixversion zu warten. Wenn Sie jedoch wirklich eine Version verwenden möchten, die nicht offiziell unterstützt wird (und Java 11 oder höher), handelt es sich um eine Erste-Hilfe-Maßnahme. Es kann möglich sein, es für zu verwenden. ** (Überprüft am 27.04.) ** Offiziell unterstützt von Oracle JDK 11.0.3 / 12.0.1 und OpenJDK 11.0.3 + 7 / 12.0.1, daher ist dies bei Verwendung dieser oder einer späteren Version nicht erforderlich.

Ergänzung

Über die Notation des ersten Jahres

Im vorherigen Ausführungsbeispiel wurde es als "Reiwa 1 Jahr" ausgegeben. Bei der Ausgabe in Kanji gibt es jedoch viele Fälle, in denen Sie so etwas wie "das erste Jahr von Reiwa" ausgeben möchten.

java.util.Date/Calendarの場合

Verwenden Sie im alten java.text.DateFormat den Datumsformatierer, der den FULL-Stil angibt. Es kann mit realisiert werden. ** (4/17 Nachschrift) ** Wenn Sie 4 oder mehr "y" wie "GGGGyyyy year" angeben, entspricht dies dem FULL-Stil.

FirstYearTest.java


import java.text.*;
import java.util.Calendar;
import java.util.Locale;

public class FirstYearTest {
	public static void main(String... args) throws ParseException {
		DateFormat fullFormat = DateFormat.getDateInstance(DateFormat.FULL, new Locale("ja", "JP", "JP"));
		Calendar cal = Calendar.getInstance();
		cal.clear();
		cal.set(2019, Calendar.MAY, 1);
		System.out.println(fullFormat.format(cal.getTime()));
		fullFormat.parse("8. Januar 1989"); //Es gibt kein Problem mit der Analyse, aber Heisei wird der Einfachheit halber verwendet.
	}
}

Wenn das oben Genannte ausgeführt wird, ist die Ausgabe so etwas wie "1. Mai, 1. Jahr von Reiwa". ** (Bewertet am 27.04.) ** In Java 11 und höher wurden, wie im oben gezeigten Ausführungsbeispiel, Platzhalter priorisiert und wurden "1. Mai, 1. Jahr der ursprünglichen Ausgabe", aber Oracle JDK 11.0.3 / 12.0.1, OpenJDK 11.0.3 Offiziell unterstützt in +7 / 12.0.1.

Wenn Sie den KURZEN Stil usw. angeben, ist das Jahr übrigens eine Ziffer als "R1.05.01", also JIS X 0301-Notation Es unterscheidet sich von% 9C% AC_ (JIS_X_0301)).

Für Datums- und Uhrzeit-API

** (1/13 Bewertung) ** Es ist möglich, den FULL-Stil mit der Datums- und Uhrzeit-API von Java 8 anzugeben, aber derzeit wird das "erste Jahr" leider nicht unterstützt, und die Ausgabe variiert je nach Version. ~~ JDK-8068571 unterstützt nicht "erstes Jahr", sondern [DateTimeFormatterBuilder](https: // docs) .oracle.com / javase / jp / 8 / docs / api / java / time / format / DateTimeFormatterBuilder.html) wird dies unterstützen. ** (Bewertet am 27.04.) ** Grundsätzlich ist Shaping ist Java 11 oder höher, Analyse ist Java 12 oder höher / blowse / JDK-8210633) wird unterstützt. ~~ Es wird wahrscheinlich nach 8u221 und 11.0.4 zurückportiert, die Mitte Juli 2019 veröffentlicht werden. ~~ Beide wurden mit Oracle JDK 8u211 / 11.0.3 und OpenJDK 8u212-b03 / 11.0.3 + 7 zurückportiert.

FirstYear8Test.java


import java.util.*;
import java.time.chrono.*;
import java.time.format.*;
import java.time.LocalDate;
import java.time.temporal.ChronoField;

public class FirstYear8Test {
	public static void main(String... args) {
		DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
		builder.appendText(ChronoField.ERA, TextStyle.FULL);
		builder.appendText(ChronoField.YEAR_OF_ERA, Collections.singletonMap(1L, "Ehemalige"));
		builder.appendLiteral("Jahr");
		builder.appendValue(ChronoField.MONTH_OF_YEAR);
		builder.appendLiteral("Mond");
		builder.appendValue(ChronoField.DAY_OF_MONTH);
		builder.appendLiteral("Tag");
		DateTimeFormatter formatter = builder.toFormatter(Locale.JAPAN)
				.withChronology(JapaneseChronology.INSTANCE);

		System.out.println(formatter.format(JapaneseDate.of(2019, 5, 1)));
		formatter.parse("8. Januar 1989", LocalDate::from);
	}
}

** (Überprüft am 27.04.) ** Aus diesem Grund gibt die Platzhalterimplementierung von Java 11 oder höher bei einfacher Ausführung so etwas wie "1. Mai, 1. Jahr der ursprünglichen Ausgabe" aus, aber Oracle JDK 11.0.3 Es wird offiziell von / 12.0.1, OpenJDK 11.0.3 + 7 / 12.0.1 unterstützt und "1. Mai, 1. Jahr von Reiwa" wird ausgegeben. In der alten Version kann die Datums- und Uhrzeit-API allein das "erste Jahr" nicht unterstützen, daher denke ich, dass es einfacher wäre, das Muster wie "1. Mai, 1. Jahr des Dekrets" durch einen regulären Ausdruck zu ersetzen. Ich werde.

** (3/24 Nachschrift) ** Das Obige gibt an, dass nur "Collections.singletonMap (1L," original ")" und das erste Jahr konvertiert werden sollen. Bei anderen als dem ersten Jahr (z. B. "2019") ist dies zum Zeitpunkt der Formgebung kein Problem, es ist jedoch erforderlich, diesen Betrag zum Zeitpunkt der Analyse zur Karte hinzuzufügen. Ändern Sie beispielsweise das relevante Teil wie folgt. (Es wird davon ausgegangen, dass die erforderliche Importanweisung separat angegeben wird.)

Map<Long, String> yearMap = LongStream.rangeClosed(1, 100).boxed()
        .collect(Collectors.toMap(Function.identity(), String::valueOf));
yearMap.put(Long.valueOf(1), "Ehemalige");
builder.appendText(ChronoField.YEAR_OF_ERA, yearMap);

Korrespondenz mit chinesischen Nummern

** (3/3 Nachschrift) ** Wenn Sie im vorherigen Codebeispiel den Teil von DateTimeFormatterBuilder ändern, können Sie andere chinesische Zahlen als das erste Jahr unterstützen. Wenn Sie das 100. Jahr der ursprünglichen Ausgabe vorerst unterstützen möchten, können Sie es wie folgt ersetzen.

// 0(〇)Wird in diesem Beispiel nicht verwendet, aber der Einfachheit halber eingestellt
String[] kanjiNumBase = {"〇", "einer", "zwei", "drei", "vier", "Fünf", "Sechs", "Sieben", "Acht", "Neun"};

// 1(einer)Ab 99(Neunundneunzig)Stellen Sie chinesische Zahlen auf ein
Map<Long, String> kanjiNumMap = new HashMap<>();
for (int num = 1; num < 100; num++) {
    if (num < 10) {
        kanjiNumMap.put(Long.valueOf(num), kanjiNumBase[num]);
        continue;
    }

    int tens = num / 10;
    int ones = num % 10;
    StringBuilder kanjiNum = new StringBuilder();
    if (tens > 1) {
        kanjiNum.append(kanjiNumBase[tens]);
    }
    kanjiNum.append("Zehn");
    if (ones > 0) {
        kanjiNum.append(kanjiNumBase[ones]);
    }
    kanjiNumMap.put(Long.valueOf(num), kanjiNum.toString());
}

//Das Jahr entspricht dem ersten Jahr und 100 Jahren
Map<Long, String> yearMap = new HashMap<>(kanjiNumMap);
yearMap.put(Long.valueOf(1), "Ehemalige");
yearMap.put(Long.valueOf(100), "hundert");

DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
builder.appendText(ChronoField.ERA, TextStyle.FULL);
builder.appendText(ChronoField.YEAR_OF_ERA, yearMap);
builder.appendLiteral("Jahr");
builder.appendText(ChronoField.MONTH_OF_YEAR, kanjiNumMap);
builder.appendLiteral("Mond");
builder.appendText(ChronoField.DAY_OF_MONTH, kanjiNumMap);
builder.appendLiteral("Tag");

DateTimeFormatter formatter = builder.toFormatter(Locale.JAPAN)
        .withChronology(JapaneseChronology.INSTANCE)
        .withResolverStyle(ResolverStyle.LENIENT);

Wenn es sich um Java 11 oder höher handelt, können Sie damit etwas wie "30. April 1991" ausgeben. Wenn es sich bei der Konvertierung in DateTimeFormatter zusätzlich zu normalen Daten wie "8. Januar 1989" und "30. April 1991" um Java 12 oder höher handelt, wird `withResolverStyle (ResolverStyle.LENIENT) Durch Angabe von "" wird es möglich, nicht existierende Daten wie "31. Dezember 1997" und "1. Januar 1945" zu analysieren.

Backport zu Java 8/11

** (Bewertet am 17.04.) ** Mit der Veröffentlichung am 16. April 2019 (US-Zeit) wurde ein Backport für Revisionen implementiert. Wenn Sie ein Upgrade auf eine spätere Version durchführen können, sollten Sie daher in der Lage sein, ohne große Überlegung auf die Revision zu reagieren.

Korrespondenz gemeinsamer Charaktere

** (Bewertet am 28.9.) ** In der neuen Ausgabe werden Zeichen wie "㍻" zugewiesen Unicode-Codepunkt "U + 32FF". , Java 13 oder höher von Unicode 12.1-Unterstützung, [Unicode-Normalisierung](https://docs.oracle.com/javase/ jp / 8 / docs / api / java / text / Normalizer.html) wird ebenfalls unterstützt, und Sie können dies mit dem folgenden Code überprüfen.

LigatureNormalizeTest.java


import java.text.Normalizer;

public class LigatureNormalizeTest {
	public static void main(String... args) {
		System.out.println("\u337b"); // ㍻
		System.out.println(Normalizer.normalize("\u337b", Normalizer.Form.NFKD));
		System.out.println(Normalizer.normalize("\u337b", Normalizer.Form.NFKC));

		System.out.println("\u32ff"); // ㋿ (Reiwas gemeinsamer Charakter)
		System.out.println(Normalizer.normalize("\u32ff", Normalizer.Form.NFKD));
		System.out.println(Normalizer.normalize("\u32ff", Normalizer.Form.NFKC));
	}
}

Das Ergebnis der Ausführung mit Oracle OpenJDK 13 ist wie folgt.

$ java -version
openjdk version "13" 2019-09-17
OpenJDK Runtime Environment (build 13+33)
OpenJDK 64-Bit Server VM (build 13+33, mixed mode, sharing)

$ java LigatureNormalizeTest
㍻
Heisei
Heisei
㋿
Reiwa
Reiwa

In meiner Umgebung macOS Mojave 10.14.6 konnte ich bestätigen, dass es normalisiert und korrekt angezeigt wird. Letztendlich hängt die Anzeige der Zeichen vom Betriebssystem-Update und der Schriftartenunterstützung ab.

Ändern Sie auch unter Windows 10 (1903) nach Erhalt eines Kommentars von @mazkasa die Codepage an der Eingabeaufforderung in "65001" (UTF-8) und fügen Sie "-Dfile.encoding = UTF-8" hinzu, um sie anzuzeigen. Es wurde getan. Das Ausführungsbeispiel bei Verwendung von Liberica JDK lautet wie folgt.

> chcp 65001
Active code page: 65001

> java -version
openjdk version "13-BellSoft" 2019-09-17
OpenJDK Runtime Environment (build 13-BellSoft+33)
OpenJDK 64-Bit Server VM (build 13-BellSoft+33, mixed mode, sharing)

> java -Dfile.encoding=UTF-8 LigatureNormalizeTest
㍻
Heisei
Heisei
㋿
Reiwa
Reiwa

Beachten Sie, dass die Unterstützung von Unicode 12.1, einschließlich der Silbenschrift, möglicherweise auf die LTS-Version JDK 8/11 zurückportiert wird, es ist jedoch unklar, was im Moment passieren wird.

Zusammenfassung

Die folgende Tabelle, einschließlich der Hinweise zu früheren Versionen, lautet wie folgt. ** (Bewertet am 18.04.) **

Ausführung java.util.Date/Calendar Date and Time API Allgemeine Bemerkungen / Notizen
6 ○:Kanji-Zeichen sind je nach Betriebssystem verstümmelt N/A (unvereinbar) Veröffentlichungen vor April 2019 sind Kalender.Eigenschaften müssen geändert werden
7 N/A (unvereinbar) Veröffentlichungen vor April 2019 sind Kalender.Eigenschaften müssen geändert werden
8 △:Wenn Sie die neueste Version verwenden ◎ Veröffentlichungen vor April 2019 sind Kalender.Die Eigenschaften müssen geändert werden. Die Notation für das erste Jahr wird separat implementiert
9 ◎:Die Alphabet-Notation ist Java.locale.Anbieter erforderlich ○:Kanji-Notation"GGGG"Und Musterspezifikation, Notation für das erste Jahr wird separat implementiert jdk.calendar.japanese.supplemental.Ära erforderlich
10 ◎:Die Alphabet-Notation ist Java.locale.Anbieter erforderlich ○:Die Notation für das erste Jahr wird separat implementiert jdk.calendar.japanese.supplemental.Ära erforderlich
11 oder später ○:Bei der Implementierung von Platzhaltern ist die alphabetische Notation Java.locale.Anbieter erforderlich ○:Unterstützt die Notation im ersten Jahr, die Implementierung von Platzhaltern kann überschrieben werden Wenn Sie nach April 2019 auf eine Version aktualisieren, sind alle ◎

** (Überprüft am 28.9.) ** Bitte verwenden Sie JDK 13, das im September 2019 veröffentlicht wurde, um die Unicode-Normalisierung des japanischen Zeichens "㋿" zu unterstützen.

abschließend

Die Hauptidee besteht darin, Ihr JDK / JRE nach der Überarbeitung auf die neueste Version zu aktualisieren. Wenn Sie jedoch Oracle JDK / JRE 8 verwenden, endeten die öffentlichen Updates für kommerzielle Benutzer im Januar 2019. Daher wird davon ausgegangen, dass möglicherweise zu Oracle Java SE-Abonnement oder einer anderen JDK-Distribution gewechselt werden muss. Getan werden. Wenn der neue Yuan früher angekündigt wurde (spätestens Anfang 2019), wurde er möglicherweise durch die öffentlichen Aktualisierungen im Januar 2019 offiziell überarbeitet, und es war möglicherweise nicht erforderlich, diesen Artikel zu schreiben. .. Es ist nicht auf Java beschränkt, aber ich hoffe, dass die Revisionsunterstützung für das System, das den japanischen Kalender verarbeitet, erfolgreich abgeschlossen wird.

Recommended Posts

Zusammenfassung der Revisionen (neue Yuan-Probleme) nach Java-Version
Zusammenfassung der Java-Unterstützung 2018
Zusammenfassung der neuen Funktionen von Java 12
Zusammenfassung der neuen Funktionen von Java 13
Zusammenfassung der neuen Funktionen von Java 10
Zusammenfassung der neuen Funktionen von Java 14
Ansicht über anderen Apps auf Android anzeigen (Zusammenfassung der Unterstützungsmethoden nach API-Version)
[Java] Grundlegende Zusammenfassung von Java, die nicht von Progate abgedeckt wird ~ Teil 1 ~
[Endgültige Version] Überprüfen Sie den Betrieb des japanischen Kalenders auf der Intensivstation, um das neue Yuan-Problem zu unterstützen.
[Java] Zusammenfassung der regulären Ausdrücke
[Java] Zusammenfassung der Operatoren (Operator)
Objektorientierte Zusammenfassung von Anfängern (Java)
Zusammenfassung der Grundlagen der Java-Sprache
Zusammenfassung der Java Math Klasse
[Java] Zusammenfassung der Steuerungssyntax
Zusammenfassung der Java-Fehlerverarbeitung
[Java] Zusammenfassung der Entwurfsmuster
[Java] Zusammenfassung der mathematischen Operationen
[Java] Grundlegende Zusammenfassung von Java, die nicht von Progate abgedeckt wird ~ Teil 2 ・ Liste ~
Zusammenfassung der von der Spliterator-Merkmalsmethode #java zurückgegebenen Werte
Wechseln Sie die von SDKMAN installierte Java-Version, wenn Sie Verzeichnisse verschieben
[Für Anfänger] Zusammenfassung des Java-Konstruktors
[Java Edition] Geschichte der Serialisierung
Zusammenfassung des Pakets [Java Silver Study]
[Java] Ausgabe von DateTimeFormatter durch FormatStyle
Java "Pass by Reference" Problemzusammenfassung
Java EE 8 (Jakarta EE 8) Zusammenfassung der neuen Funktionen
Zusammenfassung der objektorientierten Programmierung mit Java
[Java Silver] Zusammenfassung der Zugriffsmodifikatorpunkte
Zusammenfassung der internen Rookie-Lernsitzung [Java]
Memorandum des neuen Absolventen SES [Java-Grundlagen]
[java] Zusammenfassung des Umgangs mit char
Zusammenfassung des Docker-Verständnisses für Anfänger do ~ Docker-Compose ~
Ich habe das neue Yuan-Problem in Java ausprobiert
[Java] Persönliche Zusammenfassung der bedingten Anweisungen (grundlegend)
Installation des OMC APM Agent --JAVA Edition-
[Java] [Maven3] Zusammenfassung der Verwendung von Maven3
Einführung des Java-Programmierhandbuchs der neuen Generation (Java 10)
Java Zusammenfassung der häufig gesuchten Typkonvertierungen
Einführung des Java-Programmierhandbuchs der neuen Generation (Java 11)
Zusammenfassung von Java Math.random und Import (Kalender)
Einführung des Java-Programmierhandbuchs der neuen Generation (Java 12)
[java] Zusammenfassung des Umgangs mit Zeichenketten
Zusammenfassung der Java-Umgebungseinstellungen für mich [mac]
[Java] Dynamischer Methodenaufruf durch Reflektion des Aufzählungstyps (Aufzählung)
[Java] Zusammenfassung, wie Lambda-Ausdrücke weggelassen werden
[Java] Zugriff auf die signierte URL von s3 (signierte Version 2)
Zusammenfassung der neuen Funktionen, die in Deeplearning4J 1.0.0-beta4 hinzugefügt wurden
Memorandum des neuen Absolventen SES [Java Object Oriented Edition]
Probieren Sie Progate Free Edition [Java II]
[Hinweis] Java: Geschwindigkeit der Verarbeitung der Liste nach Zweck
Zusammenfassung des Docker-Verständnisses für Anfänger do ~ Docker-Run -p ~
Probieren Sie Progate Free Edition [Java I]