将带有 +0000 的字符串日期时间转换为即时

Converting string date time with +0000 To instant

如何将作为字符串 2018-08-10T18:25:00.000+0000 传递的日期时间转换为 Instant?我尝试了以下方法,但没有用。

 public static Instant toInstant(final String timeStr) {
    if (StringUtils.isBlank(timeStr)) {
        throw new IllegalArgumentException("Invalid date time value passed [" + timeStr + "]");
    }

    try {
        return LocalDate.parse(timeStr).atStartOfDay().toInstant(ZoneOffset.UTC);
    } catch (Exception e) {
        try {
            return LocalDateTime.parse(timeStr).toInstant(ZoneOffset.UTC);
        } catch (Exception e1) {
            try {
                return ZonedDateTime.parse(timeStr).toInstant();
            } catch (Exception e2) {
                try {
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                    return LocalDateTime.parse(timeStr, formatter).toInstant(ZoneOffset.UTC);
                } catch (Exception e3) {
                    try {
                        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
                        return LocalDateTime.parse(timeStr, formatter).toInstant(ZoneOffset.UTC);
                    } catch (Exception e4) {
                        try {
                            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS");
                            return LocalDateTime.parse(timeStr, formatter).toInstant(ZoneOffset.UTC);
                        } catch (Exception e5) {
                        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
                            return LocalDateTime.parse(timeStr, formatter).toInstant(ZoneOffset.UTC);
                        } finally {
                            throw new IllegalArgumentException("Incorrect date time value passed [" + timeStr + "]");
                        }
                    }
                }
            }
        }
    }
}

您可以将 OffsetDateTimeDateTimeFormatter 一起使用。像这样,

public static Instant toInstant(final String timeStr) {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
    OffsetDateTime dateTime = OffsetDateTime.parse(timeStr, formatter);
    return dateTime.toInstant();
}

您的字符串 2018-08-10T18:25:00.000+0000 的时区偏移量为 +0000 小时,因此,您应该将其解析为 OffsetDateTime,后者可以转换为 Instant

演示:

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

public class Main {
    public static void main(String args[]) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSZ", Locale.ENGLISH);
        OffsetDateTime odt = OffsetDateTime.parse("2018-08-10T18:25:00.000+0000", dtf);
        Instant instant = odt.toInstant();
        System.out.println(instant);
    }
}

输出:

2018-08-10T18:25:00Z

ONLINE DEMO

上述解决方案中使用的 DateTimeFormatter 仅适用于模式中指定的固定数量的数字,例如秒中只有 3 位数字。可以使用 DateTimeFormatterBuilder 构建更好的 DateTimeFormatter,如以下演示所示:

import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.Locale;

public class Main {
    public static void main(String args[]) {
        DateTimeFormatter dtf = new DateTimeFormatterBuilder()
                                .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
                                .appendPattern("Z")
                                .toFormatter(Locale.ENGLISH);
        OffsetDateTime odt = OffsetDateTime.parse("2018-08-10T18:25:00.000+0000", dtf);
        Instant instant = odt.toInstant();
        System.out.println(instant);
    }
}

输出:

2018-08-10T18:25:00Z

ONLINE DEMO

了解有关 modern Date-Time API* from Trail: Date Time 的更多信息。


* 如果您正在为 Android 项目工作,并且您的 Android API 级别仍然不符合 Java-8,请检查Java 8+ APIs available through desugaring. Note that Android 8.0 Oreo already provides support for java.time

你的麻烦在这里:

        } finally {
            throw new IllegalArgumentException("Incorrect date time value passed [" + timeStr + "]");
        }

您在这些行中的解析是成功的(但可能给出不正确的结果):

            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
            return LocalDateTime.parse(timeStr, formatter).toInstant(ZoneOffset.UTC);

成功解析字符串后,在 finally 块中抛出异常。所以调用者没有收到结果,而是得到一个异常,将不得不认为解析或转换失败。

结果不正确?您对 LocalDateTime 的解析会丢弃字符串 +0000 中的 UTC 偏移量。接下来,您对 Instant 的转换采用 UTC,在本例中恰好与字符串一致。如果字符串中的偏移量不是 +0000(例如 +0100),您将得到不正确的 Instant.

其他答案显示了将字符串转换为 Instant 的正确方法。