Résumé des révisions (nouveaux problèmes de yuan) par version Java

introduction

Le yuan révisé a été annoncé le 1er mai 2019 et le nouveau yuan a été annoncé le 1er avril sous le nom de «Reiwa». ~~ L'annonce du nouveau yuan est prévue pour le 1er avril, il y a un mois ~~ ** (avis 4/1) ** Les articles associés incluent "Correspondant au nouveau problème d'origine en Java", mais Java SE 8 (ci-après, simplement appelé Java 8) Comme il ne prend pas en charge l'API Date and Time de, et qu'il y a beaucoup d'anciennes informations dans d'autres blogs, j'ai décidé de le résumer à nouveau afin qu'il soit aussi complet et pratique que possible.

** (PostScript 3/24) ** Article de blog d'Oracle "[Une nouvelle ère (japonaise) pour Java!]" (Https://blogs.oracle.com/java-platform-group/a-new-japanese) le 21 mars 2019 (heure des États-Unis) -era-for-java) "(traduction en japonais) a été publié. Il a été annoncé que la mise à jour prévue pour le 16 avril 2019 (heure des États-Unis) prendra en charge le nouveau problème du yuan. Cet article explique comment y faire face autant que possible, même si vous ne pouvez pas mettre à niveau. ** (Révisé le 27/04) ** Oracle JDK 7u221, 8u211, 11.0.3, qui nécessite une licence commerciale, a été publié, et OpenJDK 7u221, 8u212-b03, 11.0.3 + 7 reflète également la prise en charge du nouveau numéro original "Reiwa". Il a également été reflété dans Oracle JDK / OpenJDK 12.0.1, qui est actuellement la dernière version et n'est pas LTS (support à court terme). Par conséquent, il devrait être possible de le traiter sans trop de considération en effectuant une mise à niveau après ces derniers.

supposition

** (Evalué le 17/04) **

Conclusion (politique de réponse)

Comme ce sera plus long après cela, je pense que la politique de réponse API standard pour les révisions sera la suivante pour chaque version. ** (Evalué le 17/04) **

--Java 6, 7 _ (corrigé après 7u221) _ --Modifier calendars.properties lors de l'utilisation de java.util.Date / Calendar --Java 8 _ (corrigé après Oracle JDK 8u211, OpenJDK 8u212-b03) _ --Modifier calendars.properties lors de l'utilisation de java.util.Date / Calendar

** (Evalué le 17/04) ** En fait, non seulement l'API standard, mais aussi, par exemple, "En avril (même après mai), n'imprimez pas le nouveau numéro original! ”, Etc., peut devoir être mis en œuvre de manière indépendante en fonction des besoins de l'entreprise, mais en principe, cet article ne le couvre pas.

Exemple d'exécution

De la correspondance du calendrier japonais, nous visons essentiellement à être en mesure de formater et d'analyser les dates qui sont susceptibles d'être couramment utilisées. ** (avis 4/1) ** Puisque le nouveau yuan a été annoncé comme "Reiwa" et l'alphabet comme "R", nous l'avons examiné, y compris des exemples d'exécution basés sur cela.

$echo Reiwa| native2ascii
\u4ee4\u548c

Par conséquent, ceci est essentiellement spécifié dans {JRE_HOME} /lib/calendars.properties.

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を使った例

On peut dire qu'il s'agit d'une implémentation traditionnelle difficile à utiliser [java.util.Date](https://docs.oracle. com / javase / jp / 8 / docs / api / java / util / Date.html) et java.util.Calendar Un exemple d'utilisation de (/util/Calendar.html) est le suivant.

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 année M mois j jour", locale);
		DateFormat asciiFormat = new SimpleDateFormat("Gyy.MM.dd", locale);

		//Sortie de la date actuelle
		Calendar now = Calendar.getInstance();
		System.out.println(kanjiFormat.format(now.getTime()));
		System.out.println(asciiFormat.format(now.getTime()));

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

		//Date de sortie avant révision
		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));

		//Sortie de date après révision
		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));

		//Analyse de date non stricte
		System.out.println(kanjiFormat.parse("1 mai 2019"));
		System.out.println(asciiFormat.parse("H31.05.01"));

		//Une erreur se produira strictement lors de l'analyse
		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 postscript) ** Pour référence, Locale (" ja "," JP "," JP ") est la locale qui représente le calendrier japonais, mais c'est un cas spécial pour maintenir la compatibilité, et depuis Java 7, Locale.forLanguageTag (" ja-JP-u- " Il peut être spécifié comme ca-japanese ").

