如何根据语言环境获取带时区的数据时间模式?

How to get the data time pattern with time zone based on the locale?

下面的代码是我已有的:

DateFormat f = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Java_Locale);
SimpleDateFormat sf = (SimpleDateFormat) f;
String pattern = sf.toPattern();

使用上面的代码,我可以根据语言环境获得正确的 date/time 模式。例如:"M/d/yy h:mm a" 代表美国英语,"yy-M-d ah:mm" 代表中文。

但是,该模式没有时区信息。我希望能够将时区添加到模式中。例如,"M/d/yy h:mm a z" 表示英语,但我不想指定其他语言环境的模式。我希望根据给定的语言环境获得正确的时区模式,类似于其他语言环境的 "M/d/yy h:mm a z"。

我用Java8.

zSimpleDateFormat 的有效模式(根据 javadoc,它是时区指示符)对于 any 语言环境。

唯一的区别是,对于某些值,结果可能取决于区域设置(例如:如果您使用 zzzz,时区 America/Los_Angeles 可以格式化为 太平洋夏令时 英语(因为它目前处于夏令时)或 Horário de luz natural do Pacífico 葡萄牙语),但模式 z 本身并不无效语言环境。

getDateTimeInstance将使用预定义的内置硬编码模式。由于短模式通常不包括时区,您必须手动添加 z

DateFormat f = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.ENGLISH);
SimpleDateFormat sf = (SimpleDateFormat) f;
String pattern = sf.toPattern();

// add z to the format, use the same locale
SimpleDateFormat sdf = new SimpleDateFormat(pattern + " z", Locale.ENGLISH);

Java 新 Date/Time API

旧的 类(DateCalendarSimpleDateFormat)有 lots of problems and design issues,它们正在被新的 APIs.

由于您正在使用 Java 8,请考虑使用 new java.time API. It's easier, less bugged and less error-prone than the old APIs.

不幸的是,预定义的内置模式仍然是硬编码的,您必须手动添加时区,但至少您将摆脱上面链接中解释的所有问题:

import java.time.chrono.IsoChronology;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.FormatStyle;
import java.time.ZonedDateTime;

// get built-in localized format for a specified locale
String pattern = DateTimeFormatterBuilder.getLocalizedDateTimePattern(FormatStyle.SHORT,
                     FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.ENGLISH);
// create a formatter, add the timezone manually, use same locale
DateTimeFormatter fmt = DateTimeFormatter.ofPattern(pattern + " z", Locale.ENGLISH);
// format a date
System.out.println(fmt.format(ZonedDateTime.now()));

当您打印时区时,我使用的是 ZonedDateTime,它表示特定时区的日期和时间。查看 tutorial 了解有关新日期类型的更多详细信息。

DateTimeFormatter 也比 SimpleDateFormat 有更多选项。查看 javadoc 了解详情。


如果您仍然需要与 java.util.Date 的互操作性,您可以轻松地将其转换为新的 API:

// convert to Instant (UTC)
ZonedDateTime z = new Date().toInstant()
    // convert to some timezone
    .atZone(ZoneId.of("Europe/London"));

API 使用 IANA timezones names(格式总是 Continent/City,如 America/Sao_PauloEurope/Berlin)。 避免使用 3 个字母的缩写(如 CSTPST),因为它们是 ambiguous and not standard.

DateFormat f = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.FULL, Java_Locale);

FULL时间样式包括时区。不过,这会使时间变得更加复杂。

注意:仅向模式字符串添加 z 并不总是准确的。例如,阿拉伯语语言环境将时区放在日期和时间之间:

Locale Java_Locale = Locale.forLanguageTag("ar");
DateFormat f = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.FULL, Java_Locale);
SimpleDateFormat sf = (SimpleDateFormat) f;
String pattern = sf.toPattern(); // "dd/MM/yy z hh:mm:ss a"