Kotlin/java - 如何将日期时间字符串转换为 Instant?

Kotlin/java - How to convert a date time string to Instant?

我正在尝试从日期和时间字符串创建一个 Instant 实例。日期格式如下 yyyy-MM-dd。所以值可能如下所示:

val date = "2021-11-25"
val time = "15:20"

我正在尝试从这 2 个字符串中创建一个有效的瞬间,如下所示:

val dateTime = "${date}T${time}:00"
val instantDateTime = ZonedDateTime.parse(dateTime, 
                                          DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(defaultTimeZone)
                                         ).toInstant()

我也试过:

val instantDateTime = Instant.from(DateTimeFormatter .ISO_OFFSET_DATE_TIME.withZone(defaultTimeZone).parse(dateTime))

但是,这不起作用,我得到:

Exception in thread "main" java.time.format.DateTimeParseException: Text '2021-11-25T15:20:00' could not be parsed at index 19

您的日期字符串不包含时区,因此无法将其直接解析为 ZonedDateTime(请参阅 ZonedDateTime#parse 的 javadoc)。

尝试将字符串解析为 LocalDateTime(使用 LocalDate#parse).

然后您可以使用 LocalDateTime#toInstantLocalDateTime 转换为 Instant 或使用 LocalDateTime#atZone

转换为 ZonedDateTime

您可以组合日期和时间字符串以创建 ISO 8601 格式的日期时间字符串,您可以将其解析为 LocalDateTime,然后使用适用的 [=18] 转换为 Instant =].请注意,现代日期时间 API 基于 ISO 8601 并且不需要明确使用 DateTimeFormatter 对象,只要日期时间字符串符合 ISO 8601 标准。

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;

public class Main {
    public static void main(String[] args) {
        String strDate = "2021-11-25";
        String strTime = "15:20";
        String strDateTime = strDate + "T" + strTime;
        LocalDateTime ldt = LocalDateTime.parse(strDateTime);
        Instant instant = ldt.atZone(ZoneId.systemDefault()).toInstant();
        System.out.println(instant);
    }
}

输出:

2021-11-25T15:20:00Z

ONLINE DEMO

一些替代方法:

  1. 可以按照 daniu 的建议创建 LocalDateTime 的实例,即单独解析日期和时间字符串并使用它们创建 LocalDateTime 的实例。

演示:

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;

public class Main {
    public static void main(String[] args) {
        String strDate = "2021-11-25";
        String strTime = "15:20";
        LocalDateTime ldt = LocalDateTime.of(LocalDate.parse(strDate), LocalTime.parse(strTime));
        Instant instant = ldt.atZone(ZoneId.systemDefault()).toInstant();
        System.out.println(instant);
    }
}

ONLINE DEMO

  1. 使用 ZonedDateTime#of(LocalDate, LocalTime, ZoneId) as suggested by Ole V.V.. Another variant that you can try with this approach is by using ZonedDateTime#of(LocalDateTime, ZoneId) 创建 ZonedDateTime 的实例。

演示:

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class Main {
    public static void main(String[] args) {
        String strDate = "2021-11-25";
        String strTime = "15:20";
        ZonedDateTime zdt = ZonedDateTime.of(LocalDate.parse(strDate), LocalTime.parse(strTime),
                                                ZoneId.systemDefault());
        // Alternatively
        // ZonedDateTime zdt = ZonedDateTime.of(LocalDateTime.of(LocalDate.parse(strDate), LocalTime.parse(strTime)),
        //                                          ZoneId.systemDefault());
        
        Instant instant = zdt.toInstant();
        System.out.println(instant);
    }
}

ONLINE DEMO

  1. 合并日期和时间字符串以创建 ISO 8601 格式的日期时间字符串,并使用 DateTimeFormatter.ISO_LOCAL_DATE_TIME.withZone(ZoneId.systemDefault()).
  2. 将其解析为 ZonedDateTime

演示:

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        String strDate = "2021-11-25";
        String strTime = "15:20";
        DateTimeFormatter dtf = DateTimeFormatter.ISO_LOCAL_DATE_TIME.withZone(ZoneId.systemDefault());
        ZonedDateTime zdt = ZonedDateTime.parse(strDate + "T" + strTime, dtf);
        Instant instant = zdt.toInstant();
        System.out.println(instant);
    }
}

ONLINE DEMO

  1. 通过解析日期和时间字符串创建LocalDateTime的实例,并使用LocalDateTime#toInstant获取所需的Instant

演示:

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;

public class Main {
    public static void main(String[] args) {
        String strDate = "2021-11-25";
        String strTime = "15:20";
        LocalDateTime ldt = LocalDateTime.of(LocalDate.parse(strDate), LocalTime.parse(strTime));
        Instant instant = ldt.toInstant(ZoneId.systemDefault().getRules().getOffset(ldt));
        System.out.println(instant);
    }
}

ONLINE DEMO

了解有关 modern Date-Time API* from Trail: Date Time. Check this answer and this answer 的更多信息,了解如何将 java.time API 与 JDBC 一起使用。


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