将时间转换为UTC时间是相反的方式 [英] Converting time to UTC time goes the opposite way

查看:132
本文介绍了将时间转换为UTC时间是相反的方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Java 8 DateTimeFormatter解析偏移时间。

I'm trying to parse an offset time using Java 8 DateTimeFormatter.

我生活在UTC-5的EST时间,所以当我尝试转换

I live in EST time which is UTC-5, so when I try to convert

2019-01-22T13:09:54.620-05:00应该-> 2019-01-22T18:09:54.620

2019-01-22T13:09:54.620-05:00 should be --> 2019-01-22T18:09:54.620

但是,使用我的代码,它会获取当前时间并返回5个小时,从而导致2019-01-22 08:09:54.620

However, with my code, it gets the current time and goes back 5 hours, resulting in 2019-01-22 08:09:54.620

代码:


import java.sql.Timestamp
import java.time._
import java.time.format.DateTimeFormatter

import scala.util.{Failure, Success, Try}

class MyTimeFormatter(parser: DateTimeFormatter) {

   def parse(input: String): Try[Timestamp] = {
    Try(new Timestamp(Instant.from(parser.withZone(ZoneOffset.UTC).parse(input)).toEpochMilli))
  }
}

测试:

new MyTimeFormatter(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSxxx")).parse("2019-01-22T13:09:54.620-05:00") shouldEqual Timestamp.valueOf("2019-01-22T18:09:54.620")

其中解析器是键入 DateTimeFormatter ,输入字符串仅为 2019-01-22T13:09:54.620-05:00

where parser is of type DateTimeFormatter and input string is just "2019-01-22T13:09:54.620-05:00"

我想使用此 parser.parse 方法,而不是与特定的TemporalAccessor(如 OffsetDateTime.parse)一起使用(输入,解析器),这样我就可以处理所有情况,例如 LocalTime,LocalDateTime,ZonedDateTime,OffsetDateTime等。

I want to use this parser.parse method and not with specific temporalAccessors like OffsetDateTime.parse(input, parser) so I can handle all cases like LocalTime, LocalDateTime, ZonedDateTime, OffsetDateTime, etc..

似乎代码只是抓住时间,减去偏移量,然后将其标记为UTC,而不是计算相对于UTC的偏移量。

It seems like the code just grabs the time, subtracts the offset, and brands it as UTC instead of calculating the offset with respect to UTC.

还有,只有输入格式为ZonedDateTime / OffsetDateTime格式时,才有办法应用UTC转换吗?如果我输入LocalDateTime(没有偏移量),例如 2017-01-01 12:45:00 ,解析器仍将应用UTC偏移量转换,因为我告诉解析器使用UTC区域进行解析。

Also, is there a way to apply this UTC conversion only if the input format is of ZonedDateTime/OffsetDateTime format? If I input a LocalDateTime (which doesn't have an offset) such as 2017-01-01 12:45:00 the parser will still apply the UTC offset conversion because I told the parser to parse with zone UTC.

推荐答案

tl; dr



使用现代的 java.time 类。仅在需要使用旧代码时才转换为旧类。

tl;dr

Use modern java.time classes. Convert to legacy class only if necessary to work with old code.

具体来说,将输入字符串解析为 OffsetDateTime 对象,通过提取即时,最后将其转换为 java.sql.Timestamp (仅在必须时)。

Specifically, parse your input string as a OffsetDateTime object, adjust to UTC by extracting an Instant, and lastly, convert to java.sql.Timestamp (only if you must).

java.sql.Timestamp ts =                           // Avoid using this badly-designed legacy class if at all possible.
    Timestamp                                     // You can convert back-and-forth between legacy and modern classes.
    .from(                                        // New method added to legacy class to convert from modern class.
        OffsetDateTime                            // Represents a moment with an offset-of-UTC, a number of some hours-minutes-seconds ahead or behind UTC.
       .parse( "2019-01-22T13:09:54.620-05:00" )  // Text in standard ISO 8601 format can be parsed by default, without a formatting pattern.
       .toInstant()                               // Adjust from an offset to UTC (an offset of zero) by extracting an `Instant`. 
    )                                             // Returns a `Timestamp` object. Same moment as both the `OffsetDateTime` and `Instant` objects.
;

请参阅此代码在IdeOne.com上实时运行,结果是:


ts.toString():2019-01- 22 18:09:54.62

ts.toString(): 2019-01-22 18:09:54.62

如果使用JDBC 4.2或更高版本,请跳过 Timestamp 总共。

If using JDBC 4.2 or later, skip the Timestamp altogether.

myPreparedStatement.setObject( … , myOffsetDateTime ) ;



祖鲁语



Zulu


2019-01-22T13:09:54.620-05:00应该-> 2019-01-22T18:09:54.620

2019-01-22T13:09:54.620-05:00 should be --> 2019-01-22T18:09:54.620

如果您的第二个值表示用UTC表示的时刻,请附加自UTC的偏移量以表明这一事实。 +00:00 Z (发音为 Zulu): 2019-01- 22T18:09:54.620Z

If you meant that second value to represent a moment in UTC, append the offset-from-UTC to indicate that fact. Either +00:00 or Z (pronounced "Zulu"): 2019-01-22T18:09:54.620Z.

报告不带UTC偏移或时区指示符的时刻就像报告没有货币指示符的金额。

Reporting a moment without an offset-from-UTC or time zone indicator is like reporting an amount of money without a currency indicator.

具有从UTC偏移的字符串应解析为 OffsetDateTime 对象。

A string with an offset-from-UTC should be parsed as a OffsetDateTime object.

您的输入字符串恰好符合文本日期时间值的ISO 8601标准格式。解析/生成字符串时, java.time 类默认使用ISO 8601格式。因此无需指定格式模式。

Your input string happens to comply with the ISO 8601 standard formats for textual date-time values. The java.time classes use ISO 8601 formats by default when parsing/generating strings. So no need to specify a formatting pattern.

OffsetDateTime odt = OffsetDateTime.parse( "2019-01-22T13:09:54.620-05:00" ) ;



时间戳



显然您想要一个 java.sql.Timestamp 对象。这是与最早的Java版本捆绑在一起的可怕的日期时间类之一。这些类现在已成为遗留类,并随着JSR 310的采用完全被现代 java.time 类所取代。请尽可能避免使用这些遗留类。

Timestamp

Apparently you want a java.sql.Timestamp object. This is one of the terrible date-time classes bundled with the earliest versions of Java. These classes are now legacy, supplanted entirely by the modern java.time classes with the adoption of JSR 310. Avoid these legacy classes whenever possible.

如果您必须具有 Timestamp 才能与尚未更新为与 java.time 一起使用的旧代码进行互操作,则可以进行转换。要进行转换,请调用添加到 old 类中的新方法。

If you must have a Timestamp to interoperate with old code not yet updated to work with java.time, you can convert. To convert, call new methods added to the old classes.

java.sql.Timestamp 类带有 from(Instant) 方法。 Instant 是UTC中的重要时刻。要从我们的 OffsetDateTime 的偏移量调整为UTC,只需提取一个 Instant

The java.sql.Timestamp class carries a from( Instant ) method. An Instant is a moment in UTC. To adjust from the offset of our OffsetDateTime to UTC, just extract an Instant.

Instant instant = odt.toInstant() ;
java.sql.Timestamp ts = Timestamp.from( instant ) ;

我们有三个对象( odt 即时 ts ),它们都代表同一时刻。第一个具有不同的挂钟时间。但是所有三个在时间轴上是同时的。

We have three objects ( odt, instant, & ts ) that all represent the same moment. The first has a different wall-clock time. But all three are the same simultaneous point on the timeline.

从JDBC 4.2开始,我们可以直接与数据库交换 java.time 对象。因此,无需使用时间戳

As of JDBC 4.2, we can directly exchange java.time objects with the database. So no need to use Timestamp.

myPreparedStatement.setObject( … , odt ) ;

…和…

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;






关于 java.time



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


About java.time

The 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 项目,现在处于维护模式 ,建议迁移到 java.time 类。

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

要了解更多信息,请参见 Oracle教程 。并在Stack Overflow中搜索许多示例和说明。规范为 JSR 310

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

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

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

在哪里获取java.time类?

Where to obtain the java.time classes?


  • Java SE 8 Java SE 9 Java SE 10 Java SE 11 ,以及更高版本-具有捆绑实现的标准Java API。


    • Java 9添加了一些次要功能和修复。

    • Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
      • Java 9 adds some minor features and fixes.

      • 大多数 java.time 功能都反向移植到Java 6& nofollow noreferrer> ThreeTen-Backport

      • Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
      • Later versions of Android bundle implementations of the java.time classes.
      • For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….

      ThreeTen-Extra 项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容打下了基础。您可能会在这里找到一些有用的类,例如 时间间隔 YearWeek YearQuarter 更多

      这篇关于将时间转换为UTC时间是相反的方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