【问题标题】:DateFormat format method doesn't display a parsed date to a particular TimeZoneDateFormat 格式方法不显示特定时区的解析日期
【发布时间】:2016-03-15 23:58:25
【问题描述】:

我通过 SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").parse(DateinString) 将日期字符串转换为日期。
这里不是转换为 UTC,而是转换为我的本地时区。我通过 DateFormat 的格式方法显示这个解析的日期来检查它。

所以我必须将其重新格式化回 UTC。现在,当我尝试通过相同的格式方法将此解析后的日期显示为 UTC 时区时,它仍然显示在本地时区中。以下是我将解析日期格式化为 UTC 的代码-

Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone("UTC"));
cal.setTime(alreadyParsedDateTime); // 
System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(cal.getTime()));       

我的示例日期字符串是“2015-12-23T15:00:00-0800”
解析后 -- alreadyParsedDateTime.toString():: Thu Dec 24 04:30:00 IST 2015
解析后—— System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(alreadyParsedDateTime)):: 2015-12-24T04:30:00

经过上面提到的将解析日期重新格式化为UTC-- System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(cal.getTime())):: 2015-12-24T04:30:00

预计日期格式为:: 2015-12-23T23:00:00

我不知道为什么格式化方法不能以预期的方式工作,或者有什么技巧可以做到这一点。请帮忙..

【问题讨论】:

  • 查看DateFormat(以及SimpleDateFormat)的setTimeZone()方法。
  • 仅供参考,麻烦的旧日期时间类,如 java.util.Calendarjava.text.SimpleDateFormat 现在是 legacy,被 Java 8 和 Java 9 中内置的 java.time 类所取代。参见 @987654324 @.

标签: java date datetime time


【解决方案1】:

这里有两个不同的主题;解析和格式化。

1。解析

SimpleDateFormat.parse() 将尝试从提供的日期字符串中解析时区。如果您正在解析的日期字符串不包含明确的时区,则将使用 SimpleDateFormat 对象上的“默认”时区。您可以使用setTimeZone() 方法设置默认时区。请参阅 SimpleDateFormat.parse()DateFormat.setTimeZone() 的 API 文档以供参考。

这是一个示例,显示了解析是如何受setTimeZone() 设置的时区影响的:

    String dateString = "2015.12.10 13:58:18";

    SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
    sdf1.setTimeZone(TimeZone.getTimeZone("GMT"));
    Date date1 = sdf1.parse(dateString);

    SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
    sdf2.setTimeZone(TimeZone.getTimeZone("EST"));
    Date date2 = sdf2.parse(dateString);

    // Shows that the parsing honours time zone -- will print:
    // Thu Dec 10 14:58:18 CET 2015 (original date was parsed as GMT)
    // Thu Dec 10 19:58:18 CET 2015 (original date was parsed as EST)
    System.out.println(date1);
    System.out.println(date2);

2。格式化

假设日期已正确解析,那么您的问题在于格式。您需要为用于格式化的实际 SimpleDateFormat 对象设置时区。我修改了您的代码来执行此操作,它现在将打印您所表达的内容:

    Calendar cal = Calendar.getInstance();
    cal.setTime(alreadyParsedDateTime);
    SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
    sdf3.setTimeZone(TimeZone.getTimeZone("UTC"));

    // Prints: 2015-12-23T23:00:00 for your example date string
    System.out.println(sdf3.format(cal.getTime()));

【讨论】:

  • 我已经尝试过了,但没有结果。 SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
  • 是的,你的例子是正确的,但我的 dateString ("2015-12-23T15:00:00-0800") 也包含 TimeZone,这就是为什么 setTimeZone 可能不起作用。在这里我用 SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") 解析这个 dateString。
  • 非常感谢,现在可以使用了。你救了我的一天! :-)
  • 很好的答案,但是……仅供参考,麻烦的旧日期时间类,如 java.util.Datejava.util.Calendarjava.text.SimpleDateFormat 现在是 legacy,被构建的 java.time 类所取代进入 Java 8 和 Java 9。请参阅 Tutorial by Oracle
  • @BasilBourque 新的 java.time 类很棒,但是 API 文档中没有官方声明说 java.util.Calendarjava.util.SimpleDateFormat 等是“遗留”(它们没有标记不推荐使用或描述为“遗留”或“过时”)。至于java.util.Date,大部分从1.1开始就被弃用了;它应该只用于表示时间的瞬间,而不是用于解析或格式化。
【解决方案2】:

tl;博士

UTC 当前时刻。

Instant.now()        // Capture current moment in UTC.
    .toString()      // Generate string in standard ISO 8601 format.

2018-02-11T22:13:28.650328Z

调整到另一个时区。

instant.atZone(      // Apply a `ZoneId` to `Instant` object to get a `ZonedDateTime` object.
    ZoneId.of( "Pacific/Auckland" )
).toString()

2018-02-12T11:13:28.650328+13:00[太平洋/奥克兰]

或直接将当前时刻捕捉到该区域。

ZonedDateTime.now(   // Capture current moment as seen on the wall-clock time of the people in a particular region.
    ZoneId.of( "Pacific/Auckland" )
).toString()         // Generate string in standard ISO 8601 format, wisely extended by appending the name of the time zone in square brackets.

2018-02-12T11:13:28.650328+13:00[太平洋/奥克兰]

详情

Answer by Grodriguez 正确但已过时。

java.time

现代方法使用 java.time 类来代替麻烦的旧旧日期时间类。

您的输入字符串符合ISO 8601 格式标准。 java.time 类在解析/生成字符串时默认使用这些格式。所以不需要指定格式模式。

Instant 类表示UTC 中时间轴上的时刻,分辨率为nanoseconds(最多九 (9) 位小数)。

捕捉UTC中的当前时刻。

Instant instant = Instant.now() ;  // Current moment in UTC.

要通过另一个地区(时区)的人们使用的挂钟时间的镜头来查看同一时刻,请应用ZoneId 以获取ZonedDateTime 对象。

ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

请注意,我们在这里使用的是智能对象,而不是哑字符串。不要将日期时间对象与可能以文本形式表示其值的纯字符串混为一谈。

如果要生成标准ISO 8601 格式的字符串,请调用toString 方法。

String outputA = instant.toString() ;
String outputB = zdt.toString() ;

要生成其他格式的字符串,请使用DateTimeFormatterDateTimeFormatterBuilder 类。两者都在 Stack Overflow 上得到了广泛的介绍,因此请搜索更多信息。


关于java.time

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

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

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

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

从哪里获得 java.time 类?

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多