Le comportement attendu à ce moment devrait être le suivant.

1 avril 2019
H31.04.01
30 avril 2019
H31.04.30
1er mai, 1ère année de 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"

En outre, une analyse de date non stricte (par défaut) autorisera même des champs de date manifestement étranges tels que "13 mois" et "-1 jour", donc en fonction des besoins commerciaux, comme décrit ci-dessus, DateFormat # setLenient (false) ) Ou vous devez vérifier la portée de chaque champ séparément. Il y aura.

Voyons le fonctionnement et les précautions pour chaque version. Java 6 En gros, toute version mineure fonctionne comme prévu. Cependant, même si Locale (" ja "," JP "," JP ") est spécifié, le kanji peut être brouillé selon le système d'exploitation. Autant que j'ai essayé, cela fonctionnait correctement lorsque le paramètre de langue de Windows était japonais. Le paramètre de langue de Windows est défini sur l'anglais, et dans l'environnement macOS X, il devient quelque chose comme «?? 31? 4? 30?». Cela semble être un problème lors de la sortie du japonais sur la console en général, mais soyez prudent. Java 7, 8 En gros, toute version mineure fonctionne comme prévu. ** (Révisé le 27/04) ** Officiellement pris en charge dans Oracle JDK 7u221 / 8u211, OpenJDK 7u221, 8u212-b03 ou version ultérieure.

Java 9 ou version ultérieure

En changeant avec JDK-8048123, calendars.properties disparaît et en définissant la propriété système jdk.calendar.japanese.supplemental.era Il est conçu pour être une alternative. Procédez comme suit:

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

** (Révisé le 27/04) ** Similaire à l'API Date et heure décrite plus loin, Java 11 et les versions ultérieures ignorent les spécifications de propriété système ci-dessus. De plus, Oracle JDK 11.0.3 et OpenJDK 11.0.3 + 7 ou version ultérieure sont officiellement pris en charge, aucune spécification n'est donc requise.

Une fois exécuté, le résultat sera le suivant.

1 avril 2019
2019.04.01
30 avril 2019
2019.04.30
1er mai, 1ère année de 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)

Vous avez une exception. En regardant la sortie avant cela, la partie qui devrait être "H31.04.30" est "2019.04.30". ("R01.05.01" avec les propriétés système explicitement spécifiées est sorti)

