我如何解析Java 8中不包含标点的ISO-8601格式的字符串?

问题描述 投票:4回答:3

如何将以下字符串解析为LocalDateTime-对象?

20200203092315000000

我总是收到以下异常,但我不明白:

java.time.format.DateTimeParseException: Text '20200203092315000000' could not be parsed at index 0

    at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
    at java.time.LocalDateTime.parse(LocalDateTime.java:492)
    at de.x.struct.type.LocalDateTimeStructField.setBytesValue(LocalDateTimeStructField.java:44)
    at de.x.struct.Struct.bytesToStruct(Struct.java:110)
    at de.x.struct.StructTest.testStringToStruct(StructTest.java:60)

我的应用程序代码如下:

LocalDateTime ldt = LocalDateTime.parse("20200203092315000000", DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSSSSS"));
java localdate
3个回答
5
投票

看起来像一个已知问题...

bug_id=JDK-8031085bug_id=JDK-8138676

解决方法:

DateTimeFormatter dtf =新DateTimeFormatterBuilder()。appendPattern(“ yyyyMMddHHmmss”)。appendValue(ChronoField.MILLI_OF_SECOND,3).toFormatter()

客户提交的解决方法:请使用以下格式(请注意'。'):“ yyyyMMddHHmmss.SSS”

LocalDateTime.parse(“ 20150910121314987”,DateTimeFormatter.ofPattern(“ yyyyMMddHHmmss.SSS”))

或使用jodatime库


0
投票

我已经使用以下代码近三年了,它为我提供了很好的帮助。

ISO 8601允许两种格式:基本和扩展。基本格式不包含标点符号,而扩展格式则包含标点符号。例如,扩展格式的2017-12-10T09:47:00-04:00等同于基本格式的20171210T094700-0400。

由于Java 8中的行为是仅接受扩展格式,所以我通常使用新的DateTimeFormatter来接受这两种格式。

此格式不能准确表示ISO 8601的要求。规则是时间戳的文本表示形式可以是完全基本的(即,没有标点符号)或完全扩展的(即,所有标点符号都存在)。仅有一些标点符号是无效的,但是我发现有些库不遵守该规则。具体来说,Gson产生时间戳,在时区说明符中冒号丢失。由于我希望自己接受的东西是自由的,所以我完全忽略了所有标点符号。

Java 8也无法准确处理年份,尤其是在缺少标点符号的情况下。 ISO 8601一年中需要精确地四位数,但如果双方都同意使用明确的位数,则允许使用额外的位数。在这种情况下,必须在年份前加一个符号。但是,Java 8并没有强制要求具有符号并接受四到九位数字。虽然这种方法比较宽松,并且与我通常要完成的工作保持一致,但由于我不知道应该显示多少位数,因此无法解析一年。在这种情况下,我会收紧格式以符合ISO 8601的要求,不过如果需要,可以使用其他方法。例如,您可以预先准备文本,知道期望多少位数,如果位数太多,则添加符号。

我建议仅在解析时使用此格式化程序,而在序列化时不建议使用此格式化程序,因为我倾向于严格限制所产生的内容。

以下代码应接受您的格式,带有和不带有时区偏移量。它仅与您所拥有的有所不同,因为它接受小数秒的九位数而不是六位数。您可以根据需要进行调整。

static DateTimeFormatter ISO_8601_LENIENT_FORMAT = new DateTimeFormatterBuilder()
        .parseCaseInsensitive()
        .appendValue(YEAR, 4, 4, SignStyle.EXCEEDS_PAD)
        .optionalStart().appendLiteral('-').optionalEnd()   // Basic format has no punctuation
        .appendValue(MONTH_OF_YEAR, 2)
        .optionalStart().appendLiteral('-').optionalEnd()
        .appendValue(DAY_OF_MONTH, 2)
        .optionalStart().appendLiteral('T').optionalEnd()   // permitted to omit the 'T' character by mutual agreement
        .appendValue(HOUR_OF_DAY, 2)
        .optionalStart().appendLiteral(':').optionalEnd()
        .appendValue(MINUTE_OF_HOUR, 2)
        .optionalStart()                                    // seconds are optional
            .optionalStart().appendLiteral(':').optionalEnd()
            .appendValue(SECOND_OF_MINUTE, 2)
            .optionalStart().appendFraction(NANO_OF_SECOND, 0, 9, true).optionalEnd()
        .optionalEnd()
        .optionalStart().appendOffset("+HH:MM", "Z").optionalEnd()
        .optionalStart().appendOffset("+HHMM", "Z").optionalEnd()
        .optionalStart().appendOffset("+HH", "Z").optionalEnd()
        .toFormatter()
        ;

-3
投票

您的输入无效,超出范围。

输入正确时使用此代码。

Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(your input * 1000);
        System.out.println(cal.getTime());
© www.soinside.com 2019 - 2024. All rights reserved.