将字符串转换为 Instant

Converting string to Instant

我正在尝试使用 java 8 或 utils 包将字符串中的日期时间转换为即时。

例如

String requestTime = "04:30 PM, Sat 5/12/2018";

Instant reqInstant should result in 2018-05-12T20:30:00.000Z

reqString 在 America/Toronto 时区。

这是我试过的

 String strReqDelTime = "04:30 PM, Sat 5/12/2018";
 Date date = new SimpleDateFormat("hh:mm a, EEE MM/dd/yyyy").parse(requestTime);
 Instant reqInstant = date.toInstant();

以上代码结果为 "2018-05-12T23:30:00Z"

感谢任何帮助。

tl;博士

  • 修复未填充的月份和日期的格式设置模式。
  • 仅使用 java.time 类,绝不使用遗留 类.

人为的例子:

LocalDateTime.parse(                   // Parse as an indeterminate `LocalDate`, devoid of time zone or offset-from-UTC. NOT a moment, NOT a point on the timeline.
    "04:30 PM, Sat 5/12/2018" ,        // This input uses a poor choice of format. Whenever possible, use standard ISO 8601 formats when exchanging date-time values as text. Conveniently, the java.time classes use the standard formats by default when parsing/generating strings.
    DateTimeFormatter.ofPattern( "hh:mm a, EEE M/d/uuuu" , Locale.US )  // Use single-character `M` & `d` when the number lacks a leading padded zero for single-digit values.
)                                      // Returns a `LocalDateTime` object.
.atZone(                               // Apply a zone to that unzoned `LocalDateTime`, giving it meaning, determining a point on the timeline.
    ZoneId.of( "America/Toronto" )     // Always specify a proper time zone with `Contintent/Region` format, never a 3-4 letter pseudo-zone such as `PST`, `CST`, or `IST`. 
)                                      // Returns a `ZonedDateTime`. `toString` → 2018-05-12T16:30-04:00[America/Toronto].
.toInstant()                           // Extract a `Instant` object, always in UTC by definition.
.toString()                            // Generate a String in standard ISO 8601 format representing the value within this `Instant` object. Note that this string is *generated*, not *contained*.

2018-05-12T20:30:00Z

使用个位数格式化模式

您在格式化模式中使用了 MM,这意味着任何单个数字的值(1 月至 9 月)都将以填充的前导零显示。

但是您的输入缺少填充的前导零。所以使用单个 M.

同上我期望的日期:d 而不是 dd

仅使用java.time

您使用的是多年前被java.time[取代的麻烦的有缺陷的旧日期时间类(Date & SimpleDateFormat) =122=] 类。新的 类 完全取代了旧的。无需混合传统和现代。

LocalDateTime

解析为 LocalDateTime because your input string lacks any indicator of time zone or offset-from-UTC。这样的值是不是一个时刻,是不是时间轴上的一个点。这只是一组 潜在 时刻,时间范围约为 26-27 小时。

String input = "04:30 PM, Sat 5/12/2018";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "hh:mm a, EEE M/d/uuuu" , Locale.US );  // Specify locale to determine human language and cultural norms used in translating that input string.
LocalDateTime ldt = LocalDateTime.parse( input , f );

ldt.toString(): 2018-05-12T16:30

ZonedDateTime

如果您确定输入是为了表示使用加拿大多伦多地区人们使用的挂钟时间的时刻,请应用 ZoneId 以获得 ZonedDateTime 对象.

分配一个时区让你的未时区变得有意义 LocalDateTime。现在我们有一个时刻,时间轴上的一个点。

ZoneId z = ZoneId.of( "America/Toronto" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;  // Give meaning to that `LocalDateTime` by assigning the context of a particular time zone. Now we have a moment, a point on the timeline.

zdt.toString(): 2018-05-12T16:30-04:00[America/Toronto]

Instant

看到与 UTC, extract an Instant 相同的时刻。同一时刻,不同的挂钟时间。

Instant instant = zdt.toInstant() ;

instant.toString(): 2018-05-12T20:30:00Z


关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

Joda-Time project, now in maintenance mode, advises migration to the java.time 类.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

您可以直接与数据库交换 java.time 对象。使用 JDBC driver compliant with JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql.* 类.

java.time类在哪里获取?

  • Java SE 8, Java SE 9, Java SE 10,及以后
    • 内置。
    • 标准 Java API 的一部分,带有捆绑实施。
    • Java 9 添加了一些小功能和修复。
  • Java SE 6 and Java SE 7
  • Android
    • Android java.time 类.
    • 捆绑实施的更高版本
    • 对于较早的 Android (<26),ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See .

ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

您的计算机(服务器)中的时区似乎是美国太平洋夏令时 (GMT-7),但您希望得到美国东部夏令时 (GMT-4) 的结果。

Instant.toString() returns ISO-8601 格式的 UTC (GMT+0) 日期时间。 (最后的'Z'表示UTC)。

SimpleDateFormat 在未指定时将 DateTime String 视为计算机的默认时区。而且您的输入没有指定时区。

因此,您需要对输入的时区进行处理。

PS。在 DST 东部的我的机器上,你的代码给我的结果完全符合你的预期。

有关说明,您可以在此处阅读 [https://www.baeldung.com/java-string-to-date]

String requestTime = "04:30 PM, Sat 5/12/2018 America/Toronto";
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("hh:mm a, EEE M/dd/yyyy z");
            ZonedDateTime zonedDateTime = ZonedDateTime.parse(requestTime, formatter);
            System.out.println(zonedDateTime.toInstant());  

Instant.parse(字符串)格式正确