如何显示正确的本地化 DateTime 格式?

How to display the proper localized DateTime format?

我正在编写一个显示 Windows 的时间和日期格式的 JavaFx 程序。这意味着当我更改 Windows 的语言时,程序应该显示新的时间和日期格式。例如在某些地方,时间格式是这样的:

2018 年 12 月 30 日

而在其他地方,是这样显示的:

12.30.2018

我尝试在 Java 中使用 LocalDateTime Class,但这没有任何意义,因为 class 没有时区信息。

private void init()
{
    button = new Button("Update");
    button.setFont(Font.font(null,FontWeight.BOLD,15));
    setBottom(button);
    setAlignment(button, Pos.CENTER);
    setPadding(new Insets(15));

    ldt = LocalDateTime.now();
    label = new Label();
    label.setFont(Font.font(null, FontWeight.BOLD,20));
    label.setTextFill(Color.RED);
    label.setAlignment(Pos.CENTER);

    text = ldt.toString();
    label.setText(text);

    gridPane = new GridPane();
    gridPane.add(label, 0, 0);
    gridPane.setAlignment(Pos.CENTER);
    setCenter(gridPane);        
}

德语:

英语:

如何才能正确显示?

错误class:LocalDateTime

切勿使用 LocalDateTime 来跟踪实际时刻。 缺乏任何时区概念或 offset-from-UTC,LocalDateTime 无法代表片刻。 LocalDateTime 可以知道“2019 年 1 月 23 日中午”,但它 不会 知道你指的是日本东京中午、突尼斯突尼斯中午还是魁北克蒙特利尔中午- 三个截然不同的时刻,每个时刻相隔数小时。

LocalDateTime中的“本地”一词表示任何个地方,或每个个地方。但它 表示任何一个特定的地方。

正确class:ZonedDateTime

要跟踪时刻,请使用 Instant(始终采用 UTC)或 ZonedDateTime(或者 OffsetDateTime)。

Continent/Region的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用 2-4 个字母的缩写,例如 ESTIST,因为它们 不是 真正的时区,不是标准化的,甚至不是唯一的(!)。

ZoneId z = ZoneId.of( "America/Montreal" ) ;  
ZonedDateTime zdt = ZonedDateTime.now( z ) ; // Capture the current moment as seen through the wall-clock time used by the people of a particular region (a time zone). 
Instant instant = zdt.toInstant() ;  // Adjust from a zone to UTC, if needed. An `Instant` is always in UTC by definition. 

如果未指定时区,JVM 将隐式应用其当前默认时区。该默认值在运行时可能 change at any moment (!),因此您的结果可能会有所不同。最好将 desired/expected 时区明确指定为参数。如果关键,请与您的用户确认区域。

Auto-localize

DateTimeFormatter class 可以在生成表示 date-time object.

值的文本时自动本地化

要本地化,请指定:

  • FormatStyle 确定字符串的长度或缩写。
  • Locale判断:
    • 人类语言 翻译日名、月名等。
    • 文化规范决定缩写、大写、标点符号、分隔符等问题。

示例:

Locale l = Locale.CANADA_FRENCH ;   // Or Locale.US, Locale.JAPAN, etc.
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL )
                                       .withLocale( l );
String output = zdt.format( f );

请注意,语言环境和时区彼此 没有任何关系 – 正交问题。一位来自魁北克的工程师在印度参加一个会议,可能希望看到以她的母语法语和加拿大文化规范呈现的活动日程,并且 date-time 显示在当地印度时区。


关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

您可以直接与您的数据库交换 java.time objects。使用 JDBC driver compliant with JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql.* classes.

在哪里获取java.time classes?

ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.