【问题标题】:How to make DateFormat to parse String date to the assigned timezone如何使日期格式将字符串日期解析为指定的时区
【发布时间】:2017-02-26 12:47:34
【问题描述】:

我有一个“yyyyMMdd”的字符串日期“20160104”,它是 GMT-12 时区。

一直在尝试将其解析为 Java 中的 Date 对象。预期结果是

FastTime = 1451908800000。格林威治标准时间 2016 年 1 月 4 日星期一下午 12:00:00

试过这样的

DateFormat gmtMinus12 = new SimpleDateFormat("yyyyMMdd");
gmtMinus12.setTimeZone(TimeZone.getTimeZone("Etc/GMT-12"));
// gmtMinus12.getCalendar().setTimeZone(TimeZone.getTimeZone("Etc/GMT-12"));
gmtMinus12
    .setCalendar(Calendar.getInstance(TimeZone.getTimeZone("Etc/GMT-12")));

try {
  Date date = gmtMinus12.parse("20160104");

} catch (ParseException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
}

但是解析出来的输出是

快速时间 = 1451822400000 。格林威治标准时间 2016 年 1 月 3 日星期日下午 12:00:00

如何使 DateFormat 假定与分配的时区相同。

非常感谢任何帮助。

提前致谢。

【问题讨论】:

  • 将时区显式添加到输入字符串(和解析模式)
  • 当您指定不同时区的日期时,为什么希望结果是 UTC 午夜?基本上,2016 年 1 月 4 日星期一在 Etc/GMT-12 中从您已经检索到的值开始。
  • 抱歉,我刚刚编辑了我的预期结果。 20160104 00:00 GMT-12。 (假设夏威夷)可能是 20160104 下午 12:00 在伦敦,所以我预计结果将是格林威治标准时间 2016 年 1 月 4 日星期一下午 12:00:00
  • 看起来 DateFormat 正在执行 -12 而不是 +12 小时

标签: java calendar timezone date-format simpledateformat


【解决方案1】:

java.time

您正在使用麻烦的旧日期时间类,现在已被 java.time 类取代。

LocalDate 类表示仅日期值,没有时间和时区。

DateTimeFormatter f = DateTimeFormatter.ofPattern ( "uuuuMMdd" );
LocalDate ld = LocalDate.parse ( "20160104" , f );

现在分配一个时间和一个offset-from-UTC 来传递一个OffsetDateTime 对象。

ZoneOffset offset = ZoneOffset.ofHours ( -12 );
LocalTime lt = LocalTime.MIN;  // 00:00
OffsetTime ot = OffsetTime.of ( lt , offset );
OffsetDateTime odt = ot.atDate ( ld );

odt.toString(): 2016-01-04T00:00-12:00

要查看UTC 中的同一时刻,请提取Instant

Instant instant = odt.toInstant();

instant.toString(): 2016-01-04T12:00:00Z

如您所料,一天中的时间是 UTC 的 4 日中午。

时区

您应该知道GMT-12 不是时区。这是一个offset-from-UTC

time zone 是一个偏移量加上一组用于处理夏令时 (DST) 等异常的规则。

如果您知道预期的时区,您应该应用它而不是仅仅偏移。以continent/region 的格式指定proper time zone name。切勿使用 3-4 个字母的缩写,例如 ESTIST,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

ZoneId z = ZoneId.of( "Asia/Kamchatka" );
ZonedDateTime zdt = odt.atZoneSameInstant( z );

zdt.toString(): 2016-01-05T00:00+12:00[亚洲/堪察加]

关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date.Calendarjava.text.SimpleDateFormat

Joda-Time 项目现在位于maintenance mode,建议迁移到 java.time。

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

从哪里获得 java.time 类?

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

【讨论】:

    【解决方案2】:

    您真正的问题不仅在于使用旧的且笨拙的 API,还在于使用了错误的偏移量。请使用

    Etc/GMT+12 (=UTC-12:00) 而不是 Etc/GMT-12 (=UTC+12:00)。

    过时的 Etc/...-notation 非常令人困惑,因为它使用标准时区偏移的相反符号,另请参阅嵌入的 translation table in TZ-database

    【讨论】:

    • 非常感谢。这实际上解决了我的问题。
    • 除了写“Etc/GMT+12”,你也可以写“GMT-12”(为了更好的可读性)。
    猜你喜欢
    • 2016-05-17
    • 1970-01-01
    • 1970-01-01
    • 2010-12-01
    • 1970-01-01
    • 2019-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多