在东部时间中获取日期和时间输入,并在Java中转换为UTC时间戳

smithzo622

我有一个简单的Web界面,其日期和时间的格式为“ 2009/10/09 11:00”或“ yyyy / MM / dd HH:mm”。时间(从用户的角度来看)为东部时间。

我希望能够使用此字符串,将其转换为UTC时间戳,因此我可以采用此时间戳,并根据指定的时间查询我们的NoSQL数据库。

我的代码如下:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm");
    LocalDateTime dateTime = LocalDateTime.parse(startSearchTime, formatter);
    System.out.println(dateTime);
    LocalDateTime utcTime = dateTime.plusHours(4);
    Instant instant = Instant.parse(utcTime.toString());
    System.out.println(instant.toEpochMilli());

我从UI获取字符串并将其存储在“ startSearchTime”中。我通过添加4小时将其从东部时间转换为UTC。然后,我尝试创建一个即时对象并解析该字符串并获得纪元毫秒,但我得到的异常是:

“无法解析文本'2015-10-16T14:00z'”

有了这个新的Java 8 DateTime API,我认为这个任务会很容易,我还缺少什么?

罗勒·布尔克

Yasmani Llanes回答基本上是正确的。我会讲解。

LocalDateTime != UTC时刻

ALocalDateTime不是真实的日期时间,它与时间线无关。除非您将其调整到一个时区以确定时间线上的一点(即时刻),否则它没有真正的意义。您的代码(LocalDateTime utcTime带有变量名的选择)表明您已将“本地”日期时间与UTC时刻相混淆它不是。一个是模糊的想法,另一个是真实的。(嗯,在牛顿意义上是真实的,而不是在爱因斯坦相对论意义上;;)

因此,的输出LocalDateTime::toString不是该Instant.parse方法所期望的完整字符串具体来说,它没有与UTC偏移量时区有关的数据上一段解释了为什么这是功能而不是bug

您想要的ZonedDateTime基本上是一个Instant(UTC时间轴上的时刻)加上一个ZoneId(时区)。

ZonedDateTime= Instant+ZoneId

时区是相对于UTC的偏移量(小时和分钟),以及一组针对过去,现在和将来的调整的规则和异常情况(例如,夏时制DST)。

ZoneId =从UTC偏移+调整规则

您是正确的LocalDateTime在java.time框架中进行遍历的地方,这有点令人困惑。从逻辑上讲,我们应该能够直接将输入String解析为ZonedDateTime但是存在一个问题,即由于调整规则,没有任何时区信息的输入字符串可能不适用于特定的时区。例如,在春季,当我们采用夏时制“提前”时,在美国,凌晨2点向前跳一个小时,则当天没有“ 02:38”或“ 20:54” 。时钟从01:59.59.x跳到03:00:00.0。

我的理解是java.time框架希望通过LocalDateTime传递给对象来处理此调整ZonedDateTime而不是ZonedDateTime在解析时直接处理它。分两个步骤:(1)将字符串解析为LocalDateTime,(2)将LocalDateTime对象和ZoneId对象ZonedDateTime为了正确处理当天输入为“ 20:54”的字符串,我们需要将其解析为LocalDateTime,然后要求ZonedDateTime使用指定的时区进行调整(结果是“ 03:54”,我认为-请阅读课程doc,了解调整行为中使用的详细信息和逻辑)。

因此,我们需要添加到您的代码中,调用ZonedDateTime使用LocalDateTime您创建对象,我们需要指定一个ZoneId对象,ZonedDateTime以用于完成对的转换ZonedDateTime

正确的时区名称

您说输入的字符串是在“东部时间”。恐怕告诉你没有这样的事情。“ EST”,“ EDT”和其他此类3-4个字母代码不是官方的,未标准化的并且也不是唯一的。您需要学习使用正确的时区名称也许您的意思是America/New_York(请注意下划线)或America/Montreal此类区域。我会随便去纽约。

变量命名

