--2019/5/7 Added about Node.js --2019 / 5/7 Specify the Japanese calendar locale with the language tag, and add to the usage of some APIs in the source code (no change in operation) --2019/4/26 Updated ICU 64.2 description on Mac Homebrew --Added about 2019/4/18 ICU 64.2. It is no longer necessary to specify the temporary era --2019/4/1 The new era has been decided as Reiwa, so the related parts have been updated. --Added about 2019/4/1 ICU 64.1
In this article, the new era "Reiwa" is targeted at applications that incorporate the cross-platform international library ICU (International Components for Unicode). I will explain the actions required to respond to "Iwa)".
The content of this article is based on what is written at here.
Starting with version 64.2 released on April 18, 2019 (Japan time), ICU has incorporated resources to support the new era "Reiwa". Prior to that, from version 63 (63.1 *) released on October 15, 2018, resources for supporting the new era were already incorporated in the form of "temporary era", but ** temporary era No need to specify the issue **. Also, from version 64 (64.1) released on March 27, 2019, "first year" can be handled as a notation for both input and output in addition to one year. At the moment, ICU's support for the new era is specifically the following two points.
Note * The first release is 63.1, not a zero start such as 63.0.
Applications linked to versions of ICU older than v63.1 can be tested by simply replacing the library with v64.2. However, in order to display "Reiwa" or accept it by input, it is only if the application already supports the Japanese calendar format such as "Heisei" or "Showa" by input and output. Therefore, ** If you are only dealing with dates in the Christian era at this time, replacing the library will not immediately support the new era **
The operation is summarized as follows.
Input in the Japanese calendar | 63.1 or less or ICU_ENABLE_TENTATIVE_ERA=false | 63.1 or more and ICU_ENABLE_TENTATIVE_ERA=true | 64.2 or more (no environment variables required) |
---|---|---|---|
May 1, 2019 | May 1, 2019 | QQ May 1, 1st(63.1) /QQ May 1, 1st year(64.1) | May 1, 1st year of Reiwa |
QQ May 1, 1st | Perspective error | QQ May 1, 1st(63.1) /QQ May 1, 1st year(64.1) | Perspective error |
QQ May 1, 1st year | Perspective error | Perspective error(63.1) /QQ May 1, 1st year(64.1) | Perspective error |
May 1, 1st year of Reiwa | Perspective error | Perspective error(63.1) /Perspective error(64.1) | May 1, 1st year of Reiwa |
This result assumes java.util.Calendar.setLenient (true)
and com.ibm.icu.util.Calendar.setCalendarLenient (true)
(both are default values and do not need to be specified). ..
"May 1, 2019" is a date that does not actually exist, but whether or not to make it a parse error depends on the application specifications.
The behavior of setLenient ()
and setCalendarLenient ()
is not covered in this article because it has a wide variety of contents.
Another topic about dealing with the new era "Reiwa" is the handling of ligatures that represent the era with one letter, such as "㍼" and "㍻", but this is also not covered in this article. Hmm.
"First year" notation is supported from ICU v64.1. However, please note that the v64.1 release was before the announcement of the new era "Reiwa", so it does not yet support "Reiwa". Please link with v64.2 or above.
The timeline can be summarized as follows.
season | ICU Version | Supports new era |
---|---|---|
October 2018 | 63.1 | "QQ" ICU_ENABLE_TENTATIVE_ERA=Enabled with true |
March 2019 | 64.1 | "QQ" ICU_ENABLE_TENTATIVE_ERA=Enabled with true,"1 year="First year" correspondence |
April 2019 | 64.2 | Added "Reiwa"(ICU_ENABLE_TENTATIVE_ERAUnnecessary) |
According to this Pull Request (ICU-20536), in addition to v64.2, there are orders for past versions. It seems that the Japanese era has been added. I was able to confirm the following version numbers.
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
Compared to v64.2, these versions do not support the following new eras:
--There is no "first year" support --No support for Reiwa ligatures added in Unicode v12.1 (because older ICUs are based on older Unicode) --There is no correspondence for collation of ligatures (the order of ㍾ <㍽ <㍼ <㍻ <(reiwa ligature))
Now, I will explain how to link ICU version 64.2 (and past Reiwa-compatible ICU versions) to the application and check the operation.
ICU (ICU4C) provides APIs for C and C ++, but here we will use a C ++ example.
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;
//A simple utility to prevent garbled characters on 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;
//Year-based locale
Locale loc_jp1 = Locale::getJapanese();
//Japanese calendar-based locale Designated by LanguageTag
Locale loc_jp2 = Locale("ja-u-ca-japanese");
// (A)Pattern generation class
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)Get the appropriate date format pattern for each locale
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)Generate using a format pattern
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)Click here for how to write 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;
//First, Perth as the Christian era
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;
//Next, Perth as the Japanese calendar
inDate = df_jp2->parse(uin, status);
if (U_FAILURE(status)) {
std::cout << "Parse error (" << u_errorName(status) << ") again." << std::endl;
return 1;
}
}
//Output the entered date in each of the Western and Japanese calendars
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;
}
macOS has an ICU built-in, but to test the OS's ICU without updating it directly, take advantage of Homebrew (http://brew.sh/) to install ICU 64.2. (Released on April 19, 2019)
$ brew install icu4c
The above sample code can be compiled as follows. The environment variable part can also be specified as an argument to the compiler. If the installation destination by brew is different from the example, replace it as appropriate.
$ 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
You can do this as follows: In the first argument, specify the input date in the Western or Japanese calendar.
The execution example is based on v64.2. For results executed under v63.2, replace "first year" with "1 year".
Depending on the setting of setLenient ()
, it can be processed even if you enter the date of the period of Reiwa in Heisei.
Since df_jp1
expects input in the Christian era, Parse error
appears once.
$ ./a.out May 1, 2019
pattern jp1:yyyy year M month d day
pattern jp2:Gy year M month d day
input:May 1, 2019
Parse error (U_ILLEGAL_ARGUMENT_ERROR) try another.
output jp1:May 1, 2019
output jp2:May 1, 1st year of Reiwa
Due to Reiwa support, it is no longer possible to forcibly output dates after "May 1, 1st year of Reiwa" in Heisei using the above sample code.
I don't get a Parse error
.
$ ./a.out May 1, 2019
pattern jp1:yyyy year M month d day
pattern jp2:Gy year M month d day
input:May 1, 2019
output jp1:May 1, 2019
output jp2:May 1, 1st year of Reiwa
Due to Reiwa support, it is no longer possible to forcibly output dates after "May 1, 1st year of Reiwa" in Heisei using the above sample code.
Since df_jp1
expects input in the Christian era, Parse error
appears once.
$ ./a.out May 1, 1st year of Reiwa
pattern jp1:yyyy year M month d day
pattern jp2:Gy year M month d day
input:May 1, 1st year of Reiwa
Parse error (U_ILLEGAL_ARGUMENT_ERROR) try another.
output jp1:May 1, 2019
output jp2:May 1, 1st year of Reiwa
Even if you enter in "1 year", it will be output in "first year".
$ ./a.out May 1, 1st year of Reiwa
pattern jp1:yyyy year M month d day
pattern jp2:Gy year M month d day
input:May 1, 1st year of Reiwa
Parse error (U_ILLEGAL_ARGUMENT_ERROR) try another.
output jp1:May 1, 2019
output jp2:May 1, 1st year of Reiwa
Depending on the setting of setLenient ()
, it can also be processed by entering the date of the Heisei period in Reiwa. In this case, it will be output in Heisei.
$ ./a.out April 1, 1st year of Reiwa
pattern jp1:yyyy year M month d day
pattern jp2:Gy year M month d day
input:April 1, 1st year of Reiwa
Parse error (U_ILLEGAL_ARGUMENT_ERROR) try another.
output jp1:May 1, 2019
output jp2:April 1, 2019
$ ./a.out Reiwa April 1, 1st
pattern jp1:yyyy year M month d day
pattern jp2:Gy year M month d day
input:April 1, 1st year of Reiwa
Parse error (U_ILLEGAL_ARGUMENT_ERROR) try another.
output jp1:May 1, 2019
output jp2:April 1, 2019
Confirmed on Ubuntu 18.04 (64bit).
Download ʻicu4c-64_2-Ubuntu-18.04-x64.tgzfrom the ICU site and unzip it. The extracted directory is referred to as
$ ICUPATH` here.
The rest can be done in much the same way as on 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
Or
$ g++ sample.cpp -licuio -licui18n -licutu -licuuc -licudata
The execution method is the same as for macOS.
Create a project in Visual Studio with Visual C ++
> Windows Desktop
> Windows Console Application
. Here, the solution name is JapaneseNewEraICU
.
Download ʻicu4c-64_2-Win64-MSVC2017.zipfrom the ICU site and unzip it. The extracted folder is referred to as
% ICUPATH%` here.
Set the following values in the solution properties.
item | Value to set |
---|---|
Configuration properties> VC++directory | |
Include directory | %ICUPATH%\include;$(IncludePath) |
Library directory | %ICUPATH%\lib64;$(LibraryPath) |
Configuration properties>Linker>input | |
Additional dependent files | icuio.lib;icuin.lib;icutu.lib;icuuc.lib;%(AdditionalDependencies) |
When I compile with this setting, I get the error "The program cannot start because icuin64.dll is missing from your computer. To resolve this issue, try reinstalling the program." This is an error due to the downloaded ICU DLL not being found in the environment variable% PATH%.
When you run it, open a separate command prompt and
C:\> set PATH=%ICUPATH%\bin64;%PATH%
After running
C:\> .\JapaneseNewEraICU.exe February 16, 2020
And so on.
ʻAdd ICU4J` to the Maven repository dependency.
pom.xml
<!-- https://mvnrepository.com/artifact/com.ibm.icu/icu4j -->
<dependency>
<groupId>com.ibm.icu</groupId>
<artifactId>icu4j</artifactId>
<version>64.2</version>
</dependency>
Here is a code example similar to 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)Click here for how to write DateFormat
//import com.ibm.icu.text.DateFormat;In conjunction with
//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);
}
}
In addition to execution on the IDE, when executing directly from the command, it will be as follows.
$ java -cp ~/.m2/repository/com/ibm/icu/icu4j/64.2/icu4j-64.2.jar:target/classes test.Sample Reiwa May 10, 1st
Starting with Node.js v12.1 released on April 29, 2019, it will be linked to ICU v64.2. Therefore, it is now possible to use Reiwa as the era name without any special designation.
Since there is no library such as ICU for NodeJS, the following is an example of displaying the date of the Reiwa period with a normal Date object.
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
December 20, 1st year of Reiwa(Day)
As explained in "ICU Status" above, ICU release v64.2 with embedded "Reiwa" has been released.
So far, if you have thoroughly tested the display and input of the provisional era in "QQ" using ICU 63.1 / 64.1 or later, you can replace it with ICU v64.2 after the official release to get to the new era. Correspondence is completed.
One point to note is the locale setting that corresponds to the Japanese calendar. The locale ja-u-ca-japanese
used as jp2
in the sample source code is the locale corresponding to the Japanese calendar. It also works in formats such as ja_JP_TRADITIONAL
or ja_JP_JP
.
Since these values are rarely set by the user or system with the environment variable LANG
etc., it is expected that the application will prepare its own logic to determine whether it operates in the Japanese calendar.
The yuan has already been revised, but we hope that this article will help you in the response work in the future.
Recommended Posts