java - 将OffSetDateTime字符串转换为ZonedDateTime Java

标签 java datetime

我有模式"yyyy-MM-dd'T'HH:mm:ssZ"的字符串,我想使用Java将其转换为ZonedDateTime格式。

输入字符串示例:"2019-11-23T10:32:15+12:24"
输出:ZonedDateTime

编辑:我已经尝试过了,但它不起作用。

   ZonedDateTime convertToZonedDateTime(final String source) {
    final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    Date date = null;
    try {
        date = dateFormat.parse(source);
    } catch (ParseException e) {
        e.printStackTrace();
    }
    return ZonedDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());

}


我有适用于字符串“ 2018-04-05 19:58:55”的解决方案,它会产生输出2018-04-05T19:58:55 + 05:30 [Asia / Kolkata],但是当我将函数中的模式更改为“ yyyy-MM-dd'T'HH:mm:ssZ“,并将字符串输入到2019-11-23T10:32:15 + 12:24,由于ParseException:无法解析的数据,它不起作用。

我需要API的ZonedDateTime格式,该格式需要使用该格式的输入时间。

最佳答案

tl; dr

OffsetDateTime                       // Represent a moment as a date with time-of-day in the context of an offset-from-UTC (a number of hours-minutes-seconds).
.parse(                              // Parse text into a date-time object.
    "2019-11-23T10:32:15+12:24"      // The offset of +12:24 looks suspicious, likely an error.
)                                    // Returns an `OffsetDateTime` object.


从语义上讲,我们现在已经有了一个OffsetDateTime对象。

但是您声称使用的是需要ZoneDateTime对象的API。我们没有适用的时区,因此我们应用UTC(零时分分钟秒)。

OffsetDateTime                       // Represent a moment as a date with time-of-day in the context of an offset-from-UTC (a number of hours-minutes-seconds).
.parse(                              // Parse text into a date-time object.
    "2019-11-23T10:32:15+12:24"      // The offset of +12:24 looks suspicious, likely an error.
)                                    // Returns an `OffsetDateTime` object.
.atZoneSameInstant(                  // Convert from `OffsetDateTime` to `ZonedDateTime` by applying a time zone.
    ZoneOffset.UTC                   // This constant is a `ZoneOffset` object, whose class extends from `ZoneId`. So we can use it as a time zone, though semantically we are making a mess. 
)                                    // Returns a `ZonedDateTime` object.
.toString()                          // Generate text in standard ISO 8601 format.


参见此code run live at IdeOne.com


  2019-11-22T22:08:15Z


警告:示例输入字符串的偏移量对我来说似乎是错误的。

细节

您需要了解一些有关日期时间处理的概念。

偏移量

距UTC的偏移量仅比格林威治皇家天文台绘制的子午线早或晚数小时-数秒。

在Java中,我们用ZoneOffset类表示偏移量。偏移量上下文中的日期和时间用OffsetDateTime类表示。这样的对象表示时刻,即时间轴上的特定点。

时区

时区更多。时区是特定地区人民过去,现在和将来对偏移量的更改的历史记录。这些变化是由政客决定的。因此,这些更改可能是任意的,反复无常的,并且经常出乎意料地发生,常常很少甚至没有警告。例如,在北美,大多数地区都采用了夏令时(DST)废话,导致偏移每年更改两次。当前,政客们热衷于退出DST更改,而在“夏令时”永久保持全年无休,比标准时间早一小时。

有一个数据库将这些更改分类。 tZ数据是IANA维护的文件,列出了全球范围内的更改。您很可能会在主机OS,企业质量的数据库管理系统(例如Postgres)和Java虚拟机中找到这些数据的副本。确保随着您关心的区域的变化而使这些保持最新。

时区的名称格式为Continent/Region。例如,Africa/TunisEurope/ParisAsia/Kolkata

OffsetDateTime

因此,“ 2019-11-23T10:32:15 + 12:24”之类的输入字符串没有时区指示符,只有偏移量。因此,我们必须将其解析为OffsetDateTime

OffsetDateTime odt = OffsetDateTime.parse( "2019-11-23T10:32:15+12:24" ) ;


ZonedDateTime的身份要求没有任何意义。我们不能仅从偏移量可靠地确定时区。许多时区可能会在某些品脱时间上共享偏移量。

同样,该特定输入字符串2019-11-23T10:32:15+12:24是可疑的。十二小时二十四分钟的偏移量不会映射到任何当前时区。您确定正确吗?

您可以通过指定要在调整中使用的时区将OffsetDateTime转换为ZonedDateTime。我建议使用UTC。尽管这在技术上可行,但从语义上来说却令人困惑。 UTC中的时刻最好用OffsetDateTime而不是ZonedDateTime表示。但是显然,您正在与需要ZonedDateTime的代码进行互操作,所以请耐心等待。

ZonedDateTime zdt = odt.atZoneSameInstant( ZoneOffset.UTC ) ;


Instant

提示:通常,应将API作为Instant对象来传递时间,根据定义,该对象始终位于UTC中。

LocalDateTime

您提出了另一个字符串输入“ 2018-04-05 19:58:55”。此输入缺少任何时区或UTC偏移量指示符。因此,我们不知道这是否意味着在日本东京将近-8PM,在法国图卢兹将近-8PM,或者在美国俄亥俄州托莱多将近-8PM –所有这些事件相隔数小时,发生在时区上的不同时间点。

该值必须解析为LocalDateTime。将中间的SPACE替换为T以符合ISO 8601标准格式。

LocalDateTime ldt = LocalDateTime.parse( "2018-04-05 19:58:55".replace( " " , "T" ) ) ;


结果对象不代表时刻,也不是时间轴上的一点。这样的物体代表了大约26-27小时(全球时区范围)内的潜在时刻。

ZonedDateTime

如果确定输入字符串用于特定时区,请应用ZoneId以获得ZonedDateTime。然后,您确定了一个时刻,即时间轴上的特定点。

ZoneId z = ZonedId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;




Table of date-time types in Java, both modern and legacy



关于java.time

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

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

现在位于Joda-Time中的maintenance mode项目建议迁移到java.time类。

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

在哪里获取java.time类?


Java SE 8Java SE 9Java SE 10Java SE 11和更高版本-具有捆绑实现的标准Java API的一部分。


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

Java SE 6Java SE 7


大多数java.time功能都被反向移植到ThreeTen-Backport中的Java 6和7。

Android


更高版本的Android捆绑了java.time类的实现。
对于较早的Android(<26),ThreeTenABP项目改编为ThreeTen-Backport(如上所述)。请参见How to use ThreeTenABP…



Table of which java.time library to use with which version of Java or Android

ThreeTen-Extra项目使用其他类扩展了java.time。该项目是将来可能向java.time添加内容的试验场。您可能会在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

关于java - 将OffSetDateTime字符串转换为ZonedDateTime Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59378786/

相关文章:

python - 使用python格式化日期

Java Joda 时间 夏令时

asp.net datetime 随机重复时间偏移。是一个错误?

java - hibernate vs hibernate-core maven 包

java - IllegalArgumentException 尝试使用 @style/Widget.MaterialComponents.TextInputLayout.OutlinedBox 时

java - 更改 c3p0.properties 和 hibernate.properties 的位置

c++ - 纳秒和计时 C++

javascript - 按日期过滤的正确方法是什么

java - 为简单的伪代码语言创建解析器?

java - HtmlUnit 和 HTTPS 页面