quarta-feira, 8 de setembro de 2021

🇯🇵 Uma Nova Era (Japonesa) para o Java!

🇯🇵 Uma Nova Era (Japonesa) para o Java!

No dia a dia, o Japão usa o mesmo calendário que a maior parte do mundo, no qual estamos atualmente no ano de 2019 (da era comum). Para documentos oficiais e formais, o calendário japonês usa o mesmo dia e mês, mas um nome de era e anos dentro dessa era, em vez do ano da era comum. A era japonesa atual é Heisei (平成) e o ano de 2019 corresponde a Heisei 31.


🗾 Compreendendo as Eras Japonesas

No Japão moderno, uma era começa com a ascensão de um novo imperador e dura até a ascensão do próximo imperador. Por exemplo, a era 明治 Meiji durou até 30 de julho de 1912 (30 de julho Meiji 45). A era seguinte, 大正 Taishō, começou em 31 de julho de 1912 com a ascensão do Imperador Taishō. A primeira data seria 31 de julho Taishō 1, exceto que o primeiro ano de novas eras é sempre referido como 元年 (Gan-nen). Seria escrito como “31 de julho 大正元年” (Taishō Gan-nen).

Em 2016, o Imperador Akihito anunciou planos de abdicar do trono em favor de seu filho, o Príncipe Herdeiro Naruhito. O plano era abdicar em 30 de abril de 2019 (30 de abril Heisei 31). O nome da nova era, que começaria em 1º de maio de 2019, seria anunciado pelo gabinete japonês em 1º de abril de 2019.


⚙️ Preparativos no JDK para a Nova Era

Foram necessários alguns preparativos para a nova era, mas atualizações finais só poderiam ser concluídas após o anúncio oficial do nome da nova era. No JDK, especificamente, algumas mudanças foram planejadas:

  • Ao converter uma data Gregoriana para sua data equivalente no calendário japonês e renderizá-la como texto, é necessário saber o nome da era correto.
  • A operação inversa, converter uma string representando uma data na data correta, requer analisar o nome da era e saber a qual ano da era comum ela corresponde.
  • O Unicode adicionaria um novo caractere quadrado representando o nome da nova era.

A partir do JDK 8, as APIs Java possuem uma nova Data Time API (consulte o JSR 310), além da classe mais antiga java.util.Calendar, com métodos para manipular datas. Todas as APIs relevantes seriam atualizadas para lidar corretamente com a nova era.

Em preparação para as mudanças, o JDK 12 usaria um nome provisório para a nova era: 元号 (“NewEra”). Usando o JDK 12, seria possível ter uma ideia de como o nome da nova era seria tratado nas atualizações lançadas após o anúncio do nome.

Após o lançamento do nome da nova era, com a próxima atualização (planejada para 16 de abril de 2019), todas as versões suportadas do JDK: 7, 8, 11 LTS e 12 seriam atualizadas para lidar com a nova era.


💻 Exemplos de Código: Antes e Depois da Atualização

Em todas as versões suportadas, a classe java.util.Calendar seria atualizada para entender e retornar os valores corretos.

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());

// Antes da atualização: 平成31年5⽉1⽇
// Depois da atualização: 元号元年5⽉1⽇
// Nas versões lançadas após o novo anúncio, 元号 será substituído pelo novo nome da era.

A análise de uma data usando java.text.SimpleDateFormat funcionaria corretamente:

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⽇"));

// Resultado: “2020-2-1”
// Com 元号 substituído pelo novo nome da era

Para JDK 8 e posteriores, as novas APIs de data e hora JSR 310 também seriam atualizadas (JDK 7 não possui essas novas 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));

// Resultado: “元号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⽇"));

// Resultado: “2020-2-1”
JapaneseEra.of(3).getDisplayName(TextStyle.FULL,
         Locale.forLanguageTag("ja-JP-u-ca-japanese"));

// Resultado: “元号”
// Com 元号 substituído pelo novo nome da era

No JDK 8 e posterior, o ponto de código Unicode U+32FF também seria incluído na classe java.lang.Character. O ponto de código U+32FF é reservado para o caractere quadrado da nova era japonesa.


✅ Resumo das Atualizações

Em resumo:

  • As atualizações do JDK lançadas após o anúncio do novo nome da era japonesa lidariam corretamente com o novo nome da era.
  • Até o nome da era ser divulgado, o JDK 12 (e, em menor extensão, o JDK 11) funcionaria de maneira semelhante à futura, mas usando 元号 como um nome provisório (*).

(*) Devido a um problema na análise de uma data em formato de string, seria necessário aguardar as atualizações do JDK de abril de 2019 para que a análise funcionasse corretamente.