Java 将字符串转换为 Instant

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/50299639/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 23:32:49  来源:igfitidea点击:

Converting string to Instant

javadatetimezonezoneddatetimejava.time.instant

提问by Venky

I am trying to covert datetime in string to instant using java 8 or utils package.

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

For eg.

例如。

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

to

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

reqString is in America/Toronto timezone.

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

This is what I tried

这是我试过的

 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();

The above code results in "2018-05-12T23:30:00Z".

上面的代码导致"2018-05-12T23:30:00Z".

Any help is appreciated.

任何帮助表示赞赏。

采纳答案by Basil Bourque

tl;dr

tl;博士

  • Fix your formatting pattern for unpadded month & day.
  • Use only java.timeclasses, never the legacy classes.
  • 修复未填充的月份和日期的格式模式。
  • 只使用java.time类,不要使用遗留类。

Contrived example:

人为的例子:

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

2018-05-12T20:30:00Z

Use single-digit formatting pattern

使用个位数格式模式

You used MMin your formatting pattern, to mean any single-digit value (months January-September) will appear with a padded leading zero.

MM在格式化模式中使用,表示任何一位数的值(一月至九月的月份)都将带有填充的前导零。

But your input lacks that padded leading zero. So use a single M.

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

Ditto for day-of-month I expect: drather than dd.

同样适用于我期望的月份:d而不是dd.

Use only java.time

只使用java.time

You are using troublesome flawed old date-time classes (Date& SimpleDateFormat) that were supplanted years ago by the java.timeclasses. The new classes entirely supplant the old. No need to mix the legacy and modern.

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

LocalDateTime

LocalDateTime

Parse as a LocalDateTimebecause your input string lacks any indicator of time zoneor offset-from-UTC. Such a value is nota moment, is nota point on the timeline. It is only a set of potentialmoments along a range of about 26-27 hours.

解析为 aLocalDateTime因为您的输入字符串缺少任何时区指示符或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

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

ZonedDateTime

ZonedDateTime

If you know for certain that input was intended to represent a moment using the wall-clock time used by the people of the Toronto Canada region, apply a ZoneIdto get a ZonedDateTimeobject.

如果您确定该输入旨在使用加拿大多伦多地区的人们使用的挂钟时间来表示某个时刻,请应用 aZoneId来获取ZonedDateTime对象。

Assigning a time zone gives meaning to your unzoned LocalDateTime. Now we have a moment, a point on the timeline.

分配时区赋予未分区的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]

zdt.toString(): 2018-05-12T16:30-04:00[美国/多伦多]

Instant

Instant

To see that same moment as UTC, extract an Instant. Same moment, different wall-clock time.

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

Instant instant = zdt.toInstant() ;

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

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



About java.time

关于java.time

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

java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如java.util.Date, Calendar, & SimpleDateFormat

The Joda-Timeproject, now in maintenance mode, advises migration to the java.timeclasses.

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

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

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

You may exchange java.timeobjects directly with your database. Use a JDBC drivercompliant with JDBC 4.2or later. No need for strings, no need for java.sql.*classes.

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

Where to obtain the java.time classes?

从哪里获得 java.time 类?

The ThreeTen-Extraproject 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.

ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多

回答by Vadim

It seems like Time Zone in your computer(server) is US Pacific DST (GMT-7), but you expect to have result for US Eastern DST (GMT-4).

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

Instant.toString() returns UTC (GMT+0) DateTime in ISO-8601 format. ('Z' at the end means UTC).

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

SimpleDateFormat threats DateTime String in default Time Zone of computer when it is not specified. And your input does not specify time zone.

SimpleDateFormat 威胁计算机默认时区中的 DateTime 字符串(未指定时)。并且您的输入未指定时区。

So, you need to do something about in what time zone your input is.

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

PS. on mine machine in Eastern DST your code gives me result exactly as you expected.

附注。在东部夏令时的我的机器上,您的代码完全符合您的预期。