Java LocalDateTime.parse方法支持毫秒精度,但可以选择微秒精度。

9

有没有一种方法可以创建一个LocalDateTime模式,该模式将解析具有至少毫秒精度但可选微秒精度的日期/时间,例如在以下情况下,毫秒日期/时间可以成功解析,但微秒的第二个日期/时间无法解析。我认为模式中方括号“[]”中的可选指示符将允许此工作:

DateTimeFormatter DATE_TIME_FORMATTER = 
    DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS[SSS]");
System.out.println(LocalDateTime.parse("2019-02-14 11:04:52.784", DATE_TIME_FORMATTER));     
System.out.println(LocalDateTime.parse("2019-02-14 11:04:52.784108", DATE_TIME_FORMATTER));
1个回答

14

技巧一

    String withMillis = "2019-02-14 11:04:52.784";
    String withMicros = "2019-02-14 11:04:52.784108";

    System.out.println(LocalDateTime.parse(withMillis.replace(' ', 'T')));
    System.out.println(LocalDateTime.parse(withMicros.replace(' ', 'T')));
2019-02-14T11:04:52.784
2019-02-14T11:04:52.784108
当我们将字符串中间的空格替换为T时,该字符串符合ISO 8601标准格式,即LocalDateTime和java.time的其他类默认解析(和打印)的格式,也就是说,没有任何显式格式化程序。因此,这是一个简单的解决方案。
第二个技巧:
像您尝试的那样,可以使其工作。只是您不能使用中括号在SSSSSS序列中间进行拆分。
static final DateTimeFormatter DATE_TIME_FORMATTER = 
        DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.[SSSSSS][SSS]");

接下来:

    System.out.println(LocalDateTime.parse(withMillis, DATE_TIME_FORMATTER));     
    System.out.println(LocalDateTime.parse(withMicros, DATE_TIME_FORMATTER));

我可选地指定6位小数,然后再选择3位小数。我们需要按照这个顺序。如果我们输入[SSS][SSSSSS]并尝试解析6位小数,则格式化程序将首先解析3位小数,然后抛出异常,因为它无法使用SSSSSS解析剩余的3位小数。这有点像一个hack,因为它还将接受没有任何小数点的小数点,并且如果我们给它9个小数,可能会发出非常令人困惑的错误消息(或者甚至给出不正确的结果)。
好的解决方案:使用生成器
编辑:自第一个答案版本以来,我已经稍微改进了生成器。
static final DateTimeFormatter DATE_TIME_FORMATTER = 
        new DateTimeFormatterBuilder().append(DateTimeFormatter.ISO_LOCAL_DATE)
                .appendLiteral(' ')
                .append(DateTimeFormatter.ISO_LOCAL_TIME)
                .toFormatter();

DateTimeFormatter.ISO_LOCAL_TIME可以解析从0到9位小数的秒,因此我们可以在自己的格式化器中重用该格式化程序。

原始的构建者:

static final DateTimeFormatter DATE_TIME_FORMATTER = 
        new DateTimeFormatterBuilder().append(DateTimeFormatter.ISO_LOCAL_DATE)
                .appendLiteral(' ')
                .appendPattern("HH:mm:ss")
                .appendFraction(ChronoField.NANO_OF_SECOND, 1, 9, true)
                .toFormatter();

这里我指定小数点后最少1位,最多9位。如果你喜欢,也可以指定3位或6位。当然,它也能接受4或5位。

链接:维基百科文章:ISO 8601


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接