注意我如何更改您的变量名。命名变量通常对于清晰度和以后的维护非常重要,但对于日期时间工作则更为重要。

ISO 8601

顺便说一句,通过字符串交换日期时间值的数据的更好方法是使用ISO 8601格式,例如2015-10-15T13:21:09Z这些格式包括UTC偏移量,例如Z前一句中所示(Zulu,UTC)。java.time框架通过在括号中添加时区名称来明智地扩展了ISO 8601格式。传递没有偏移量或时区信息的日期时间字符串会带来麻烦。

示例代码。

这是Java 8中的一些示例代码。首先,我们将字符串解析为一个LocalDateTime对象。

// Parse input string into a LocalDateTime object.
String input = "2009/10/09 11:00";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "yyyy/MM/dd HH:mm" );
LocalDateTime localDateTime = LocalDateTime.parse ( input , formatter );

LocalDateTime通过分配时区,将非晶态转换为时间线上的实际时刻。我们假设输入字符串代表的挂钟时间波基普西它使用纽约时区。因此,我们获得了ZoneId纽约时区的一个对象。

// Specify the time zone we expect is implied for this input string.
ZoneId zoneId = ZoneId.of ( "America/New_York" );
ZonedDateTime zdtNewYork = ZonedDateTime.of ( localDateTime , zoneId );

您可以轻松调整到其他时区。我将任意显示印度时间以两种方式形成对比:在UTC之前而不是在UTC之前,并且其偏移量不是整小时(+05:30)。

// For fun, adjust into India time, five and a half hours ahead of UTC.
ZonedDateTime zdtKolkata = zdtNewYork.withZoneSameInstant ( ZoneId.of ( "Asia/Kolkata" ) );

我们可以进行日期时间计算,例如增加四个小时。因为我们有一个ZonedDateTime,所以该类处理诸如夏令时之类的异常所需的调整

// Get a moment four hours later.
ZonedDateTime later = zdtNewYork.plusHours ( 4 );  // DST and other anomalies handled by ZDT when adding hours.

对于UTC时区,您可以选择两种方式之一。

  • 就像分配其他时区一样,分配一个时区,但是请注意在中的方便的常量ZoneOffset(的子类ZoneId)。
  • 或者,提取Instant从内ZonedDateTime根据Instant定义,An始终使用UTC。

两种方式都代表时间轴上的同一时刻。但是请注意下面的输出中,每种默认情况下在各自的toString实现中如何使用不同的格式

// To get the same moment in UTC time zone, either adjust time zone or extract Instant.
ZonedDateTime zdtUtc = zdtNewYork.withZoneSameInstant ( ZoneOffset.UTC );
Instant instant = zdtNewYork.toInstant ();

转储到控制台。

System.out.println ( "input: " + input );
System.out.println ( "localDateTime: " + localDateTime );
System.out.println ( "zdtNewYork: " + zdtNewYork );
System.out.println ( "zdtKolkata: " + zdtKolkata );
System.out.println ( "zdtUtc: " + zdtUtc );
System.out.println ( "instant: " + instant );
System.out.println ( "later: " + later );

运行时。

input: 2009/10/09 11:00
localDateTime: 2009-10-09T11:00
zdtNewYork: 2009-10-09T11:00-04:00[America/New_York]
zdtKolkata: 2009-10-09T20:30+05:30[Asia/Kolkata]
zdtUtc: 2009-10-09T15:00Z
instant: 2009-10-09T15:00:00Z
later: 2009-10-09T15:00-04:00[America/New_York]

数据库查询

至于查询数据库,请搜索StackOverflow,因为已经对其进行了详尽的处理。总结:将来,JDBC应该能够使用此处显示的java.time数据类型。在此之前,请转换为java.sql.Timestamp对象。为您提供的便捷转换方法,例如java.sql.Timestamp.from( Instant instant )

java.sql.Timestamp ts = java.sql.Timestamp.from( zdtNewYork.toInstant () );

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章