Java 无法从字符串中获取OffsetDateTime

Java 无法从字符串中获取OffsetDateTime,java,spring,spring-boot,datetime,datetimeoffset,Java,Spring,Spring Boot,Datetime,Datetimeoffset,我必须从字符串值中获取OffsetDateTime “2008-11-15T17:52:58” 我尝试了各种方法,但它给出了这个错误。请查看下面的代码片段和错误,并提供注释 第一种尝试方法: ZonedDateTime.parse("2008-11-15T17:52:58", DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")).toOffsetDateTime(); 第二次尝试: Offs

我必须从字符串值中获取
OffsetDateTime

“2008-11-15T17:52:58”

我尝试了各种方法,但它给出了这个错误。请查看下面的代码片段和错误,并提供注释

第一种尝试方法:

ZonedDateTime.parse("2008-11-15T17:52:58", DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")).toOffsetDateTime();
第二次尝试:

OffsetDateTime.parse("2014-06-09T17:15:04+02:00", DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"));
我得到了这个错误

Text '2008-11-15T17: 52: 58' could not be parsed at index 19

您的模式
yyyy-MM-dd'HH:MM:ss.SSSZ
不包括要分析的区域偏移量
+02:00
。此格式看起来像已在中预先创建的格式

如果您需要
OffsetDateTime
,而您的输入没有偏移量,您应该问问自己要使用什么偏移量

DateTimeFormatter中有一种方法可以尝试多个时态查询,并将结果返回给您:

Stream.of("2008-11-15T17:52:58", "2014-06-09T17:15:04+02:00").map(s -> {
    return DateTimeFormatter.ISO_DATE_TIME.parseBest(s,
            OffsetDateTime::from, LocalDateTime::from);
}).forEach(ta -> {
    System.out.println("Type : " + ta.getClass());
    System.out.println("Value : " + ta.toString());
});
以下是输出:

Type : class java.time.LocalDateTime
Value : 2008-11-15T17:52:58
Type : class java.time.OffsetDateTime
Value : 2014-06-09T17:15:04+02:00
如您所见,您的第一个输入
2008-11-15T17:52:58
没有偏移量信息,因此无法解析为OffsetDateTime。如果您知道要使用什么偏移量,可以很容易地检测到它并调用
.atOffset(…)

Stream.of("2008-11-15T17:52:58", "2014-06-09T17:15:04+02:00").map(s -> {
    return DateTimeFormatter.ISO_DATE_TIME.parseBest(s,
            OffsetDateTime::from, LocalDateTime::from);
}).forEach(ta -> {

    final OffsetDateTime odt;

    if (ta instanceof OffsetDateTime) {
        odt = (OffsetDateTime) ta;
    } else {
        //here is 2-hour offset hardcoded. If you need OffsetDateTime
        //you should also know offset somehow
        odt = ((LocalDateTime) ta).atOffset(ZoneOffset.ofHours(2));
    }

    System.out.println("Type : " + odt.getClass());
    System.out.println("Value : " + odt.toString());
});
这里是一个修改版本,用于检测丢失的偏移量,并将
LocalDateTime
转换为
OffsetDateTime
(如果您知道要使用的偏移量)

输出

Type : class java.time.OffsetDateTime
Value : 2008-11-15T17:52:58+02:00
Type : class java.time.OffsetDateTime
Value : 2014-06-09T17:15:04+02:00

您的模式
yyyy-MM-dd'HH:MM:ss.SSSZ
不包括要分析的区域偏移量
+02:00
。此格式看起来像已在中预先创建的格式

如果您需要
OffsetDateTime
,而您的输入没有偏移量,您应该问问自己要使用什么偏移量

DateTimeFormatter中有一种方法可以尝试多个时态查询,并将结果返回给您:

Stream.of("2008-11-15T17:52:58", "2014-06-09T17:15:04+02:00").map(s -> {
    return DateTimeFormatter.ISO_DATE_TIME.parseBest(s,
            OffsetDateTime::from, LocalDateTime::from);
}).forEach(ta -> {
    System.out.println("Type : " + ta.getClass());
    System.out.println("Value : " + ta.toString());
});
以下是输出:

Type : class java.time.LocalDateTime
Value : 2008-11-15T17:52:58
Type : class java.time.OffsetDateTime
Value : 2014-06-09T17:15:04+02:00
如您所见,您的第一个输入
2008-11-15T17:52:58
没有偏移量信息,因此无法解析为OffsetDateTime。如果您知道要使用什么偏移量,可以很容易地检测到它并调用
.atOffset(…)

Stream.of("2008-11-15T17:52:58", "2014-06-09T17:15:04+02:00").map(s -> {
    return DateTimeFormatter.ISO_DATE_TIME.parseBest(s,
            OffsetDateTime::from, LocalDateTime::from);
}).forEach(ta -> {

    final OffsetDateTime odt;

    if (ta instanceof OffsetDateTime) {
        odt = (OffsetDateTime) ta;
    } else {
        //here is 2-hour offset hardcoded. If you need OffsetDateTime
        //you should also know offset somehow
        odt = ((LocalDateTime) ta).atOffset(ZoneOffset.ofHours(2));
    }

    System.out.println("Type : " + odt.getClass());
    System.out.println("Value : " + odt.toString());
});
这里是一个修改版本,用于检测丢失的偏移量,并将
LocalDateTime
转换为
OffsetDateTime
(如果您知道要使用的偏移量)

输出

Type : class java.time.OffsetDateTime
Value : 2008-11-15T17:52:58+02:00
Type : class java.time.OffsetDateTime
Value : 2014-06-09T17:15:04+02:00

如果您可以获得字符串,如
2014-06-09T17:15:04+02:00
,则它包含UTC偏移量,此处为
+02:00
,即2小时0分钟。在本例中,您设置为:

    OffsetDateTime parsedDateTime = OffsetDateTime.parse("2014-06-09T17:15:04+02:00");
    System.out.println(parsedDateTime);
2014-06-09T17:15:04+02:00

我们甚至不需要指定格式化程序。字符串采用ISO 8601格式,
OffsetDateTime
和其他java.time类将最常见的ISO 8601变体解析为默认值

如果您得到类似
2008-11-15T17:52:58
的字符串,则缺少偏移量,因此无法将其直接转换为
OffsetDateTime
,因为正如名称所示,
OffsetDateTime
包含偏移量。如果你只知道一个人的名字,你就不能给他指定名字和姓氏

如果您知道某个已知时区已被理解和使用,则可以转换为
OffsetDateTime
。如果你知道一个人的姓,也许你可以假设它也是这个人的姓?如果我们在代码中显式地进行转换,可能更容易理解。我们首先解析为
LocalDateTime
Local
在java.time的一些类名中表示“没有时区或偏移量”,因此这是适合字符串的类。而且格式仍然是ISO8601,所以我们仍然不需要格式化程序

    OffsetDateTime calculatedDateTime = LocalDateTime.parse("2008-11-15T17:52:58")
            .atZone(ZoneId.of("Asia/Karachi"))
            .toOffsetDateTime();
    System.out.println(calculatedDateTime);
2008-11-15T17:52:58+05:00

转换将考虑指定时区内的任何夏季时间(DST)和其他时间变化

你的代码出了什么问题?
您的模式
yyyy-MM-dd'T'HH:MM:ss.SSSZ
要求您的字符串包含秒的三个小数和不带冒号的UTC偏移量,例如
2008-11-15T17:52:58.000+0200
。一种方法是使用格式化程序格式化和打印结果:

    System.out.println(ZonedDateTime.now(ZoneId.of("Asia/Kolkata"))
            .format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")));
2021-02-13T02:59:04.324+0530

由于您试图解析的字符串既不包含秒分数也不包含偏移量,因此解析失败

你的第二次尝试也有同样的问题。你的琴弦上仍然没有一分一秒。这次有一个偏移量,但冒号在小时和分钟之间,单个
Z
不匹配。您可能已经使用了
xxx
进行这种偏移

链接
如果您可以像
2014-06-09T17:15:04+02:00
那样获取字符串,那么它包含UTC偏移量,这里是
+02:00
,即2小时0分钟。在本例中,您设置为:

    OffsetDateTime parsedDateTime = OffsetDateTime.parse("2014-06-09T17:15:04+02:00");
    System.out.println(parsedDateTime);
2014-06-09T17:15:04+02:00

我们甚至不需要指定格式化程序。字符串采用ISO 8601格式,
OffsetDateTime
和其他java.time类将最常见的ISO 8601变体解析为默认值

如果您得到类似
2008-11-15T17:52:58
的字符串,则缺少偏移量,因此无法将其直接转换为
OffsetDateTime
,因为正如名称所示,
OffsetDateTime
包含偏移量。如果你只知道一个人的名字,你就不能给他指定名字和姓氏

如果您知道某个已知时区已被理解和使用,则可以转换为
OffsetDateTime
。如果你知道一个人的姓,也许你可以假设它也是这个人的姓?如果我们在代码中显式地进行转换,可能更容易理解。我们首先解析为
LocalDateTime
Local
在java.time的一些类名中表示“没有时区或偏移量”,因此这是适合字符串的类。而且格式仍然是ISO8601,所以我们仍然不需要格式化程序

    OffsetDateTime calculatedDateTime = LocalDateTime.parse("2008-11-15T17:52:58")
            .atZone(ZoneId.of("Asia/Karachi"))
            .toOffsetDateTime();
    System.out.println(calculatedDateTime);
2008-11-15T17:52:58+05:00

转换将考虑指定时区内的任何夏季时间(DST)和其他时间变化

你的代码出了什么问题?
您的模式
yyyy-MM-dd'T'HH:MM:ss.SSSZ
要求您的str