如何在日期解析(Java)中忽略时区标识符?

时间:2015-10-12 22:29:27

标签: java date datetime

我正在尝试解析这样的日期:

DateFormat df = new SimpleDateFormat("MMM dd, yyyy K:mm:ss,SSS a z", Locale.ENGLISH);
Date date = df.parse("Oct 04, 2015 2:11:58,757 AM UTC");

我的价值是5小时,因为我住的是UTC + 3时区。但是我需要具有2am的值,但是,使用相同的格式字符串(以指定格式给出的日期字符串,我不允许更改)。怎么做?

更新:我不需要在适当的时区格式化日期,我需要通过没有时区的值来比较这些日期。我想要确切地说该日期已经解析了忽略原始字符串中的时区 - 并且总是在同一时区(例如我的),无论包含原始字符串:UTC或UTC + 3还是其他什么。

2 个答案:

答案 0 :(得分:6)

accepted Answer工作太辛苦了。操纵偏移是日期时间库的范畴。自己做这样的工作是浪费你的时间,并可能成为错误的来源。

旧的java.util.Date/.Calendar类非常麻烦。避免他们。而是使用java.time或Joda-Time。

java.time

Java 8及更高版本内置了一个新的java.time框架。

困惑的问题

你的问题很困惑。你说你想忽略时区,但是你接受了一个确实解析并处理时区的答案。然后,该答案通过偏移调整结果。所以,似乎你想要忽略时区。

实际上,忽略时区很少有意义。也许你想比较柏林和底特律的一对工厂,看看他们是否同时休息。在这种情况下,您要比较各自的wall-clock time。 java.time框架为此提供了“Local”类:LocalDateLocalTimeLocalDateTime。但根据我的经验,这在大多数业务场景中很少需要。这些对象与时间轴无关。

所以你想要的就是能够比较不同时区的日期时间值。 java.time类隐式地执行此操作。具有各种指定时区的ZonedDateTime个对象可以使用isBeforeisAfterisEqual方法相互比较。

示例代码

首先我们解析输入字符串。

z模式代码意味着期望和解析时区。如果未指定其他特定时区,则还将为结果日期时间对象分配此对象。

我们还为Locale对象分配了一个人类语言组件,该组件与我们希望在输入字符串中看到的文本相匹配。在这种情况下,我们需要任何带英语的Locale。

String input = "Oct 04, 2015 2:11:58,757 AM UTC";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "MMM dd, yyyy K:mm:ss,SSS a z" ).withLocale( Locale.ENGLISH );

ZonedDateTime then = ZonedDateTime.parse( input, formatter );

接下来,我们获取Québec的当前时间。这个任意选择的时区将进一步说明我们可以将这个ZonedDateTime对象与另一个具有不同时区的对象进行比较。具体而言,与分配给我们上面的then对象的UTC时区进行比较。

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now( zoneId );

进行比较。

Boolean isThenBeforeNow = then.isBefore( now );

顺便说一下,一般来说,日期时间工作的最佳做​​法是将所有日期时间值转换为UTC时区,以进行业务逻辑,存储和数据交换。只在需要时调整到时区以满足用户对屏幕或报告的期望。

ZonedDateTime nowUtc = now.withZoneSameInstant( ZoneOffset.UTC );

转储到控制台。

System.out.println( "input: " + input );
System.out.println( "then: " + then );
System.out.println( "now: " + now );
System.out.println( "isThenBeforeNow: " + isThenBeforeNow );
System.out.println( "nowUtc: " + nowUtc );

跑步时。

  

输入:2015年10月4日上午2:11:58,757 UTC

     

然后:2015-10-04T02:11:58.757Z [UTC]

     

现在:2015-10-19T19:28:04.619-04:00 [美国/蒙特利尔]

     

isThenBeforeNow:true

     

nowUtc:2015-10-19T23:28:04.619Z

关于 java.time

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

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

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

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

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore

答案 1 :(得分:1)

Upd2:已解决

好的,现在我得到了我想要的东西:

DateFormat df = new SimpleDateFormat("MMM dd, yyyy K:mm:ss,SSS a z", Locale.ENGLISH);
Date date = df.parse("Oct 04, 2015 2:11:58,757 AM UTC");
long diff = TimeZone.getDefault().getRawOffset() - df.getTimeZone().getRawOffset();
date = new Date(date.getTime()-diff);

无论如何,谢谢大家