[JAVA] [Version finale] Vérifiez le fonctionnement du calendrier japonais en utilisant ICU pour prendre en charge le nouveau problème du yuan.

Mettre à jour le contenu

introduction

Dans cet article, le nouveau numéro original "Rewa (Rewa)" est destiné aux applications qui intègrent ICU (International Components for Unicode), qui est une bibliothèque d'internationalisation multiplateforme. J'expliquerai les actions nécessaires pour répondre à "Iwa)".

Le contenu de cet article est basé sur ce qui est écrit sur ici.

Statut ICU

À partir de la version 64.2 publiée le 18 avril 2019 (heure du Japon), l'ICU a incorporé des ressources pour prendre en charge la nouvelle émission de yuans «Reiwa». Auparavant, à partir de la version 63 (63.1 *) publiée le 15 octobre 2018, les ressources pour soutenir le nouveau yuan étaient déjà incorporées sous la forme de "yuan temporaire", mais ** yuan provisoire Il n'est plus nécessaire de spécifier le problème **. De plus, à partir de la version 64 (64.1) publiée le 27 mars 2019, la «première année» peut être gérée comme une notation à la fois pour l'entrée et la sortie en plus d'un an. Pour le moment, l'ICU soutient la nouvelle question du yuan dans les deux points suivants.