** (1/8 avis) ** J'ai essayé toutes les étapes jusqu'à ~~ Java 12-ea + 25 et 13-ea + 1 (Early Access montre le numéro de build), mais le même résultat est obtenu, donc Signaler comme bug .com / bugreport /), mais actuellement il est dans un format comme "NYY.MM.DD" (notation JIS X 0301 % 97% A5% E6% 9C% AC_ (JIS_X_0301))) est [SimpleDateFormat](https://docs.oracle.com/javase/jp/8/docs/api/java/text/SimpleDateFormat] après Java 9 Il vaut mieux penser que .html) ne peut pas être formaté et analysé. ~~ ~~ Il n'y a pas de problème si vous n'utilisez que les kanji du problème d'origine. En outre, l'utilisation de l'API Date et heure suivante peut être une solution de contournement pour le moment. ~~ "[[JDK-8216204] Comportement incorrect de SimpleDateFormat avec le calendrier impérial japonais](https://bugs.openjdk.java.net/browse/JDK-8216204?focusedCommentId=14234290&page=com.atlassian.jira.plugin.system.issuetabpanels: J'ai reçu un commentaire dans comment-tabpanel # comment-14234290) ", mais ce n'était pas un bogue mais un changement de spécification de Java 9. Si vous voulez que la sortie soit la même que Java 8 ou une version antérieure, vous pouvez définir la propriété système java.locale.providers sur quelque chose comme "COMPAT, CLDR".

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

** (1/13 postscript) ** CLDR n'est pas activé par défaut dans Java 8 et le paramètre de compatibilité est -Djava.locale.providers = COMPAT, SPI. -3704069.html # JDK-8008577), donc si vous êtes intéressé, vous pouvez le configurer de cette façon.

Informations de référence

Exemple d'utilisation de l'API Date et heure

L'API Date et heure introduite dans Java 8 est [conçue sur la base de la norme ISO 8601](https: //www.coppermine) pour remplacer ou migrer les anciens java.util.Date et java.util.Calendar. .jp / note / 2019/01 / base-de-iso8601 /). Un exemple utilisant ceci est le suivant. ** (6/15 avis) **

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 année M mois j jour", Locale.JAPAN);
		DateTimeFormatter asciiFormat = DateTimeFormatter.ofPattern("GGGGGyy.MM.dd", Locale.JAPAN);

		//Sortie de la date actuelle
		JapaneseDate today = JapaneseDate.now();
		System.out.println(kanjiFormat.format(today));
		System.out.println(asciiFormat.format(today));

		//Date de sortie avant révision
		JapaneseDate lastHeiseiDate = JapaneseDate.of(2019, 4, 30);
		System.out.println(kanjiFormat.format(lastHeiseiDate));
		System.out.println(asciiFormat.format(lastHeiseiDate));

		//Sortie de date après révision
		JapaneseDate firstNewEraDate = JapaneseDate.of(2019, 5, 1);
		System.out.println(kanjiFormat.format(firstNewEraDate));
		System.out.println(asciiFormat.format(firstNewEraDate));

		//Analyse de date non stricte
		DateTimeFormatter kanjiParseFormat = kanjiFormat.withChronology(JapaneseChronology.INSTANCE)
				.withResolverStyle(ResolverStyle.LENIENT);
		System.out.println(kanjiParseFormat.parse("1 mai 2019", LocalDate::from));
		//* En notation alphabétique"y"Si vous n'analysez pas avec un chiffre, le problème d'origine durera jusqu'à 11 ans+Traité depuis 100 ans
		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)); //Seulement après la sortie officielle

		//Une erreur se produira strictement lors de l'analyse
		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());
		}
	}
}

Au cas où, il est codé en dur comme JapaneseEra.HEISEI Cette partie ne peut pas être prise en charge jusqu'à la version lorsque le support de révision est officiellement entré. ** (Évalué le 27/09) ** JapaneseEra.REIWA est désormais public Is from Java 13](https://bugs.openjdk.java.net/browse/JDK-8193826) sorti en septembre. À propos, Locale peut être omis dans DateTimeFormatter, mais cela dépend du système d'exploitation et des paramètres de langue. "Heisei" est affiché au lieu de "Heisei", il est donc recommandé de le spécifier explicitement.

** (post-scriptum 6/15) ** Pour les modèles alphabétiques tels que GGGGGyy.MM.dd, le formatage fonctionne correctement, mais l'analyse doit être publiée après avril, date à laquelle elle a été officiellement publiée, pour les dates du nouveau genre. DateTimeParseException](https://docs.oracle.com/javase/jp/8/docs/api/java/time/format/DateTimeParseException.html) se produira. Ne faites pas non plus de GGGGGy.MM.dd et **" y "à un seul chiffre comme expliqué par @ kazuki43zoo dans les commentaires et article. Veuillez noter que jusqu'à la 11e année de l'émission d'origine sera traitée comme +100 ans **. Bien que ce soit contre-intuitif, j'ai confirmé avec des experts qu'il ne s'agissait pas d'un bug mais de [IsoChronology](https://docs.oracle.com/javase/jp/8/docs/api/java/time/ Il a été conclu que c'était probablement parce que les spécifications étaient formulées sur la base de chrono / IsoChronology.html). Si une analyse stricte incluant le nombre de chiffres est requise, il peut être préférable d'utiliser des expressions régulières ensemble.

Le comportement attendu à ce moment devrait être le suivant.

1 avril 2019
H31.04.01
30 avril 2019
H31.04.30
1er mai, 1ère année de 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の例と同様に、解析には注意が必要です。 La valeur par défaut est ResolverStyle.SMART, "13 mars" et "- Nous n'autorisons pas «1 jour» etc., mais nous ne pourrons pas analyser «2020» etc., donc je pense que cela ne répond souvent pas aux exigences de l'entreprise. Seules une analyse de date non stricte (LENIENT) et une analyse de date stricte (STRICT) sont spécifiées ici, mais des contrôles plus détaillés peuvent être nécessaires en fonction de la situation.

Voyons le fonctionnement et les précautions pour chaque version. Notez que les propriétés système calendars.properties et jdk.calendar.japanese.supplemental.era de Java 9 ou version ultérieure doivent être spécifiées de la même manière que dans l'exemple utilisant java.util.Date / Calendar.

Java 8 ** (Révisé le 27/04) ** Officiellement pris en charge par Oracle JDK 8u221 et 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)

