OffsetDateTime字符串与java中的OffsetDateTime.now()进行比较

问题描述 投票:1回答:1

我对OffsetDateTime的用法很新,我试图用这种方式将OffsetDateTime字符串与OffsetDateTime.now()进行比较,

import java.time.OffsetDateTime;

public class OffsetDateTimeDemo {
   public static void main(String[] args) {

      OffsetDateTime one = OffsetDateTime.parse("2017-02-03T12:30:30+01:00");
      System.out.println("First ::" + OffsetDateTime.now().compareTo(one));

      OffsetDateTime date1 = OffsetDateTime.parse("2019-02-14T00:00:00");
      System.out.println("Second ::" +  OffsetDateTime.now().compareTo(date1));

      OffsetDateTime date3 = OffsetDateTime.parse("Mon Jun 18 00:00:00 IST 2012");
      System.out.println(" Third :: " +OffsetDateTime.now().compareTo(date3));


   }
}   

但是我在所有3种情况下都得到了java.time.format.DateTimeParseException。

但是,如果我将2个OffsetDateTime字符串与CompareTo方法进行比较,则其工作正常。

有人可以在这方面为我提供一些启示,并指导我完成我的错误。

提前致谢。

java date datetime java-time compareto
1个回答
1
投票

你的compareTo编码是一种分心。您的例外是将字符串输入解析为对象。

另一个问题:您在第2和第3个输入上使用了错误的类。

另一个问题:在调用now()时,您隐式依赖于JVM当前的默认时区。糟糕的做法,因为任何程序员阅读都不会知道你是否打算使用默认设置,或者如果你没有意识到这个问题就像许多程序员一样。此外,当前默认值可以在运行时期间随时由JVM中任何应用程序的任何线程中的任何代码更改。因此,最好始终明确指定所需/预期的区域或偏移量。

OffsetDateTime.now( 
    ZoneOffset.UTC
)

或者更好的是,使用ZonedDateTime来获取比OffsetDateTime更多的信息。

ZonedDateTime.now(
    ZoneId.of( "Pacific/Auckland" )
)

First: OffsetDateTime works

您的第一个字符串输入正确,并成功解析。

OffsetDateTime.parse( "2017-02-03T12:30:30+01:00" )

全系列代码:

OffsetDateTime odt = OffsetDateTime.parse( "2017-02-03T12:30:30+01:00" ) ;

看到这个code run live at IdeOne.com

odt.toString():2017-02-03T12:30:30 + 01:00

比较,提取Instant。这样做可以有效地调整您从某个偏移量到零偏移量或UTC本身的时刻。根据定义,Instant始终为UTC。

Instant instant = Instant.now() ;                          // Capture the current moment as seen in UTC.
boolean odtIsPast = odt.toInstant().isBefore( instant ) ;

Second: LocalDateTime

你的第二个字符串输入缺少offset-from-UTCtime zone的任何指标。所以OffsetDateTime是错误的使用类。而是使用缺少任何偏移或区域概念的LocalDateTime

这意味着LocalDateTime不能代表片刻。例如,今年1月23日的中午可能意味着Asia/Tokyo中午会比Europe/Paris中午早几个小时,或者它可能意味着America/Montreal的中午,这将是更长时间之后的一个时刻。没有区域或偏移的上下文,LocalDateTime没有实际意义。因此,将LocalDateTime与当前时刻进行比较是毫无意义的。

LocalDateTime.parse( "2019-02-14T00:00:00" )

看到这个code run live at IdeOne.com

ldt.toString():2019-02-14T00:00

比较,你不能 - 如上所述不合逻辑。您必须指定时区(或偏移量)以确定时间轴上的时刻。如果您确定此日期和时间是针对特定时区的,请指定ZoneId以获取ZonedDateTime。然后提取一个Instant进行比较。

ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;                   // India time.
ZonedDateTime zdt = ldt.atZone( z ) ;
Instant instant = Instant.now() ;                          // Capture the current moment as seen in UTC.
boolean zdtIsPast = zdt.toInstant().isBefore( instant ) ;  // Compare.

顺便说一句,我注意到时间是零。如果您的目标是仅表示日期,没有任何时间且没有任何区域,请使用LocalDate类。

Third: Don’t bother, ambiguous input

您的第三个字符串输入带有时区指示符。因此它应该被解析为ZonedDateTime

不幸的是,你选择了一个糟糕的字符串格式来解析。切勿使用像IST这样的2-4个字符伪区域。它们不是标准化的。它们并不是独一无二的!您的IST可能意味着爱尔兰标准时间或印度标准时间或其他。

proper time zone name的格式指定Continent/Region,例如America/MontrealAfrica/CasablancaPacific/Auckland

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;

看到这个code run live at IdeOne.com

zdt.toString():2019-02-20T22:34:26.833 + 01:00 [非洲/突尼斯]

你可以尝试解析这个。 ZonedDateTime将猜测IST是指哪个区域。但这只是一个猜测,因为输入本身含糊不清,所以不可靠。就个人而言,我会拒绝编码,将此输入数据拒绝回源。

如果您坚持要进行这种不可靠的解析尝试,请将the correct Answer发送给您最近询问的similar Question

教育您的来源,始终使用标准的ISO 8601格式将日期时间值作为人类可读的文本进行交换。

在解析/生成字符串时,java.time类在默认情况下使用这些ISO 8601格式。 ZonedDateTime类明智地扩展了标准,将时区的标准名称附加在方括号中。


About java.time

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

要了解更多信息,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规格是JSR 310

现在在Joda-Timemaintenance mode项目建议迁移到java.time班。

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

从哪里获取java.time类?

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

© www.soinside.com 2019 - 2024. All rights reserved.