Remarque * La première version est 63.1, pas un départ nul comme 63.0.

  1. "Reiwa" a été ajouté comme numéro d'origine à partir du 1er mai 2019 (à partir de 64.2)
  2. Les notations "1 an" et "première année" peuvent être traitées (à partir de 64.1)
  3. ~~ Un espace réservé a été ajouté pour indiquer le nombre provisoire de yuans "QQ" (deux alphabet pleine largeur "cue") comme question du yuan à partir du 1er mai 2019 ~~ (de 63,1 à 64,1)
  4. ~~ Pour utiliser des espaces réservés, spécifiez ʻICU_ENABLE_TENTATIVE_ERA = true` dans l'argument JVM ou la variable d'environnement ~~ (de 63.1 à 64.1)

Les applications liées à des versions d'ICU antérieures à la v63.1 peuvent être testées en remplaçant simplement la bibliothèque par la v64.2. Cependant, pour afficher "Reiwa" ou l'accepter par entrée, ce n'est que si l'application prend déjà en charge les formats de calendrier japonais tels que "Heisei" et "Showa" par entrée et sortie. Par conséquent, ** Si vous ne traitez que des dates dans le calendrier occidental pour le moment, le remplacement de la bibliothèque ne prendra pas immédiatement en charge le nouveau problème du yuan **

L'opération est résumée comme suit.

Entrée dans le calendrier japonais 63.1 ou moins ou ICU_ENABLE_TENTATIVE_ERA=false 63.1 ou plus et ICU_ENABLE_TENTATIVE_ERA=true 64.2 ou plus (aucune variable d'environnement requise)
1 mai 2019 1 mai 2019 QQ 1, 1er mai(63.1) /QQ 1er mai, 1re année(64.1) 1er mai, 1ère année de Reiwa
QQ 1, 1er mai Erreur de perspective QQ 1, 1er mai(63.1) /QQ 1er mai, 1re année(64.1) Erreur de perspective
QQ 1er mai, 1re année Erreur de perspective Erreur de perspective(63.1) /QQ 1er mai, 1re année(64.1) Erreur de perspective
1er mai, 1ère année de Reiwa Erreur de perspective Erreur de perspective(63.1) /Erreur de perspective(64.1) 1er mai, 1ère année de Reiwa

Ce résultat suppose «java.util.Calendar.setLenient (true)» et «com.ibm.icu.util.Calendar.setCalendarLenient (true)» (les deux sont des valeurs par défaut et n'ont pas besoin d'être spécifiées). .. "1er mai 2019" est une date qui n'existe pas réellement, mais cela dépend des spécifications de l'application, qu'il s'agisse ou non d'une erreur d'analyse. Le comportement de setLenient () et setCalendarLenient () n'est pas traité dans cet article car il a une grande variété de contenus.

En outre, comme autre sujet concernant la correspondance avec le nouveau numéro du yuan "Reiwa", il y a aussi le traitement des caractères communs qui représentent le problème du yuan avec une seule lettre, comme "㍼" et "㍻", mais cela n'est pas non plus traité dans cet article. Hmm.

La notation «Première année» est prise en charge à partir de ICU v64.1. Cependant, veuillez noter que la version v64.1 n'est pas encore compatible avec "Reiwa" car elle était antérieure à l'annonce du nouveau numéro original "Rewa". Veuillez établir un lien avec la version 64.2 ou supérieure.

Le calendrier peut être résumé comme suit.

saison ICU Version Prend en charge le nouveau yuan
Octobre 2018 63.1 ICU «QQ»_ENABLE_TENTATIVE_ERA=Activé avec true
Mars 2019 64.1 ICU «QQ»_ENABLE_TENTATIVE_ERA=Activé avec true,"1 an=Correspondance "première année"
Avril 2019 64.2 "Reiwa" ajouté(ICU_ENABLE_TENTATIVE_ÈREInutile)

Correspondance avec les versions antérieures de l'ICU

Selon cette Pull Request (ICU-20536), en plus de la v64.2, il y a des commandes pour les versions antérieures. Il semble que le numéro original japonais a été ajouté. J'ai pu confirmer les numéros de version suivants.

4.8.2 50.2 51.3 52.2 53.2 54.2 55.2 56.2 57.2 58.3 59.2 60.3 61.2 62.2 63.2

Par rapport à la v64.2, ces versions omettent le nouveau support du yuan suivant.

Que pouvez-vous faire maintenant

Maintenant, je vais vous expliquer comment lier la version 64.2 de l'ICU (et les anciennes versions de l'ICU qui prennent en charge le décret) à l'application et vérifier le fonctionnement.

Exemple de code source C ++ utilisant ICU4C

ICU (ICU4C) fournit des API pour C et C ++, mais ici nous utiliserons un exemple C ++.

sample.cpp


#include <stdio.h>
#include <iostream>
#include "unicode/datefmt.h"
#include "unicode/dtfmtsym.h"
#include "unicode/gregocal.h"
#include "unicode/timezone.h"
#include "unicode/unistr.h"
#include "unicode/ustring.h"
#include "unicode/dtptngen.h"
#include "unicode/dtitvfmt.h"

using namespace icu;

//Un utilitaire simple pour éviter les caractères déformés sous Windows
void myprintf(std::string format, UnicodeString ustr) {
	char abuf[0x100];
	ustr.extract(0, sizeof(abuf), abuf);
	printf(format.c_str(), abuf);
}

int main( int argc, char **argv )
{
	UErrorCode status = U_ZERO_ERROR;
	//Paramètres régionaux basés sur AD
	Locale loc_jp1 = Locale::getJapanese();
	//Désigné par les paramètres régionaux basés sur le calendrier japonais LanguageTag
	Locale loc_jp2 = Locale("ja-u-ca-japanese");

	// (A)Classe de génération de motifs
	DateTimePatternGenerator *g_jp1 = DateTimePatternGenerator::createInstance(loc_jp1, status);
	status = U_ZERO_ERROR;
	DateTimePatternGenerator *g_jp2 = DateTimePatternGenerator::createInstance(loc_jp2, status);
	if (U_FAILURE(status)) {
		return 1;
	}

	// (B)Obtenez le modèle de format de date approprié pour chaque paramètre régional
	status = U_ZERO_ERROR;
	UnicodeString up_jp1 = g_jp1->getBestPattern(UnicodeString("yyyyMMMd"), status);
	myprintf("pattern jp1: %s\n", up_jp1);
	status = U_ZERO_ERROR;
	UnicodeString up_jp2 = g_jp2->getBestPattern(UnicodeString("yyyyMMMd"), status);
	myprintf("pattern jp2: %s\n", up_jp2);

	// (C)Générer à l'aide d'un modèle de format
	status = U_ZERO_ERROR;
	SimpleDateFormat *df_jp1 = new SimpleDateFormat(up_jp1, loc_jp1, status);
	status = U_ZERO_ERROR;
	SimpleDateFormat *df_jp2 = new SimpleDateFormat(up_jp2, loc_jp2, status);

	// (A),(B),(C)Cliquez ici pour savoir comment écrire DateFormat
	//DateFormat *df_jp1 = DateFormat::createInstanceForSkeleton("yMMMd", loc_jp1, status);
	//DateFormat *df_jp2 = DateFormat::createInstanceForSkeleton("yMMMd", loc_jp2, status);

	UnicodeString uin = UnicodeString(argv[1]);
	myprintf("input:%s\n", uin);
	status = U_ZERO_ERROR;
	//Tout d'abord, Perth comme calendrier
	UDate inDate = df_jp1->parse(uin, status);
	if (U_FAILURE(status)) {
		std::cout << "Parse error (" << u_errorName(status) << ") try another." << std::endl;
        status = U_ZERO_ERROR;
	//Ensuite, Perth comme calendrier japonais
        inDate = df_jp2->parse(uin, status);
    	if (U_FAILURE(status)) {
		    std::cout << "Parse error (" << u_errorName(status) << ") again." << std::endl;
            return 1;
        }
	}
	//Sortie de la date saisie dans chacun des calendriers occidental et japonais
	UnicodeString ud_jp1;
	df_jp1->format(inDate, ud_jp1);
	myprintf("output jp1:%s\n", ud_jp1);
	UnicodeString ud_jp2;
	df_jp2->format(inDate, ud_jp2);
	myprintf("output jp2:%s\n", ud_jp2);

	return 0;
}

Exécution sur macOS

macOS a une ICU intégrée, mais pour tester l'ICU du système d'exploitation sans la mettre à jour directement, profitez de Homebrew (http://brew.sh/) pour installer ICU 64.2. (Sortie le 19 avril 2019)

$ brew install icu4c

L'exemple de code ci-dessus peut être compilé comme suit. La partie variable d'environnement peut également être spécifiée comme argument du compilateur. Si la destination de l'installation par infusion est différente de l'exemple, remplacez-la si nécessaire.

$ export C_INCLUDE_PATH=/usr/local/opt/icu4c/include
$ export CPLUS_INCLUDE_PATH=/usr/local/opt/icu4c/include
$ export LIBRARY_PATH=/usr/local/opt/icu4c/lib
$ export LD_LIBRARY_PATH=/usr/local/opt/icu4c/lib
$ clang++ -licuio -licui18n -licutu -licuuc -licudata -std=c++1z sample.cpp

Vous pouvez le faire comme suit: Dans le premier argument, spécifiez la date d'entrée dans le calendrier occidental ou japonais.

L'exemple d'exécution est basé sur la v64.2. Pour les résultats exécutés sous la version 63.2, remplacez «première année» par «1 an».

(A) Entrée comme Heisei et sortie dans le calendrier et décret occidentaux

Selon le réglage de setLenient (), il peut être traité même si vous entrez la date de la période de réconciliation dans Heisei.

Puisque df_jp1 attend une entrée dans le calendrier occidental, Parse error apparaîtra une fois.

$ ./a.sortie le 1 mai 2019
pattern jp1:aaaa année M mois j jour
pattern jp2:Gy année M mois j jour
input:1 mai 2019
Parse error (U_ILLEGAL_ARGUMENT_ERROR) try another.
output jp1:1 mai 2019
output jp2:1er mai, 1ère année de Reiwa
(B) Entrée comme Heisei et sortie dans le calendrier occidental et Heisei

En raison du soutien du décret, il n'est plus possible de forcer la sortie des dates après le "1er mai, 1ère année du décret" à Heisei en utilisant l'exemple de code ci-dessus.

(C) Entrée dans le calendrier occidental et sortie dans le calendrier occidental et la somme

Je n'obtiens pas d'erreur d'analyse.

$ ./a.sortie le 1 mai 2019
pattern jp1:aaaa année M mois j jour
pattern jp2:Gy année M mois j jour
input:1 mai 2019
output jp1:1 mai 2019
output jp2:1er mai, 1ère année de Reiwa
(D) Entrée dans le calendrier occidental et sortie dans le calendrier occidental et Heisei

En raison du soutien du décret, il n'est plus possible de forcer la sortie des dates après le "1er mai, 1ère année du décret" à Heisei en utilisant l'exemple de code ci-dessus.

(E) Entrée en décret et sortie en calendrier chronologique et décret

Puisque df_jp1 attend une entrée dans le calendrier occidental, Parse error apparaîtra une fois.

$ ./a.sortie le 1er mai, 1ère année de Reiwa
pattern jp1:aaaa année M mois j jour
pattern jp2:Gy année M mois j jour
input:1er mai, 1ère année de Reiwa
Parse error (U_ILLEGAL_ARGUMENT_ERROR) try another.
output jp1:1 mai 2019
output jp2:1er mai, 1ère année de Reiwa

Même si vous entrez dans "1 an", il sera édité dans "première année".

$ ./a.sortie le 1er mai, 1ère année
pattern jp1:aaaa année M mois j jour
pattern jp2:Gy année M mois j jour
input:1er mai, 1ère année de Reiwa
Parse error (U_ILLEGAL_ARGUMENT_ERROR) try another.
output jp1:1 mai 2019
output jp2:1er mai, 1ère année de Reiwa
(F) Entrée dans le décret et sortie dans le calendrier occidental et Heisei

Selon le réglage de setLenient (), il peut également être traité en entrant la date de la période Heisei dans la somme. Dans ce cas, il sera publié dans Heisei.

$ ./a.sortie le 1er avril, 1ère année de Reiwa
pattern jp1:aaaa année M mois j jour
pattern jp2:Gy année M mois j jour
input:1er avril, 1ère année de Reiwa
Parse error (U_ILLEGAL_ARGUMENT_ERROR) try another.
output jp1:1 mai 2019
output jp2:1 avril 2019
$ ./a.sortie le 1er avril, 1ère année
pattern jp1:aaaa année M mois j jour
pattern jp2:Gy année M mois j jour
input:1er avril, 1ère année de Reiwa
Parse error (U_ILLEGAL_ARGUMENT_ERROR) try another.
output jp1:1 mai 2019
output jp2:1 avril 2019

Fonctionnement sous Linux

Confirmé sur Ubuntu 18.04 (64 bits).

Téléchargez ʻicu4c-64_2-Ubuntu-18.04-x64.tgz` depuis le site ICU et décompressez-le. Le répertoire extrait est appelé ici «$ ICUPATH».