Soudain, une exception s'est produite. ** (Revue 1/15) ** ~~ Il semble que le calendrier japonais ne pouvait pas être géré correctement au début de la version Java 8. (NullPointerException se produit également dans JapaneseDate.of et JapaneseDate.from.) ~~ Au début de la version Java 8, en raison d'un bogue dans JDK-8044671, l'ajout du problème d'origine à calendars.properties rend impossible la gestion correcte du calendrier japonais. Il semble que cela finira.

8u40~8u151

1 avril 2019
H31.04.01
30 avril 2019
H31.04.30
1er et 31 mai
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

Je veux que ce soit "1er mai, 1ère année de Reiwa" mais c'est "1er, 31 mai", et je veux que ce soit "R01.05.01" mais c'est "301.05.01". Il semble que puisque dans calendars.properties est utilisé, mais à part cela, il ne peut pas être lu correctement et le problème d'origine est traité comme "3". ** (Revue 1/15) ** En raison d'un bogue dans JDK-8054214, le problème original ajouté a été affiché sous forme de valeur numérique. Et il semble.

8u152~8u212

1 avril 2019
H31.04.01
30 avril 2019
H31.04.30
1er mai, 1ère année de 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

La sortie était comme prévu! Par conséquent, afin de gérer le calendrier japonais avec l'API Date et heure de Java 8, il semble préférable d'utiliser une version plus récente autant que possible.

Cependant, il y a une mise en garde. Dans l'exemple de code, DateTimeFormatter.ofPattern (" GGGGy année M mois d jour ") et "G" sont quatre [format complet](https://docs.oracle.com/javase/jp/8/docs/api/ Il a été spécifié par java / time / format / TextStyle.html # FULL), et il a été affiché comme "1er mai, 1ère année de Reiwa". S'il y a jusqu'à 3 "G", il sera traité comme format court. Cependant, "R1 May 1st" est émis. (Aucun problème jusqu'à "Heisei")

8u221~ ** (6/15 postscript) ** Officiellement pris en charge par Oracle JDK 8u221 et OpenJDK 8u222-b03. Par conséquent, lorsque vous utilisez le calendrier japonais avec l'API Date et heure, il est fondamentalement préférable d'utiliser des versions ultérieures. C'est parce que l'analyse avec des modèles alphabétiques tels que GGGGGy.MM.dd ne fonctionnera pas correctement pour les dates dans le nouveau genre (par exemple R01.05.01) à moins qu'il ne soit publié plus tard.

Voyons comment cela fonctionne dans Java 9 et supérieur. Procédez comme suit:

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

Java 9 En gros, toute version mineure fonctionne comme prévu. Cependant, Java 9 a les mêmes précautions que le 8u152 ~ précédent, donc lorsque vous écrivez en kanji, spécifiez quatre "GGGG" dans le DateTimeFormatter.

Java 10 En gros, toute version mineure fonctionne comme prévu. Même dans le format abrégé où "G" est jusqu'à 3 dans DateTimeFormatter, il a été corrigé de sorte que "1er mai, 1ère année de Reiwa" soit affiché.

Java 11, 12, 13 ** (Révisé le 27/04) ** Officiellement pris en charge par Oracle JDK 11.0.3 / 12.0.1 et OpenJDK 11.0.3 + 7 / 12.0.1, et l'implémentation d'espace réservé a été remplacée, donc ce qui suit ne s'applique pas ..

