首页 > 解决方案 > 使用时区 JAVA API 翻译时区名称

问题描述

在以下代码中:

import java.util.*;
public class HelloWorld{

     public static void main(String []args){
        Locale locale = new Locale("zh","CN");
        TimeZone zone = TimeZone.getTimeZone("America/Chicago");
        String displayNameShort = zone.getDisplayName(true, TimeZone.SHORT, locale);
        System.out.println("Short time zone name - " + displayNameShort);
        String displayNameLong = zone.getDisplayName(true, TimeZone.LONG, locale);
        System.out.println("Long time zone name - " + displayNameLong);
     }
}
Output - 
Short time zone name - CDT // Not translated
Long time zone name - 中央夏令时 // Translated

我能够翻译时区的完整显示名称,但无法翻译时区的缩写。

标签: javatimezone

解决方案


伪时区名称

这些 2-4 个字母的“短时区”名称实际上并不是实时时区名称。它们没有标准化。他们甚至不是独一无二的!

例子:

  • “CST”=“中部标准时间”(美洲)“中国标准时间”
  • "IST" = "印度标准时间""爱尔兰标准时间"

由于没有官方定义,我看不出您会如何期望本地化版本。

坚持使用实时时区名称,Continent/Region例如Africa/Tunis,America/ChicagoPacific/Auckland.

java.time类:ZoneId&ZoneOffset

该类TimeZone是与 Java 的最早版本捆绑在一起的可怕日期时间类的一部分,例如Date& Calendar。这些在几年前被JSR 310 中定义的现代java.time类所取代。

TimeZone被替换为ZoneIdandZoneOffset类。

TextStyle本地化ZoneId#getDisplayName

该类ZoneId提供了一种getDisplayName方法。该方法采用 , 的参数TextStyle来确定长度或缩写。

让我们编写代码来使用六种文本样式中的每一种。

System.out.println( "Java version: " + Runtime.version() );
System.out.println(
        "tz database version: " +
                java.time.zone.ZoneRulesProvider
                        .getVersions( "UTC" )
                        .lastEntry()
                        .getKey()
                + "\n"
);

ZoneId zoneId = ZoneId.of( "America/Chicago" );
Locale locale = Locale.US;  // new Locale( "zh" , "CN" );

for ( TextStyle textStyle : TextStyle.values() ) {
    String output = zoneId.getDisplayName( textStyle , locale );
    System.out.println( "output for " + textStyle + " = " + output );
}

跑的时候。

Java version: 17+35-2724
tz database version: 2021a

output for FULL = 北美中部时间
output for FULL_STANDALONE = 北美中部时间
output for SHORT = CT
output for SHORT_STANDALONE = CT
output for NARROW = America/Chicago
output for NARROW_STANDALONE = CT

当运行Locale.US.

Java version: 17+35-2724
tz database version: 2021a

output for FULL = Central Time
output for FULL_STANDALONE = Central Time
output for SHORT = CT
output for SHORT_STANDALONE = CT
output for NARROW = America/Chicago
output for NARROW_STANDALONE = CT

FormatStyleDateTimeFormatter.ofLocalizedDateTime

让我们尝试一些代码,将时区与ZonedDateTime对象一起使用。

这里我们使用DateTimeFormatterfromofLocalizedDateTime来自动本地化我们生成的文本。这个类需要一个参数FormatStyle(不要与TextStyle我们上面看到的混淆)来确定长度与缩写。所以我们循环所有四个枚举对象FormatStyle: FULL, LONG, MEDIUM, & SHORT

Locale locale = new Locale( "zh" , "CN" );
ZonedDateTime zonedDateTime = ZonedDateTime.now( ZoneId.of( "America/Chicago" ) );

for ( FormatStyle formatStyle : FormatStyle.values() ) {
    DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime( formatStyle ).withLocale( locale );
    String output = zonedDateTime.format( formatter );
    System.out.println( "output for FormatStyle " + formatStyle + " = " + output );
}

跑的时候。

output for FormatStyle FULL = 2021年8月9日星期一 北美中部夏令时间 上午12:19:42
output for FormatStyle LONG = 2021年8月9日 CDT 上午12:19:42
output for FormatStyle MEDIUM = 2021年8月9日 上午12:19:42
output for FormatStyle SHORT = 2021/8/9 上午12:19

而当运行Locale.US.

output for FormatStyle FULL = Monday, August 9, 2021 at 12:20:40 AM Central Daylight Time
output for FormatStyle LONG = August 9, 2021 at 12:20:40 AM CDT
output for FormatStyle MEDIUM = Aug 9, 2021, 12:20:40 AM
output for FormatStyle SHORT = 8/9/21, 12:20 AM

我们可以看到,对于两种语言环境,LONG格式样式都CDT用作时区的非官方简称。


最后,我再次建议您尽可能避免使用这些 2-4 个字母的伪区域名称。并且在将日期时间数据交换为文本时,切勿本地化;始终使用ISO 8601格式进行数据交换。


推荐阅读