java - 如何根据区域设置获取带有时区的数据时间模式?

标签 java timezone datetime-format java-time

以下代码是我已经拥有的代码:

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

通过上面的代码,我能够根据区域设置获得正确的日期/时间模式。例如:“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”。

我使用 Java 8。

最佳答案

z任何语言环境的 SimpleDateFormat 的有效模式(根据 javadoc,它是时区指示符)。

唯一的区别是,对于某些值,结果可能取决于区域设置(例如:如果您使用 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 新的日期/时间 API

旧类(DateCalendarSimpleDateFormat)有 lots of problemsdesign issues ,并且它们正在被新的 API 取代。

当您使用 Java 8 时,请考虑使用 new java.time API 。更容易,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 .

关于java - 如何根据区域设置获取带有时区的数据时间模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45825975/

相关文章:

java - 我应该创建一个新变量还是始终访问类对象中的数据?

java - 选择 hibernate 最大日期的行

timezone - 日期是否在 ISO 8601 的目标时区?

c# - DateTime ParseExact 在其他服务器上的不同行为

c# - 将 double 转换为日期时间?

java - 递归字符串连接

java - 自动缩进 Java 和 HTML 文件的脚本或程序

c# - 缺少 Microsoft 时区

mysql - 克服 MySQL Select 中的时区差异

c# - 将 C# 日期时间转换为 Javascript 日期