1 avril 2019
H31.04.01
30 avril 2019
H31.04.30
Édition originale 1er mai 1er
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

Au lieu des "Rewa" et "R" spécifiés dans les propriétés système, les "Gengo" et "N" sont affichés. Cela est dû au fait qu'il est remplacé par le contenu de Implémenté comme espace réservé. (À l'inverse, il en va de même même si vous ne spécifiez pas la propriété système jdk.calendar.japanese.supplemental.era.) ** (Révisé le 27/04) ** Le nouveau numéro a été révisé après avoir été annoncé et officiellement pris en charge dans Oracle JDK 11.0.3 / 12.0.1 et OpenJDK 11.0.3 + 7 / 12.0.1. Par conséquent, les conseils suivants sont également inutiles.

Conseils (conseils?)

Jusqu'à présent, on supposait que la propriété système jdk.calendar.japanese.supplemental.era serait définie sur "1556668800000", ce qui est considéré comme commençant le 1er mai 2019, mais si vous spécifiez une destination même pour 1 milliseconde, elle sera placée. J'ai pu outrepasser la mise en œuvre du support. ** (4/27 postscript) ** Nous avons reçu un commentaire de @mazkasa, et l'affichage est [CalendarNameProvider](https://docs.oracle.com/javase/jp/8/docs/api/java/util/spi /CalendarNameProvider.html) est une approche simple qui prend également en compte les paramètres régionaux, et l'implémentation de l'espace réservé sera également remplacée.

Voyons comment cela fonctionne dans JShell. Commencez comme suit.

$ 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 année M mois j jour", Locale.JAPAN)
-> var asciiFormat = DateTimeFormatter.ofPattern("GGGGGyy.MM.dd", Locale.JAPAN)
-> var firstNewEraDate = JapaneseDate.of(2019, 5, 1)
-> System.out.println(kanjiFormat.format(firstNewEraDate))
1er mai, 1ère année de Reiwa
-> System.out.println(asciiFormat.format(firstNewEraDate))
R01.05.01
-> /exit

なお、旧来のjava.util.Date/Calendarではオーバーライドできず、プレースホルダ実装のままとなりました。(もちろん翌日の5月2日を指定すれば動きますが意味はありません) L'API de date et d'heure ne doit pas prendre en compte la spécification de telles propriétés de système irrégulières. Par conséquent, en gros, il est préférable d'attendre la publication du correctif après l'annonce du problème officiel, mais si vous voulez vraiment utiliser une version qui n'est pas officiellement prise en charge (et Java 11 ou version ultérieure), il s'agit d'une mesure de premiers soins. Il peut être possible de l'utiliser pour. ** (Révisé le 27/04) ** Officiellement pris en charge par Oracle JDK 11.0.3 / 12.0.1 et OpenJDK 11.0.3 + 7 / 12.0.1, il n'est donc pas nécessaire lors de l'utilisation de ceci ou d'une version ultérieure.

Supplément

À propos de la notation de la première année

Dans l'exemple d'exécution précédent, la sortie était "Reiwa 1 an". Cependant, lors de la sortie en kanji, il existe de nombreux cas où vous souhaitez afficher quelque chose comme "la première année de Reiwa".

java.util.Date/Calendarの場合

Dans l'ancien java.text.DateFormat, utilisez le formateur de date qui spécifie le style FULL. Cela peut être réalisé avec. ** (4/17 postscript) ** De plus, si vous spécifiez 4 ou plus "y" comme GGGGyyyy year, ce sera la même chose que le style FULL.

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 janvier 1989"); //Il n'y a aucun problème avec l'analyse, mais Heisei est utilisé pour plus de commodité.
	}
}

Lorsque ce qui précède est exécuté, la sortie sera quelque chose comme "1er mai, 1ère année de Reiwa". ** (Révisé le 27/04) ** Dans Java 11 et versions ultérieures, comme dans l'exemple d'exécution illustré ci-dessus, les espaces réservés ont été classés par ordre de priorité et sont devenus "1er mai, 1ère année du problème d'origine", mais Oracle JDK 11.0.3 / 12.0.1, OpenJDK 11.0.3 Officiellement pris en charge dans +7 / 12.0.1.

