为什么 Instant.now() 有时格式不同?

Vic*_*cky 7 java date java-8 java-time

我的代码如下所示:

String PROPER_DATE_FORMAT = "yyyy-MM-dd";
String format = "yyyy-MM-dd'T'HH:mm:ss.SSSX";

SimpleDateFormat sdf = new SimpleDateFormat(format);
Date d = sdf.parse(Instant.now().toString());
SimpleDateFormat properFormat = new SimpleDateFormat(PROPER_DATE_FORMAT);
String formatterDate = properFormat.format(d);
Run Code Online (Sandbox Code Playgroud)

现在,大多数时候,这段代码可以工作,但时不时地,我会返回 Instant.now() ,2018-05-25T18:56:09Z然后它会抛出一个异常,因为格式不匹配。

为什么有时会不一致?

例外的是java.lang.RuntimeException: java.text.ParseException: Unparseable date: "2018-05-25T18:56:09Z"

通常,whenInstant.now().toString()会返回一个具有上述格式的字符串。同样,这段代码在大多数情况下都有效,但也有几次不起作用,我很困惑为什么。

我想是否是因为末尾有一个零但没有显示,但我不相信,因为我能够通过 Instant. 获得 2018-05-25T20:06:58.900Z 的值。 now().toString()

bru*_*uno 8

当纳秒为零时,它不包含在格式化字符串中。因此输出的格式为“yyyy-MM-dd'T'HH:mm:ssX”

您可以通过以下方式看到差异:

public static void main(String[] args) throws ParseException {
        final Instant now = Instant.now();
        System.out.println("Now:\t" +  now);

        final Instant zeroedNow = now.with(ChronoField.NANO_OF_SECOND, 0);
        System.out.println("Zeroed:\t" + zeroedNow);
} 
Run Code Online (Sandbox Code Playgroud)

输出看起来像

Now:    2018-05-25T20:23:54.208Z
Zeroed: 2018-05-25T20:23:54Z
Run Code Online (Sandbox Code Playgroud)


Tho*_*ger 8

您的代码失败,因为Instant.toString()被记录为

使用的格式与 DateTimeFormatter.ISO_INSTANT 相同。

并根据DateTimeFormatter.html#ISO_INSTANT

纳秒根据需要输出零、三、六或九位数字

因此,您有千分之一的机会获得即时,000而您的代码会失败。


无论如何,您的代码不必要地复杂,可以替换为

String formattedDate = DateTimeFormatter.ofPattern("yyyy-MM-dd")
    .withZone(ZoneId.systemDefault())
    .format(Instant.now());
Run Code Online (Sandbox Code Playgroud)

不需要将其转换Instant为字符串,只需将其解析为日期,然后再次将其转换为字符串。