X

Insights and updates on Java SE and OpenJDK from the Java Platform Group Product Management Team

  • March 21, 2019

A new (Japanese) era for Java!

Aurelio Garcia-Ribeyro
Director of Product Management

In day-to-day situations Japan uses the same calendar as most of the world, according to which we are currently in the year 2019 (of the common era).  For official and formal documents, the Japanese calendar uses the same day and month but an era name and years-within-that-era instead of the common era year.  The current Japanese era is Heisei (平成) and the year 2019 corresponds to Heisei 31.

In modern Japan, an era starts with the ascension of a new emperor and last until the ascension of the next emperor.  For example, the 明治 Meiji era lasted until July 30 of 1912 (July 30 Meiji 45). The next era, 大正 Taishō, started on July 31 of 1912 with the ascension of the Taishō Emperor (upon his death an emperor is thereafter referred to by the era of his reign).  You could think of this date as July 31 Taishō 1, except that the first year of new eras are always referred to as 元年(Gan-nen). It would be written instead as “July 31 大正元年” (Taishō Gan-nen).  Note that, unless a new emperor were to ascend on exactly Jan 1, the first year of the new era is shorter than a full calendar year as the first year ends on Dec 31 regardless of which day it started.

In 2016 Emperor Akihito announced plans to abdicate the throne in favor of his son Crown Prince Naruhito.  The Emperor plans to abdicate on April 30, 2019 (April 30 Heisei 31).  On April 1, 2019, the Japanese cabinet will announce the name of the new era which will start on May 1, 2019.

We have taken some steps to prepare for the new era but have to wait until the final announcement, with the new era name, to finalize the updates.

In the JDK in particular, there are a few changes:

  • When a Gregorian date is converted to its equivalent date in the Japanese calendar and rendered as text, it is necessary to know the correct era name.
  • The reverse operation, converting a string representing a date into the correct date, requires parsing the name of the era and knowing to what common era year does it correspond to.
  • Unicode will add a new square character representing the name of the new era.

Starting with JDK 8 the Java APIs have a new Data Time API (see JSR 310), as well as the older java.util.Calendar class, with methods for handling dates.  All relevant APIs have been updated to correctly handle the new era.

In preparation to the new era changes, JDK 12 uses a placeholder name for the new era: 元号 (“NewEra”). Using JDK 12 you can get a feel for how the new era name will be handled on updates released after the new era name is announced.

After the new era name is released, with the next update release (planned for April 16, 2019), all supported JDK releases: 7, 8, 11 LTS, and 12 will be updated to handle the new era.

In all of them, the java.util.Calendar class will be updated to understand and return the correct values:

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

new SimpleDateFormat("GGGGyyyy年M月d日", Locale.forLanguageTag("ja-JP-u-ca-japanese")).
          format(new Calendar.Builder().
          setDate(2019, Calendar.MAY, 1).build().getTime());

//before the update: 平成31年5⽉1⽇, after the update: 元号元年5⽉1⽇
//On versions released after new announcement the 元号 will be replaced with the new era name

and parsing a date using java.text.SimpleDateFormat will work correctly:

import java.text.*;

var sdf = new SimpleDateFormat("GGGGyyyy年M⽉d⽇",
           Locale.forLanguageTag("ja-JP-u-ca-japanese"));  
sdf.setLenient(false);
new SimpleDateFormat("Y-M-d", Locale.US).format(sdf.parse("元号2年2⽉1⽇"));

// => “2020-2-1”
// with 元号 replaced with the new era name

For JDK 8 and later we will also update the new JSR 310 date-time APIs (JDK 7 doesn’t have these new APIs)

import java.time.chrono.*;
import java.time.format.*;
import java.time.temporal.*;

DateTimeFormatter.ofPattern("GGGGy年M⽉d⽇").
         withChronology(JapaneseChronology.INSTANCE).
         withLocale(Locale.JAPAN).
         format(JapaneseDate.of(2020, 2, 1));

// => “元号2年2⽉1⽇”

DateTimeFormatter.ofPattern("u-M-d").format(
         DateTimeFormatter.ofPattern("GGGGy年M⽉d⽇").
         withChronology(JapaneseChronology.INSTANCE).
         withLocale(Locale.JAPAN).
         withResolverStyle(ResolverStyle.STRICT).
         parse("元号2年2⽉1⽇"));

// => “2020-2-1”

JapaneseEra.of(3).getDisplayName(TextStyle.FULL,
         Locale.forLanguageTag("ja-JP-u-ca-japanese"));

// => “元号”
// with 元号  replaced with the new era name

On JDK 8 and later we will also include Unicode U+32FF code point in java.lang.Character class.  The U+32FF code point is reserved for the square character of the Japanese new era.

In summary:

  • JDK updates released after the new Japanese era name is announced will handle the new era name correctly
  • Until the name of the era is released, JDK 12 (and to a lesser extent JDK 11) works similarly to how it will in the future but using 元号 as a placeholder name(*).

(*) Due to an issue with how parsing a date in string format works you will have to wait for the April 2019 JDK updates for parsing to work correctly.

To learn more:

 

Join the discussion

Comments ( 2 )
  • Stuart Smith Friday, March 22, 2019
    Your date format string has spaces in the wrong places. You have "GGGGy 年M 月d 日", but the year value should be next to the year kanji (年), similar for month (⽉) and day (⽇). The string really shouldn't have any spaces for actual Japanese dates, but if you need spaces, then the string should be "GGGGy年 M月 d日".
  • Aurelio Garcia-Ribeyro Tuesday, March 26, 2019
    Thanks for the correction Stuart. I updated the examples and removed the spaces.
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.