Java 将即时设置为字符串格式

Java 将即时设置为字符串格式,java,datetime,java-8,datetime-format,java-time,Java,Datetime,Java 8,Datetime Format,Java Time,我正在尝试使用新的java 8时间api和模式将瞬间格式化为字符串: Instant instant = ...; String out = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(instant); 使用上面的代码,我得到了一个异常,它抱怨一个不受支持的字段: java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: YearOfE

我正在尝试使用新的java 8时间api和模式将瞬间格式化为字符串:

Instant instant = ...;
String out = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(instant);
使用上面的代码,我得到了一个异常,它抱怨一个不受支持的字段:

java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: YearOfEra
    at java.time.Instant.getLong(Instant.java:608)
    at java.time.format.DateTimePrintContext.getValue(DateTimePrintContext.java:298)
    ...
我相信这可能会有所帮助,您可能需要使用某种localdate变体,而不是instant


我相信这可能会有所帮助,您可能需要使用某种localdate变量而不是instant

instant类不包含区域信息,它只存储UNIX历元(即UTC 1070年1月1日)的时间戳(以毫秒为单位)。 所以,格式化程序无法打印日期,因为日期总是针对具体时区打印的。 您应该将时区设置为formatter,一切都会很好,如下所示:

Instant instant = Instant.ofEpochMilli(92554380000L);
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withLocale(Locale.UK).withZone(ZoneOffset.UTC);
assert formatter.format(instant).equals("07/12/72 05:33");
assert instant.toString().equals("1972-12-07T05:33:00Z");

Instant
类不包含区域信息,它只存储UNIX历元(即UTC 1070年1月1日)的时间戳(以毫秒为单位)。 所以,格式化程序无法打印日期,因为日期总是针对具体时区打印的。 您应该将时区设置为formatter,一切都会很好,如下所示:

Instant instant = Instant.ofEpochMilli(92554380000L);
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withLocale(Locale.UK).withZone(ZoneOffset.UTC);
assert formatter.format(instant).equals("07/12/72 05:33");
assert instant.toString().equals("1972-12-07T05:33:00Z");
时区 需要设置a的格式。如果没有时区,格式化程序不知道如何将“即时”时间字段转换为“人工日期”时间字段,因此引发异常

时区可以使用直接添加到格式化程序

如果您特别想要没有明确时区的ISO-8601格式 (正如OP所问),时区隐含UTC,您需要

DateTimeFormatter.ISO_LOCAL_DATE_TIME.withZone(ZoneId.from(ZoneOffset.UTC))
生成字符串 现在,使用该格式化程序生成即时消息的字符串表示形式

Instant instant = Instant.now();
String output = formatter.format( instant );
转储到控制台

System.out.println("formatter: " + formatter + " with zone: " + formatter.getZone() + " and Locale: " + formatter.getLocale() );
System.out.println("instant: " + instant );
System.out.println("output: " + output );
跑步的时候

formatter:Localized(SHORT,SHORT),区域:US/Pacific,区域设置:en_GB
瞬间:2015-06-02T21:34:33.616Z
输出:2015年6月2日14:34
时区 需要设置a的格式。如果没有时区,格式化程序不知道如何将“即时”时间字段转换为“人工日期”时间字段,因此引发异常

时区可以使用直接添加到格式化程序

如果您特别想要没有明确时区的ISO-8601格式 (正如OP所问),时区隐含UTC,您需要

DateTimeFormatter.ISO_LOCAL_DATE_TIME.withZone(ZoneId.from(ZoneOffset.UTC))
生成字符串 现在,使用该格式化程序生成即时消息的字符串表示形式

Instant instant = Instant.now();
String output = formatter.format( instant );
转储到控制台

System.out.println("formatter: " + formatter + " with zone: " + formatter.getZone() + " and Locale: " + formatter.getLocale() );
System.out.println("instant: " + instant );
System.out.println("output: " + output );
跑步的时候

