将没有ZonedId的String转换为OffsetDateTime

时间:2018-05-18 14:38:44

标签: java datetime timezone-offset zoneddatetime

我想将String转换为OffsetDateTime数据类型。该字符串具有以下形状:

DataTable tblresult = CrossJoinTables(dtTemp2, dtTemp); // swapped order because you want columns from dtTemp2 first

我尝试了两种方法:

方法1

  2017-11-27T19:06:03

方法2:

    public static OffsetDateTime convertString(String timestamp) {
        java.time.format.DateTimeFormatter formatter = new java.time.format.DateTimeFormatterBuilder()
            .parseCaseInsensitive()
            .append(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE)
            .appendLiteral('T')
            .appendValue(HOUR_OF_DAY, 2)
            .appendLiteral(':')
            .appendValue(MINUTE_OF_HOUR, 2)
            .optionalStart()
            .appendLiteral(':')
            .appendValue(SECOND_OF_MINUTE, 2)
            .toFormatter();


        return OffsetDateTime.parse(timestamp, formatter);
    }

第一种方法不起作用,因为它抱怨以下内容:

  

java.time.format.DateTimeParseException:Text' 2017-11-27T19:02:42'无法解析:无法从TemporalAccessor获取OffsetDateTime:{},ISO已解析为类型为java.time.format.Parsed的2017-11-27T19:02:42

根据我的理解,它来自字符串没有ZoneId的事实。如何在格式化程序上覆盖ZoneId以便忽略它?

第二种方法来自from this question并且有效,但它需要额外转换2次,我希望避免这些额外的转化。

任何帮助都将受到赞赏。

2 个答案:

答案 0 :(得分:2)

要从没有偏移或时区的字符串中获取OffsetDateTime,您需要确定偏移量或获取偏移量的方法。最明显的方法是,如果您知道要在哪个时区解释日期时间。例如:

    OffsetDateTime dateTime = LocalDateTime.parse(timestamp)
            .atZone(ZoneId.of("Asia/Chongqing"))
            .toOffsetDateTime();
    System.out.println(dateTime);

使用您问题中的字符串输出:

  

2017-11-27T19:06:03 + 08:00

不要害怕从LocalDateTimeZonedDateTime再到OffsetDateTime的两次转换。使用java.time,它们不仅易于操作,而且还易于阅读。

如果您知道偏移量,只需使用它,那么您只需要一次转换(我在示例中使用了无意义的偏移量,因此您必须自己选择):

    OffsetDateTime dateTime = LocalDateTime.parse(timestamp)
            .atOffset(ZoneOffset.ofTotalSeconds(-36953));
    System.out.println(dateTime);

输出:

  

2017-11-27T19:06:03-10:15:53

您可以指定所需的偏移量,例如ZoneOffset.of("+08:00")ZoneOffset.ofHours(8)

但要回答你的问题(现在是时候了)。

  

如何在格式化程序上覆盖ZoneId以便忽略它?

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
            .parseDefaulting(ChronoField.OFFSET_SECONDS, -36953)
            .toFormatter();
    OffsetDateTime dateTime = OffsetDateTime.parse(timestamp, formatter);
    System.out.println(dateTime);

输出与前一个输出相同(并且您需要选择一个在您的情况下有意义的偏移量。)

答案 1 :(得分:0)

最后,我通过以下代码解决了这个问题:

    public static OffsetDateTime convertString(String timestamp) {
        java.time.format.DateTimeFormatter formatter = new java.time.format.DateTimeFormatterBuilder()
            .parseCaseInsensitive()
            .append(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE)
            .appendLiteral('T')
            .appendValue(HOUR_OF_DAY, 2)
            .appendLiteral(':')
            .appendValue(MINUTE_OF_HOUR, 2)
            .optionalStart()
            .appendLiteral(':')
            .appendValue(SECOND_OF_MINUTE, 2)
            .toFormatter();

    return LocalDateTime.parse(timestamp, formatter)
            .atOffset(java.time.ZoneOffset.UTC);
    }