当前位置: 首页 > 知识库问答 >
问题:

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

孙梓
2023-03-14

我有一个简单的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'”

有了这个新的Java8 DateTime API,我觉得这项任务会很简单,我错过了什么?!

共有2个答案

娄振
2023-03-14

我相信您试图解析的文本不是Instant应该的格式。您错过了秒和纳秒。有效的字符串类似于“2007-12-03T10:15:30.00Z”。

您应该在LocalDateTime上使用toInstant

萧繁
2023-03-14

亚斯马尼·兰斯的答案基本上是正确的。我来解释一下。

LocalDateTime不是真正的日期时间,它与时间线无关。它没有真正的意义,除非你把它调整到一个时区,以确定时间线上的一个点,一个时刻。您的代码,LocalDateTime utcTime,以及您选择的变量名,表明您将“本地”日期时间与UTC时刻混为一谈。事实并非如此。一个是模糊的想法,另一个是真实的。(好吧,在牛顿意义上是真实的,在爱因斯坦相对论意义上不是如此;-))

因此,LocalDateTime::toString的输出并不像Instant所期望的那样是完全格式的字符串。解析方法。具体来说,它没有与UTC或时区的偏移有关的数据。上一段解释了为什么这是一个特性而不是一个bug。

你想要的是一个ZoneDateTime,它基本上是一个瞬间(UTC时间轴上的一个时刻)加上一个ZoneId(时区)。

ZonedDateTime=即时ZoneId

时区是UTC(小时和分钟)的偏移量,加上过去、现在和未来调整的一组规则和异常(如夏令时、DST)。

偏移量调整规则

在java中执行LocalDateTime是正确的。时间框架,这就是它变得有点混乱的地方。从逻辑上讲,我们应该能够直接从输入字符串解析到ZoneDateTime。但是,由于调整规则,没有任何时区信息的输入字符串可能对特定区域无效。例如,在夏时制下的Spring,在美国,凌晨两点钟跳到一个小时之前,那天没有“02:38”或“20:54”。时钟从01:59.59跳下。x到03:00:00.0。

我的理解是java。time framework希望通过传递给ZonedDateTimeLocalDateTime对象来处理此调整,而不是让ZonedDateTime在解析时直接处理它。两个步骤:(1)将字符串解析为LocalDateTime,(2)将LocalDateTime对象和ZoneId对象馈送到ZonedDateTime。为了正确处理当天带有“20:54”的输入字符串,我们需要将其解析为LocalDateTime,然后要求ZoneDateTime使用指定的时区进行调整(我认为结果是“03:54”——阅读类文档了解调整行为中使用的详细信息和逻辑)。

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

你说输入字符串是在“东部时间”。我不敢告诉你,根本没有这种事。“EST”、“EDT”和其他3-4个字母的代码不是官方的、不标准的,也不是唯一的。你需要学会使用正确的时区名称。也许你指的是美国/纽约(注意下划线)或美国/蒙特利尔或类似区域。我会选择纽约。

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

顺便说一下,通过字符串交换日期时间值数据的更好方法是使用ISO 8601格式,例如2015-10-15T13:21:09Z。这些格式包括偏移量-from-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转换为时间线上的实际时刻。我们假设输入字符串代表Poughkeepsie中使用纽约时区的挂钟时间。因此,我们得到了纽约时区的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之前而不是之后,它的偏移量不是整小时(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的子类)

无论哪种方式都代表着时间线上的同一时刻。但是请注意,在下面的输出中,每一个在各自的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。此处显示的时间数据类型。在此之前,请转换为java。sql。时间戳对象。为您提供了方便的转换方法,例如java。sql。时间戳。来自(即时)

java.sql.Timestamp ts = java.sql.Timestamp.from( zdtNewYork.toInstant () );
 类似资料:
  • 问题内容: 从服务器上,我得到了这种格式的datetime变量:它是UTC时间。我想使用JavaScript将其转换为当前用户的浏览器时间。 如何使用JavaScript或jQuery完成此操作? 问题答案: 在将字符串转换为javascript中的日期之前,将’UTC’附加到字符串中:

  • 问题内容: 我需要一种简便的方法,可以在不使用任何库的情况下将日期时间戳转换为UTC(从服务器所在的任何时区)。 问题答案: 尝试getTimezone和setTimezone,请参见示例 (但这确实使用了一个类) 更新: 没有任何类,您可以尝试这样的事情: 注意:您可能还需要将时区设置回原始

  • 问题内容: 我有一个带有日期/时间值的字段,如下所示: 在UTC中。在查询中如何将其转换为EST? 我正在尝试类似的操作,但是会引发错误。 问题答案: 我必须对其进行一些微调,以使其在我的数据库上工作,但这是可行的: 关键是“在时区”语法。

  • 问题内容: 我从来没有不得不将时间与UTC转换。最近有人要求我的应用注意时区,并且我一直在圈子里奔波。我发现很多有关将本地时间转换为UTC的信息,这很基本(也许我也做错了),但是我找不到任何有关将UTC时间轻松转换为最终用户时区的信息。 简而言之,android应用程序向我发送了(appengine应用程序)数据,该数据中包含时间戳。要将时间戳存储为UTC时间,我正在使用: 那似乎行得通。当我的应

  • 问题内容: 这是我的约会日期“ 15-05-2014 00:00:00” 如何将IST转换为UTC即(到14-05-2014 18:30:00) 基于时区到UTC时区。 我的代码是 如果用户从任何区域输入相同的日期,则将获得UTC时间(例如:从澳大利亚,然后从15-05-2014 00:00:00到14-05-2014 16:00:00) 请任何建议。 问题答案: 您不能将日期值“转换为”其他时区