Le reste peut être fait de la même manière que pour macOS.

$ export C_INCLUDE_PATH=$ICUPATH/include
$ export CPLUS_INCLUDE_PATH=$ICUPATH/include
$ export LIBRARY_PATH=$ICUPATH/lib
$ export LD_LIBRARY_PATH=$ICUPATH/lib
$ clang++ -licuio -licui18n -licutu -licuuc -licudata -std=c++1z sample.cpp

Ou

$ g++ sample.cpp -licuio -licui18n -licutu -licuuc -licudata

La méthode d'exécution est la même que pour macOS.

Exécution sous Windows (VC ++)

Créez un projet dans Visual Studio avec Visual C ++> Windows Desktop> Windows Console Application. Ici, le nom de la solution est «JapaneseNewEraICU».

Téléchargez ʻicu4c-64_2-Win64-MSVC2017.zip` depuis le site ICU et décompressez-le. Le dossier extrait est appelé ici «% ICUPATH%».

Définissez les valeurs suivantes dans les propriétés de la solution.

article Valeur à définir
Propriétés de configuration> VC++annuaire
Inclure le répertoire %ICUPATH%\include;$(IncludePath)
Répertoire de la bibliothèque %ICUPATH%\lib64;$(LibraryPath)
Propriétés de configuration>Éditeur de liens>contribution
Fichiers dépendants supplémentaires icuio.lib;icuin.lib;icutu.lib;icuuc.lib;%(AdditionalDependencies)

Lors de la compilation avec ce paramètre, j'obtiens l'erreur "Le programme ne peut pas démarrer car icuin64.dll est absent de votre ordinateur. Pour résoudre ce problème, essayez de réinstaller le programme." Il s'agit d'une erreur due au fait que la DLL ICU téléchargée n'est pas trouvée dans la variable d'environnement% PATH%.

Lors de l'exécution, ouvrez une invite de commande distincte et

C:\> set PATH=%ICUPATH%\bin64;%PATH%

Après avoir couru

C:\> .\JapaneseNewEraICU.exe 16 février 2020

Etc.

Exemple de code source Java utilisant ICU4J

Ajoutez ʻICU4J` à la dépendance du référentiel Maven.

