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

时间:2017-08-22 19:55:39

标签: 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。

2 个答案:

答案 0 :(得分:3)

对于任何区域设置,

zSimpleDateFormat的有效模式(根据javadoc,它是时区指示符。)

唯一的区别是,对于某些值,结果可能与区域设置有关(例如:如果您使用zzzz,则时区America/Los_Angeles可以格式化为太平洋夏令时英语(因为它目前处于夏令时)或Horáriodeluz naturaldoPací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取代。< / p>

当您使用 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

答案 1 :(得分:1)

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"