我需要解析UTC日期和时间字符串,例如20180531_132001Z成为Java 8的日期和时间对象。如何使用Java 8的新日期和时间库进行此操作?我看到的大多数示例都是针对LocalDateTime的,如下所示:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss'Z'");
LocalDateTime localDateTime = LocalDateTime.parse("20180531_132001Z", formatter);
System.out.println(localDateTime);
System.out.println(localDateTime.atOffset(ZoneOffset.UTC));
代码输出:
2018-05-31T13:20:01
2018-05-31T13:20:01Z
我最终需要使用[Spring] JDBC将其持久保存到SQL Server数据库表(列类型为[datetime2](7)
。
更新:根据评论和答案,我认为我的问题没有经过深思熟虑。换句话说,如果我得到一个输入字符串并且我解析它而不考虑任何区域或偏移量,我将得到一个LocalDateTime
对象。如何获取该对象并将封装的值转换为UTC日期和时间?
答案 0 :(得分:9)
LocalDateTime
可能会产生误导。它不代表 您的 本地日期/时间,它代表 本地日期/时间。
它根本没有时区信息。
也就是说,它只是说“它是13:20”。它没有说在哪里它是13:20。由您来解释 where 部分。
由于这个LocalDateTime
对于携带时间戳通常不是很有用,它只适用于时区依赖于某些上下文的情况。 1
使用时间戳时,最好使用ZonedDateTime
或OffsetDateTime
。这些包含日期,时间和抵消。
因此,localDateTime.atOffset(ZoneOffset.UTC)
实际上会返回OffsetDateTime
的实例,将localDateTime
解释为UTC时间。
有人可能会说你可以通过首先解析时区信息来避免解释部分(即使它总是Z
):
String example = "20180531_132001Z";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmssX");
OffsetDateTime dateTime = OffsetDateTime.parse(example, formatter);
System.out.println(dateTime); // look ma, no hardcoded UTC
将打印:
2018-05-31T13:20:01Z
附加价值是您的代码会自动支持时区(例如"20180531_132001+05"
)。
JDBC 4.2兼容驱动程序可以通过调用setObject
来直接寻址java.time类型。
对于较旧的JDBC驱动程序,您可以将dateTime
转换为java.sql.Timestamp
或java.util.Date
:
java.sql.Timestamp.from(dateTime.toInstant());
java.util.Date.from(dateTime.toInstant());
1 几乎总有一些上下文,其中LocalDateTime
运行。例如“ Flight KL1302明天13:20到达机场X ”。 “明天13:20 ”的背景是机场X的当地时间;它可以通过查找X的时区来确定。
答案 1 :(得分:0)
这应该可以解决将字符串解析为LocalDateTime的问题:
String example = "20180531_132001Z";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmssX");
ZonedDateTime dateTime = ZonedDateTime.parse(example, formatter);
查看code run live in IdeOne.com.
dateTime.toString():2018-05-31T13:20:01Z
Timestamp timestamp = Timestamp.from(dateTime.toInstant());
然后将时间戳保存到db
中答案 2 :(得分:0)
也许这可以帮到你。
public static void main(String... strings) {
OffsetDateTime utc = OffsetDateTime.now(ZoneOffset.UTC);
System.out.println(utc.toString());
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy mm dd hh:mm a");
System.out.println(utc.format(format));
}
答案 3 :(得分:0)
虽然您当然可以使用LocalDateTime并将其格式化为使用偏移量的分区日期时间,但使用用于存储时区的对象会更容易。
ZonedDateTime zonedDateTime = ZonedDateTime.parse("20180531_132001Z", DateTimeFormatter.ofPattern("yyyMMdd_HHmmssX"));
这使您可以选择使用Instant转换为SQL时间戳或任何其他格式,而无需对时区进行硬编码,尤其是在将来添加时区或更改时。
java.sql.Timestamp timestamp = new java.sql.Timestamp(zonedDateTime.toInstant().toEpochMilli());
您可以查看时间戳的即时消息,并将其与toString进行比较,toString应与您的时区挂钩,而instant.toString则与UTC挂钩。
System.out.print(timestamp + " " + timestamp.toInstant().toString());