À propos, si vous spécifiez le style SHORT, etc., l'année sera à un chiffre comme "R1.05.01", donc [notation JIS X 0301](https://ja.wikipedia.org/wiki/ISO_8601#%E6%97%A5%E6 Il est différent de% 9C% AC_ (JIS_X_0301)).

Pour l'API de date et d'heure

** (1/13 avis) ** Il est possible de spécifier le style FULL avec l'API Date et Heure de Java 8, mais malheureusement, il ne prend actuellement pas en charge la "première année", et la sortie varie en fonction de la version. ~~ JDK-8068571 ne prend pas en charge la "première année", à la place [DateTimeFormatterBuilder](https: // docs) .oracle.com / javase / jp / 8 / docs / api / java / time / format / DateTimeFormatterBuilder.html) le supportera. ** (Révisé le 27/04) ** Fondamentalement, Shaping is Java 11 ou version ultérieure, Analysis is Java 12 ou version ultérieure / blowse / JDK-8210633) sera pris en charge. ~~ Il sera probablement rétroporté après 8u221 et 11.0.4, qui sortiront à la mi-juillet 2019. ~~ Les deux ont été rétroportés avec Oracle JDK 8u211 / 11.0.3 et OpenJDK 8u212-b03 / 11.0.3 + 7.

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, "Ancien"));
		builder.appendLiteral("Année");
		builder.appendValue(ChronoField.MONTH_OF_YEAR);
		builder.appendLiteral("Mois");
		builder.appendValue(ChronoField.DAY_OF_MONTH);
		builder.appendLiteral("journée");
		DateTimeFormatter formatter = builder.toFormatter(Locale.JAPAN)
				.withChronology(JapaneseChronology.INSTANCE);

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

** (Révisé le 27/04) ** Pour cette raison, lorsqu'elle est simplement exécutée, l'implémentation d'espace réservé de Java 11 ou version ultérieure affiche quelque chose comme "1er mai, 1ère année du problème d'origine", mais Oracle JDK 11.0.3 Il est officiellement supporté par / 12.0.1, OpenJDK 11.0.3 + 7 / 12.0.1, et "1er mai, 1ère année de Reiwa" est sorti. Dans les anciennes versions, l'API Date and Time ne peut à elle seule prendre en charge la "première année", donc je pense qu'il serait plus facile de remplacer un modèle tel que "1er mai, 1ère année du Rei" par une expression régulière. Je vais.

** (PostScript 3/24) ** Ce qui précède spécifie que seule la première année est convertie en Collections.singletonMap (1L," original "). Lorsqu'il s'agit d'une autre que la première année (comme "2019"), ce n'est pas un problème au moment de la mise en forme, mais il est nécessaire d'ajouter ce montant à la carte au moment de l'analyse. Par exemple, modifiez la partie appropriée comme suit. (On suppose que la déclaration d'importation requise est spécifiée séparément.)

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

Correspondance avec les nombres chinois

** (3/3 postscript) ** Si vous modifiez la partie de DateTimeFormatterBuilder dans l'exemple de code ci-dessus, vous pouvez prendre en charge les nombres chinois autres que la première année. Si vous souhaitez prendre en charge le 100e anniversaire du problème d'origine pour le moment, vous pouvez le remplacer comme suit.

// 0(〇)N'est pas utilisé dans cet exemple, mais défini pour plus de commodité
String[] kanjiNumBase = {"〇", "un", "deux", "Trois", "quatre", "Cinq", "Six", "Sept", "Huit", "Neuf"};

// 1(un)À partir de 99(Quatre-vingt-dix-neuf)Définissez des nombres chinois jusqu'à
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("Dix");
    if (ones > 0) {
        kanjiNum.append(kanjiNumBase[ones]);
    }
    kanjiNumMap.put(Long.valueOf(num), kanjiNum.toString());
}

//L'année correspond à la première année et à 100 ans
Map<Long, String> yearMap = new HashMap<>(kanjiNumMap);
yearMap.put(Long.valueOf(1), "Ancien");
yearMap.put(Long.valueOf(100), "cent");

DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
builder.appendText(ChronoField.ERA, TextStyle.FULL);
builder.appendText(ChronoField.YEAR_OF_ERA, yearMap);
builder.appendLiteral("Année");
builder.appendText(ChronoField.MONTH_OF_YEAR, kanjiNumMap);
builder.appendLiteral("Mois");
builder.appendText(ChronoField.DAY_OF_MONTH, kanjiNumMap);
builder.appendLiteral("journée");

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

Si vous utilisez Java 11 ou version ultérieure, vous pouvez l'utiliser pour afficher quelque chose comme "30 avril 1991". De plus, s'il s'agit de Java 12 ou version ultérieure, en plus des dates normales telles que "8 janvier 1989" et "30 avril 1991", lors de la conversion en DateTimeFormatter, `withResolverStyle (ResolverStyle.LENIENT) En précisant) », il devient possible d'analyser des dates inexistantes telles que« 31 décembre 1997 »et« 1er janvier 1945 ».

Backport vers Java 8/11

** (Evalué le 17/04) ** Avec la sortie le 16 avril 2019 (heure des États-Unis), un backport pour les révisions a été mis en œuvre. Par conséquent, si vous pouvez mettre à niveau vers une version ultérieure, vous devriez être en mesure de répondre à la révision sans trop de considération.

Correspondance des caractères communs

** (Évalué le 28/09) ** Dans le nouveau numéro, des caractères tels que "㍻" sont attribués point de code Unicode "U + 32FF". , Java 13 ou version ultérieure avec Prise en charge Unicode 12.1, [Normalisation Unicode](https://docs.oracle.com/javase/ jp / 8 / docs / api / java / text / Normalizer.html) est également pris en charge, et vous pouvez le vérifier avec le code suivant.

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"); // ㋿ (Caractère commun de Reiwa)
		System.out.println(Normalizer.normalize("\u32ff", Normalizer.Form.NFKD));
		System.out.println(Normalizer.normalize("\u32ff", Normalizer.Form.NFKC));
	}
}

Le résultat de l'exécution avec Oracle OpenJDK 13 est le suivant.

$ 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

Dans mon environnement macOS Mojave 10.14.6, j'ai pu confirmer qu'il est normalisé et affiché correctement. En fin de compte, l'affichage des caractères dépend de la mise à jour du système d'exploitation et de la prise en charge des polices.

Toujours sous Windows 10 (1903), après avoir reçu un commentaire de @mazkasa, changez la page de codes en "65001" (UTF-8) à l'invite de commande et ajoutez -Dfile.encoding = UTF-8 pour l'afficher. C'est venu pour être fait. L'exemple d'exécution lors de l'utilisation de Liberica JDK est le suivant.

> 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

Notez que Unicode 12.1.

Résumé

Le tableau ci-dessous, comprenant les notes des versions antérieures ci-dessus, est le suivant. ** (Évalué le 18/04) **

version java.util.Date/Calendar Date and Time API Remarques / notes courantes
6 ○:Les caractères kanji sont déformés selon le système d'exploitation N/A (incompatible) Les versions antérieures à avril 2019 sont des calendriers.les propriétés doivent être modifiées
7 N/A (incompatible) Les versions antérieures à avril 2019 sont des calendriers.les propriétés doivent être modifiées
8 △:Si vous utilisez la dernière version ◎ Les versions antérieures à avril 2019 sont des calendriers.Les propriétés doivent être modifiées, la notation de la première année est implémentée séparément
9 ◎:La notation alphabétique est java.locale.fournisseurs requis ○:Notation Kanji"GGGG"Et la spécification du modèle, la notation de la première année est implémentée séparément jdk.calendar.japanese.supplemental.époque requise
10 ◎:La notation alphabétique est java.locale.fournisseurs requis ○:La notation de la première année est implémentée séparément jdk.calendar.japanese.supplemental.époque requise
11 ou plus tard ○:Initialement implémentation d'espace réservé, la notation alphabétique est java.locale.fournisseurs requis ○:Prend en charge la notation de première année, l'implémentation d'espace réservé peut être écrasée Si vous passez à une version après avril 2019, tous sont ◎

** (Révisé le 28/09) ** Veuillez utiliser le JDK 13 publié en septembre 2019 pour prendre en charge la normalisation Unicode du caractère japonais «㋿».

