将字符串转换为即时

新手上路,请多包涵

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

例如。

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

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

reqString 位于美国/多伦多时区。

这是我尝试过的

 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"

任何帮助表示赞赏。

原文由 masterfly 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 619
2 个回答

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

您正在使用有缺陷的旧日期时间类( Date & SimpleDateFormat ),这些类在几年前已被 java.time 类取代。新的阶级完全取代了旧的阶级。无需混合传统和现代。

LocalDateTime

解析为 LocalDateTime 因为您的输入字符串缺少任何 时区 指示符或 与 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[美国/多伦多]

Instant

要查看与 UTC 相同的时刻,请提取 Instant 。同一时刻,不同的挂钟时间。

 Instant instant = zdt.toInstant() ;

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


关于 java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

现在处于 维护模式Joda-Time 项目建议迁移到 java.time 类。

要了解更多信息,请参阅 Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规范是 JSR 310

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

从哪里获得 java.time 类?

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如 IntervalYearWeekYearQuarter 等等

原文由 Basil Bourque 发布,翻译遵循 CC BY-SA 4.0 许可协议

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

Instant.toString() 返回 ISO 8601 格式的 UTC (GMT+0) DateTime。 (末尾的“Z”表示 UTC)。

SimpleDateFormat 未指定时,将 DateTime String 视为计算机的默认时区。并且您的输入未指定时区。

因此,您需要对输入所在的时区做些什么。

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

原文由 Vadim 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题