我对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方法进行比较,则其工作正常。
有人可以在这方面为我提供一些启示,并指导我完成我的错误。
提前致谢。
你的compareTo
编码是一种分心。您的例外是将字符串输入解析为对象。
另一个问题:您在第2和第3个输入上使用了错误的类。
另一个问题:在调用now()
时,您隐式依赖于JVM当前的默认时区。糟糕的做法,因为任何程序员阅读都不会知道你是否打算使用默认设置,或者如果你没有意识到这个问题就像许多程序员一样。此外,当前默认值可以在运行时期间随时由JVM中任何应用程序的任何线程中的任何代码更改。因此,最好始终明确指定所需/预期的区域或偏移量。
OffsetDateTime.now(
ZoneOffset.UTC
)
或者更好的是,使用ZonedDateTime
来获取比OffsetDateTime
更多的信息。
ZonedDateTime.now(
ZoneId.of( "Pacific/Auckland" )
)
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 ) ;
LocalDateTime
你的第二个字符串输入缺少offset-from-UTC或time 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
类。
您的第三个字符串输入带有时区指示符。因此它应该被解析为ZonedDateTime
。
不幸的是,你选择了一个糟糕的字符串格式来解析。切勿使用像IST
这样的2-4个字符伪区域。它们不是标准化的。它们并不是独一无二的!您的IST
可能意味着爱尔兰标准时间或印度标准时间或其他。
以proper time zone name的格式指定Continent/Region
,例如America/Montreal
,Africa/Casablanca
或Pacific/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
类明智地扩展了标准,将时区的标准名称附加在方括号中。
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,如java.util.Date
,Calendar
和SimpleDateFormat
。
要了解更多信息,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规格是JSR 310。
现在在Joda-Time的maintenance mode项目建议迁移到java.time班。
您可以直接与数据库交换java.time对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*
类。
从哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展了java.time。该项目是未来可能添加到java.time的试验场。你可能会在这里找到一些有用的类,如Interval
,YearWeek
,YearQuarter
和more。