如何在本地时区将 java.time.Instant 格式化为字符串?
Posted
技术标签:
【中文标题】如何在本地时区将 java.time.Instant 格式化为字符串?【英文标题】:How do I format a javax.time.Instant as a string in the local time zone? 【发布时间】:2012-11-24 23:29:26 【问题描述】:如何将javax.time.Instant
格式化为本地时区的字符串?以下将本地Instant
转换为UTC,而不是我期望的本地时区。删除对toLocalDateTime()
的调用也是如此。我怎样才能获得当地时间?
public String getDateTimeString( final Instant instant )
checkNotNull( instant );
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
DateTimeFormatter formatter = builder.appendPattern( "yyyyMMddHHmmss" ).toFormatter();
return formatter.print( ZonedDateTime.ofInstant( instant, TimeZone.UTC ).toLocalDateTime() );
注意:我们使用的是旧版本 0.6.3 的 JSR-310 参考实现。
【问题讨论】:
【参考方案1】:在您对我的回答投反对票之前,请注意该问题明确(并以粗体字表示)指的是 JSR-310 参考实现的旧版本 0.6.3!我在 2012 年 12 月问过这个问题,早在 Java 8 和新的日期库到来之前!
我放弃了 JSR-310 课程 DateTimeFormatter
和 ZonedDateTime
,转而使用老式的 java.util.Date
和 java.text.SimpleDateFormat
:
public String getDateTimeString( final Instant instant )
checkNotNull( instant );
DateFormat format = new SimpleDateFormat( "yyyyMMddHHmmss" );
Date date = new Date( instant.toEpochMillisLong() );
return format.format( date );
【讨论】:
我真的认为没有必要采用这种旧方法。 @SimonAndréForsberg:不幸的是我不得不这样做,因为我们使用的是 0.6.3 的 JSR-310 参考实现。幸运的是,虽然我们的产品仍然使用 Java 7,但我们已经转向 Java 8 中出现的最新 JSR-310。 Date 也有一个方法,Date.from(instant)。 Nwm,现在看看你的奇怪版本【参考方案2】:试试这个:
String dateTime = DateTimeFormatter.ISO_ZONED_DATE_TIME.format(
ZonedDateTime.ofInstant(instant, ZoneId.systemDefault())
);
这给出了:
2014-08-25T21:52:07-07:00[America/Los_Angeles]
您可以使用DateTimeFormatter.ISO_ZONED_DATE_TIME
以外的其他内容作为格式化程序来更改格式。 DateTimeFormatter 有一堆预定义的格式化程序,或者你可以定义自己的。
【讨论】:
我在 JSR-310 参考实现的 0.6.3 版本中找不到类ZoneId
。【参考方案3】:
用即将完成的JDK1.8版本回答这个问题
DateTimeFormatter formatter =
DateTimeFormatter.ofPattern("yyyyMMddHHmmss").withZone(ZoneId.systemDefault());
return formatter.format(instant);
关键是Instant
没有任何时区信息。因此,它不能使用任何基于日期/时间字段的模式来格式化,例如“yyyyMMddHHmmss”。通过在DateTimeFormatter
中指定时区,格式化时将瞬间转换为指定的时区,以便正确输出。
另一种方法是转换为ZonedDateTime
:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
return formatter.format(ZonedDateTime.ofInstant(instant, ZoneId.systemDefault()));
这两种方法是等效的,但是如果我的数据对象是Instant
,我通常会选择第一种。
【讨论】:
感谢您的回答。我毫不怀疑它是正确的,但我将不得不等待下一次机会应用此解决方案来代替我实施的解决方案。我还必须等到我们的团队将 JSR-310 的 0.6.3 版本替换为更新的版本或将 JDK 6 替换为 JDK 8。【参考方案4】:您为什么希望它使用本地时区?您明确要求 UTC:
ZonedDateTime.ofInstant(instant, TimeZone.UTC)
只需指定您当地的时区:
ZonedDateTime.ofInstant(instant, TimeZone.getDefault())
【讨论】:
我期待toLocalDateTime()
将其转换为本地或默认时区。显然,我误解了toLocatlDateTime()
的作用。我以为我可以创建一个LocalDateTime
,但是这个类没有将Instant
转换为LocalDateTime
的方法。
@DerekMahar:基本上,本地并不意味着您认为的那样。它只是表示与任何特定时区无关的日期和时间。例如,在世界各地,新年从 1 月 1 日午夜开始。对于任何特定年份,这是一个 LocalDateTime - 一个发生在不同时区的不同瞬间的时间。
不幸的是,JSR-310 不使用 java.util.TimeZone
和类 javax.time.calendar.TimeZone
在 JSR-310 的版本 0.6.3 中似乎没有方法 getDefault()
或任何类似的方法。
@DerekMahar:是的 - 我试图查找文档,但由于那是旧版本,所以我找不到。我确定有一种方法可以以某种方式获取系统默认时区。
据我记得你必须去 Clock 类并调用 getZone()以上是关于如何在本地时区将 java.time.Instant 格式化为字符串?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 PHP 中将默认时区设置为用户的本地时区? [复制]