0

我有一个用于 JSON 解析的 API,它需要一个 DateTimeFormatter 实例才能将日期时间字符串解析为 OffsetDateTime。但是我总是得到一个异常Unable to get ZoneOffset from TemporalAccessor: {},ISO 解析为 java.time.format.Parsed 类型 的 2021-08-17T13:26:49 API 使用 OffsetDateTime.parse(String, DateFormatter)。

// DateTimeFormatter instance to be provided to the API
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
// this is how the API uses the DateTimeFormatter instance
OffsetDateTime dateTime = OffsetDateTime.parse("20210817132649", formatter);

我如何必须创建 DateTimeFormatter 才能提供 ZoneOffset,以便 API 能够正确解析 DateTime。ZoneOffset 可以是 UTC。

4

3 回答 3

3

更新

我从您那里了解到,您使用的 API 如下:

apiClient.getJSON().setOffsetDateTimeFormat(DateTimeFormatter); 

并且您没有传递时区信息的参数。在这种情况下,您可以使用DateTimeFormatter#withZone如下所示:

import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuuMMddHHmmss", Locale.ENGLISH)
                                        .withZone(ZoneOffset.UTC);

        OffsetDateTime odt = OffsetDateTime.parse("20210817132649", formatter);

        System.out.println(odt);
    }
}

输出:

2021-08-17T13:26:49Z

ONLINE DEMO

即现在,您的电话将是:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuuMMddHHmmss", Locale.ENGLISH)
                                .withZone(ZoneOffset.UTC);

apiClient.getJSON().setOffsetDateTimeFormat(formatter); 

原始答案

您的日期时间字符串没有时区偏移量。将其解析为 a LocalDateTime,然后对其应用偏移量。

演示:

import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuuMMddHHmmss", Locale.ENGLISH);
        
        OffsetDateTime odt = LocalDateTime.parse("20210817132649", formatter)
                                .atOffset(ZoneOffset.UTC);
        
        System.out.println(odt);
    }
}

输出:

2021-08-17T13:26:49Z

ONLINE DEMO

Z输出中的 是零时区偏移的时区指示符。它代表 Zulu 并指定Etc/UTC时区(时区偏移量为+00:00小时)。您可以根据您的要求指定不同的时区偏移量(例如ZoneOffset.of("+05:30"))。

如果你ZoneId有空

如果您ZoneId有空,您应该将给定的日期时间字符串解析为 a LocalDateTime,然后将ZoneId其应用以获取 a ZonedDateTime,您始终可以从中获取OffsetDateTime. a 最好的一点ZonedDateTime是它被设计为自动调整时区偏移量,而 anOffsetDateTime用于表示固定的时区偏移量。

演示:

import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuuMMddHHmmss", Locale.ENGLISH);

        ZonedDateTime zdt = LocalDateTime.parse("20210817132649", formatter)
                                .atZone(ZoneId.of("Etc/UTC"));

        OffsetDateTime odt = zdt.toOffsetDateTime();

        System.out.println(odt);
    }
}

输出:

2021-08-17T13:26:49Z

ONLINE DEMO

您可以根据您的要求指定不同的ZoneId(例如)。ZoneId.of("Asia/Kolkata")

Trail: Date Time了解有关现代日期时间 API *的更多信息。


* 如果您正在为一个 Android 项目工作,并且您的 Android API 级别仍然不符合 Java-8,请通过 desugaring 检查可用的 Java 8+ API。请注意,Android 8.0 Oreo 已经提供java.time.

于 2021-10-18T14:22:05.820 回答
2

好吧,您传入的字符串不包含区域信息,而OffsetDateTime需要区域信息。

所以你必须为它设置一个值。

您可以使用DateTimeFormatterBuilder该类,如果解析的信息中缺少某个字段,则可以指示该类使用一些默认值:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
    .appendPattern("yyyyMMddHHmmss")
    .toFormatter(Locale.ROOT);

您还可以直接将隐含区域设置为DateTimeFormatter

DateTimeFormatter.ofPattern("yyyyMMddHHmmss").withZone(ZoneOffset.UTC);
于 2021-10-18T14:42:17.250 回答
1

更好地使用 a ZonedDateTime- 区别在于夏令时,以及具有相同区域偏移的国家/地区。也许使用默认的ZoneId.

于 2021-10-18T14:24:29.803 回答