Instant与Java中的时间戳不同吗?

时间:2017-06-10 18:41:57

标签: time java-8 formatting timezone-offset

我似乎得到了Java的时间戳的不同表示如下:

en_US
2017-06-10 14:34:35.088
2017-06-10T18:34:35.102Z

以下调用:

System.out.println(Locale.getDefault());
System.out.println(new Timestamp(System.currentTimeMillis()));
System.out.println(Instant.now());

哪些其他配置有助于均衡上面显示的时间表示之间的4小时偏移?感谢。

1 个答案:

答案 0 :(得分:2)

一个是您当地的时间,一个是UTC。这更多地取决于它的打印方式而不是实际(内部)值。

要使两者显示相等,您可以

  • -Duser.timezone=UTC传递给您的VM,将您的本地时区设置为UTC。
  • Instant格式化为您当地的时区:

    DateTimeFormatter formatter = 
    DateTimeFormatter.ISO_LOCAL_DATE_TIME.withZone(ZoneId.systemDefault());
    System.out.println(formatter.format(Instant.now()));
    
  • Timestamp转换为Instant

    new Timestamp(System.currentTimeMillis()).toInstant();
    

完整代码:

public static void main(String[] args) {
    DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME.withZone(ZoneId.systemDefault());
    Timestamp timestamp = new Timestamp(System.currentTimeMillis());
    Instant instant = Instant.now();
    System.out.println("Timestamp: " + timestamp);
    System.out.println("Instant: " + instant);
    System.out.println("Instant to local: " + formatter.format(instant));
    System.out.println("Timestamp to UTC: " + timestamp.toInstant());
}

将打印出来(在我当地时区):

Timestamp: 2017-06-10 21:17:13.935
Instant: 2017-06-10T19:17:13.935Z
Instant to local: 2017-06-10T21:17:13.935
Timestamp to UTC: 2017-06-10T19:17:13.935Z

所以有一些全局设置"虽然它可能不会做你想要的。默认为Instant will always be printed in UTC

如果您只想使用本地日期,并且不限于Instant,则还有两个*更多选项:

  • Instant转换为ZonedDateTime

    ZonedDateTime.ofInstant(Instant.now(), ZoneId.systemDefault());
    
  • 或完全跳过Instant赞成ZonedDateTime.now()

*根据您的需求,您可以与ZonedDateTimeOffsetDateTime交换LocalDateTime

编辑:神奇的方式。

public static void main(String[] args) throws Exception {
    Field field = DateTimeFormatter.class.getField("ISO_INSTANT");
    field.setAccessible(true);
    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
    field.set(null, DateTimeFormatter.ISO_LOCAL_DATE_TIME.withZone(ZoneId.systemDefault()));

    System.out.println(new Timestamp(System.currentTimeMillis()));
    System.out.println(Instant.now());
}

使用反射将DateTimeFormatter.ISO_INSTANT更改为使用当地时间的格式化程序。可能无法使用SecurityManager,可能会产生一个或多个不需要的副作用。参见例如Change private static final field using Java reflection了解详情。