【问题标题】:Threeten DateTimeParseException for OffsetDateTime.parse(String,dateTimeFormatter)OffsetDateTime.parse(String,dateTimeFormatter) 的三个 DateTimeParseException
【发布时间】:2018-10-15 01:45:34
【问题描述】:

我想简单地制作一个DateTimeFormatter 以在OffsetDateTime 解析器中使用。但我得到DateTimeParseException

final DateTimeFormatter ISO_LOCAL_DATE;
ISO_LOCAL_DATE = new DateTimeFormatterBuilder()
    .appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
    .appendLiteral('-')
    .appendValue(MONTH_OF_YEAR, 2)
    .appendLiteral('-')
    .appendValue(DAY_OF_MONTH, 2)
    .appendLiteral('T')
    .appendValue(HOUR_OF_DAY,2)
    .appendLiteral(':')
    .appendValue(MINUTE_OF_HOUR,2)
    .appendLiteral(':')
    .appendValue(SECOND_OF_MINUTE,2)
    .toFormatter().withResolverStyle(ResolverStyle.STRICT).withChronology(IsoChronology.INSTANCE);

DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
OffsetDateTime.parse("2012-03-06T00:00:00",ISO_LOCAL_DATE);

我研究了一个类似的问题,但也没有任何线索:/ 上面的代码有什么问题?与Formatter 或 Threeten lib 有什么关系?

【问题讨论】:

  • 你应该分享你的堆栈跟踪
  • 您似乎在模仿预定义的 ISO_LOCAL_DATE_TIME 并将其命名为 ISO_LOCAL_DATE。这很令人困惑。 java.time 名称中的“本地”表示“没有时区或偏移量”,这可能会给你一个提示。
  • 请问,您想要的结果是什么?为什么?
  • OffsetDateTime parsing的可能重复

标签: java threetenbp


【解决方案1】:

您没有在输入数据中指定偏移量。

这是一个带偏移量的日期时间示例:

2012-03-06T00:00+01:00

ZonedDateTime 的示例:

2012-03-06T00:00+02:00[Europe/Paris]

Europe/Berlin - 在这里可以被视为ZoneId。但是每个区域在一年中的不同时间(夏季/冬季时间)可能有不同的偏移量。

ZoneIdZoneOffset 之间没有一对一的映射关系: Is there any way to convert ZoneId to ZoneOffset in java 8?

您可以指定ZoneId,而不是指定ZoneOffset,偏移量将自动确定。

然后你可以得到ZonedDateTime,并把它转换成OffsetDateTime

public OffsetDateTime ZonedDateTime.toOffsetDateTime()

这会使用本地日期时间和偏移量创建偏移日期时间。 区域 ID 被忽略。

针对您指定 ZoneId 的情况的修复:

public class Main {
    private static final DateTimeFormatter ISO_LOCAL_DATE = new DateTimeFormatterBuilder()
            .appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
            .appendLiteral('-')
            .appendValue(MONTH_OF_YEAR, 2)
            .appendLiteral('-')
            .appendValue(DAY_OF_MONTH, 2)
            .appendLiteral('T')
            .appendValue(HOUR_OF_DAY,2)
            .appendLiteral(':')
            .appendValue(MINUTE_OF_HOUR,2)
            .appendLiteral(':')
            .appendValue(SECOND_OF_MINUTE,2)
            .toFormatter()
            .withResolverStyle(ResolverStyle.STRICT)
            .withChronology(IsoChronology.INSTANCE)
            .withZone(ZoneId.systemDefault()); // or whatever you have

    public static void main(String[] args) {
        ZonedDateTime zonedDateTime = ZonedDateTime.parse("2012-03-06T00:00:00", ISO_LOCAL_DATE);
        System.out.println(zonedDateTime);
        System.out.println(zonedDateTime.toOffsetDateTime());
    }
}

近似输出:

2012-03-06T00:00+01:00[Europe/City]
2012-03-06T00:00+01:00

修复的第二个选项 - 将 offsetId() 添加到解析器构建器并为输入字符串指定偏移部分:

public class Main {
    private static final DateTimeFormatter ISO_LOCAL_DATE = new DateTimeFormatterBuilder()
            .appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
            .appendLiteral('-')
            .appendValue(MONTH_OF_YEAR, 2)
            .appendLiteral('-')
            .appendValue(DAY_OF_MONTH, 2)
            .appendLiteral('T')
            .appendValue(HOUR_OF_DAY,2)
            .appendLiteral(':')
            .appendValue(MINUTE_OF_HOUR,2)
            .appendLiteral(':')
            .appendValue(SECOND_OF_MINUTE,2)
            .appendOffsetId()
            .toFormatter()
            .withResolverStyle(ResolverStyle.STRICT)
            .withChronology(IsoChronology.INSTANCE);

    public static void main(String[] args) {
        OffsetDateTime offsetDateTime = OffsetDateTime.parse("2012-03-06T00:00:00+02:00", ISO_LOCAL_DATE);
        System.out.println(offsetDateTime);
    }
}

输出:

2012-03-06T00:00+02:00

您可以指定自己的偏移模式,而不是 .appendOffsetId(),例如:

.appendOffset("+HH:mm", "Z")

顺便说一句,有一堆标准的DateTimeFormatters,你可以使用开箱即用的方法来解析OffsetDateTime

public class Main {
    public static void main(String[] args) {
        String offsetStringTime = "2012-03-06T00:00:00+02:00";
        OffsetDateTime offsetDateTime = OffsetDateTime.parse(offsetStringTime);
        OffsetDateTime offsetDateTime2 = OffsetDateTime.parse(offsetStringTime, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
        OffsetDateTime offsetDateTime3 = OffsetDateTime.parse(offsetStringTime, DateTimeFormatter.ISO_ZONED_DATE_TIME);
        System.out.println(offsetDateTime);
        System.out.println(offsetDateTime2);
        System.out.println(offsetDateTime3);
    }
}

输出:

2012-03-06T00:00+02:00
2012-03-06T00:00+02:00
2012-03-06T00:00+02:00

【讨论】:

  • 太棒了!你说得对。但我真正需要的是一个有效的格式化程序,用于我无法触及的 OffsetDateTime 解析器,我只能为它设置一个格式化程序。是否可以从 ZonedDateTime 获得格式化程序?!由于 ISO_LOCAL_DATE 对 OffsetDateTime 解析器无效。
  • @user737862 添加了一个例子,请参考更新后的答案。
  • @user737862 我可能会重复已编辑答案中的内容,但只需将格式化程序设置为DateTimeFormatter.ISO_OFFSET_DATE_TIME。没有理由为它构建自己的格式化程序。
猜你喜欢
  • 2019-07-01
  • 2020-09-15
  • 1970-01-01
  • 2015-01-06
  • 1970-01-01
  • 2021-04-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多