formatter:Localized(SHORT,SHORT),区域:US/Pacific,区域设置:en_GB
瞬间:2015-06-02T21:34:33.616Z
输出:2015年6月2日14:34

或者如果您仍然希望使用从模式创建的格式化程序 您可以只使用LocalDateTime而不是Instant:

LocalDateTime datetime = LocalDateTime.now();
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(datetime)

或者,如果您仍然想使用从模式创建的格式化程序 您可以只使用LocalDateTime而不是Instant:

LocalDateTime datetime = LocalDateTime.now();
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(datetime)
这使您无需转换为UTC。但是,其他一些语言的时间框架可能不支持毫秒,因此您应该这样做

DateTimeFormatter.ISO_INSTANT.format(Instant.now().truncatedTo(ChronoUnit.SECONDS))
这使您无需转换为UTC。但是,其他一些语言的时间框架可能不支持毫秒,因此您应该这样做

DateTimeFormatter.ISO_INSTANT.format(Instant.now().truncatedTo(ChronoUnit.SECONDS))

实例已经是UTC格式,并且已经具有默认的日期格式yyyy MM dd。如果您对此感到满意,并且不想弄乱时区或格式,您也可以
toString()
it:

Instant instant = Instant.now();
instant.toString()
output: 2020-02-06T18:01:55.648475Z

不需要t和Z吗?(Z表示该日期为UTC。Z表示“Zulu”又名“零小时偏移量”,又名UTC):


想要毫秒而不是纳秒吗?(这样您就可以将其放到sql查询中):


等等。

实例已经是UTC格式,并且已经具有默认的日期格式yyyy MM dd。如果您对此感到满意,并且不想弄乱时区或格式,您也可以
toString()
it:

Instant instant = Instant.now();
instant.toString()
output: 2020-02-06T18:01:55.648475Z

不需要t和Z吗?(Z表示该日期为UTC。Z表示“Zulu”又名“零小时偏移量”,又名UTC):


想要毫秒而不是纳秒吗?(这样您就可以将其放到sql查询中):


等等。

谢谢!!顺便说一句,指向年份的异常“unsupported field”非常迟钝。也许应该检测到这种情况,并立即抛出一个直接指向丢失的区域id的异常!更奇怪的是,如果您包括.withZone(例如.withZone(ZoneId.of(“Z”))并格式化LocalDateTime,则该区域将被忽略!因此,只要包含.withZone(),就可以对Instant和LocalDateTime使用相同的格式化程序,而不会影响后者显示的时间。为什么很难接受Instant的时区为GMT的事实?@KorayTugay,因为虽然迂腐的“Instant已经是GMT”评论可能是正确的,当遇到抛出的异常跟踪时,它们根本没有帮助,因为在不指定时区的情况下格式化瞬间是行不通的。如果格式化程序默认为GMT会很好,但是很好。现在,这将为您提供
yyyy-MM-dd hh:MM:ss
format:
DateTimeFormatter-formatter=DateTimeFormatter.of模式(“yyyy-MM-dd hh:MM:ss”).withZone(ZoneId.of(“Europe/Paris”)谢谢!!顺便说一句,指向年份的异常“unsupported field”非常迟钝。也许应该检测到这种情况,并立即抛出一个直接指向丢失的区域id的异常!更奇怪的是,如果您包括.withZone(例如.withZone(ZoneId.of(“Z”))并格式化LocalDateTime,则该区域将被忽略!因此,只要包含.withZone(),就可以对Instant和LocalDateTime使用相同的格式化程序,而不会影响后者显示的时间。为什么很难接受Instant的时区为GMT的事实?@KorayTugay,因为虽然迂腐的“Instant已经是GMT”评论可能是正确的,当遇到抛出的异常跟踪时,它们根本没有帮助,因为在不指定时区的情况下格式化瞬间是行不通的。如果格式化程序默认为GMT,那就太好了。现在,这将为您提供
yyyy-MM-dd hh:MM:ss
format:
DateTimeFormatter-formatter=DateTime