pom.xml


<!-- https://mvnrepository.com/artifact/com.ibm.icu/icu4j -->
<dependency>
    <groupId>com.ibm.icu</groupId>
    <artifactId>icu4j</artifactId>
    <version>64.2</version>
</dependency>

Voici un exemple de code similaire à C ++.

test/Sample.java


package test;

import java.text.ParseException;
import java.util.Date;
import java.util.Locale;

import com.ibm.icu.text.DateTimePatternGenerator;
import com.ibm.icu.text.SimpleDateFormat;

public class Sample {

    public static void main(String[] args) {
        Locale loc_jp1 = Locale.JAPANESE;
        Locale loc_jp2 = Locale.forLanguageTag("ja-u-ca-japanese");

        //(A)
        DateTimePatternGenerator g_jp1 = DateTimePatternGenerator.getInstance(loc_jp1);        
        DateTimePatternGenerator g_jp2 = DateTimePatternGenerator.getInstance(loc_jp2);
        //(B)
        String p_jp1 = g_jp1.getBestPattern("yyyyMMMd");
        System.out.format("pattern jp1: %s\n",p_jp1);
        String p_jp2 = g_jp2.getBestPattern("yyyyMMMd");
        System.out.format("pattern jp2: %s\n",p_jp2);
        //(C)
        SimpleDateFormat df_jp1 = new SimpleDateFormat(p_jp1, loc_jp1);
        SimpleDateFormat df_jp2 = new SimpleDateFormat(p_jp2, loc_jp2);

        //(A),(B),(C)Cliquez ici pour savoir comment écrire DateFormat
        //import com.ibm.icu.text.DateFormat;En conjonction avec
        //DateFormat df_jp1 = DateFormat.getInstanceForSkeleton("yMMMd", loc_jp1);
        //DateFormat df_jp2 = DateFormat.getInstanceForSkeleton("yMMMd", loc_jp2);

        String input = args[0];
        System.out.format("input: %s\n", input);
        Date idate = null;
        try {
            idate = df_jp1.parse(input);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        if (idate==null) {
            try {
                idate = df_jp2.parse(input);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        
        String out_jp1 = df_jp1.format(idate);
        System.out.format("output jp1: %s\n", out_jp1);
        String out_jp2 = df_jp2.format(idate);
        System.out.format("output jp2: %s\n", out_jp2);
    }
}

En plus de l'exécution sur l'IDE, lors de l'exécution directe à partir de la commande, ce sera comme suit.

$ java -cp ~/.m2/repository/com/ibm/icu/icu4j/64.2/icu4j-64.2.jar:target/classes test.Sample Reiwa 10 mai, 1ère année

(Bonus) Assistance avec Node.js

Depuis Node.js v12.1 sorti le 29 avril 2019, il sera lié à ICU v64.2. Par conséquent, il est désormais possible d'utiliser Reiwa comme numéro d'origine sans aucune désignation particulière.

Puisqu'il n'y a pas de bibliothèque telle que ICU pour NodeJS, voici un exemple d'affichage de la date de la période du rapprochement avec un objet Date normal.

test/sample.js


var date = new Date(Date.UTC(2019, 11, 20, 3, 0, 0));
var options = {
era: 'short',
year: 'numeric',
month: 'narrow',
day: 'numeric',
weekday: 'narrow'
};
console.log(date.toLocaleString('ja-u-ca-japanese',options));
$ node test/sample.js
20 décembre, 1ère année de Reiwa(journée)

Ce que vous pouvez faire une fois le nouveau yuan décidé

Comme expliqué dans "ICU Status" ci-dessus, la version ICU v64.2 avec "Rewa" intégré a été publiée.

Jusqu'à présent, si vous avez minutieusement testé l'affichage et la saisie du problème provisoire du yuan dans "QQ" en utilisant ICU 63.1 / 64.1 ou une version ultérieure, vous pouvez le remplacer par ICU v64.2 après la publication officielle pour obtenir le nouveau problème du yuan. La correspondance est terminée.

Un point à noter est le paramètre régional qui correspond au calendrier japonais. La locale ja-u-ca-japanese utilisée comme jp2 dans l'exemple de code source est la locale correspondant au calendrier japonais. Il fonctionne également dans des formats tels que ja_JP_TRADITIONAL ou ja_JP_JP. Étant donné que ces valeurs sont rarement définies par l'utilisateur ou le système avec la variable d'environnement «LANG», etc., on s'attend à ce que l'application prépare sa propre logique de jugement pour déterminer si elle fonctionne dans le calendrier japonais.

à la fin

Le yuan a déjà été révisé, mais nous espérons que cet article vous aidera dans le travail de réponse à l'avenir.

Recommended Posts

[Version finale] Vérifiez le fonctionnement du calendrier japonais en utilisant ICU pour prendre en charge le nouveau problème du yuan.
Résumé des révisions (nouveaux problèmes de yuan) par version Java
Vérifiez la version de Cent OS
J'ai essayé de vérifier le fonctionnement du serveur gRPC avec grpcurl
Afficher le calendrier et le jour japonais en utilisant la classe standard java8
Vérifiez le fonctionnement à l'aide de la jetée avec Maven.
Vérifiez la version du logiciel Web standard.
Vérifiez le fonctionnement de l'interface à travers le thread
Faites attention à la vérification des limites de la valeur d'entrée lors de l'utilisation du type float
Envoyez des notifications à Slack avec la version gratuite de sentry (en utilisant lambda)
Vérifiez la version de JDK installée et la version de JDK activée
J'ai essayé de vérifier le fonctionnement de la requête http (Put) avec Talented API Tester
[Rails] Comment afficher les prévisions météo de l'adresse enregistrée en japonais en utilisant OpenWeatherMap
[Java] Vérifiez la version JDK du fichier war construit
Comment télécharger une ancienne version d'Apache Tomcat