en conclusion

L'idée principale est de mettre à niveau votre JDK / JRE vers la dernière version après la révision, mais si vous utilisez Oracle JDK / JRE 8, les mises à jour publiques pour les utilisateurs commerciaux ont pris fin en janvier 2019. Par conséquent, il est supposé qu'il peut être nécessaire de basculer vers Abonnement Oracle Java SE ou une autre distribution JDK. Sera fait. Si le nouveau yuan avait été annoncé plus tôt (au plus tard début 2019), il aurait pu être officiellement révisé par les mises à jour publiques de janvier 2019, et il n'aurait peut-être pas été nécessaire d'écrire cet article. .. Ce n'est pas limité à Java, mais j'espère que le support de révision du système qui gère le calendrier japonais sera terminé avec succès.

Recommended Posts

Résumé des révisions (nouveaux problèmes de yuan) par version Java
Résumé du support Java 2018
Résumé des nouvelles fonctionnalités de Java 12
Résumé des nouvelles fonctionnalités de Java 13
Résumé des nouvelles fonctionnalités de Java 10
Résumé des nouvelles fonctionnalités de Java 14
Afficher la vue au-dessus des autres applications sur Android (Résumé des méthodes de support par version d'API)
[Java] Résumé de base de Java non couvert par Progate ~ Partie 1 ~
[Version finale] Vérifiez le fonctionnement du calendrier japonais en utilisant ICU pour prendre en charge le nouveau problème du yuan.
[Java] Résumé des expressions régulières
[Java] Résumé des opérateurs (opérateur)
Résumé orienté objet par les débutants (Java)
Résumé des bases du langage Java
Résumé de la classe Java Math
[Java] Résumé de la syntaxe de contrôle
Résumé du traitement des erreurs Java
[Java] Résumé des modèles de conception
[Java] Résumé des opérations mathématiques
[Java] Résumé de base de Java non couvert par Progate ~ Partie 2 ・ Liste ~
Récapitulatif des valeurs renvoyées par la méthode des caractéristiques Spliterator #java
Changer la version de java installée par SDKMAN lors du déplacement de répertoires
[Pour les débutants] Résumé du constructeur java
[Édition Java] Histoire de la sérialisation
Résumé du package [Java Silver Study]
[Java] DateTimeFormatter sortie par FormatStyle
Récapitulatif du problème Java "Pass by Reference"
Java EE 8 (Jakarta EE 8) Résumé des nouvelles fonctionnalités
Résumé de la programmation orientée objet utilisant Java
[Java Silver] Résumé des points de modification d'accès
Résumé de la session d’étude interne des recrues [Java]
Mémorandum du nouveau diplômé SES [Java basics]
[java] Résumé de la gestion des caractères
Résumé de la compréhension de Docker par les débutants ② ~ docker-compose ~
J'ai essayé le nouveau yuan à Java
[Java] Résumé personnel des instructions conditionnelles (basique)
Installation de l'agent OMC APM --JAVA Edition-
[Java] [Maven3] Résumé de l'utilisation de Maven3
Introduction du guide de programmation Java de nouvelle génération (Java 10)
Résumé Java des conversions de types fréquemment recherchées
Introduction du guide de programmation Java de nouvelle génération (Java 11)
Résumé de Java Math.random et import (calendrier)
Introduction du guide de programmation Java de nouvelle génération (Java 12)
[java] Résumé de la gestion des chaînes de caractères
Récapitulatif des paramètres de l'environnement Java pour moi-même [mac]
[Java] Appel de méthode dynamique par réflexion du type enum (enum)
[Java] Résumé de la façon d'omettre les expressions lambda
[Java] Accéder à l'URL signée de s3 (version signée 2)
Résumé des nouvelles fonctionnalités ajoutées dans Deeplearning4J 1.0.0-beta4
Mémorandum du nouveau diplômé SES [édition orientée objet Java]
Essayez Progate Free Edition [Java II]
[Note] Java: vitesse de traitement de la liste par objectif
Résumé de la compréhension de Docker par les débutants ① ~ docker run -p ~
Essayez Progate Free Edition [Java I]