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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33091227/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 21:09:53  来源:igfitidea点击:

How to ignore timezone identifier in date parsing (Java)?

javadatedatetime

提问by sandwwraith

I'm trying to parse date like this:

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

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");

And I'm getting a value of 5 hours am, because i live in UTC+3 timezone. But i need to have value of 2am, however, with the same format string(date string given in a specified format, which i'm not allowed to change). How to do this?

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

Upd: I don't need to format the date in proper timezone, i need to COMPARE these dates by its values without timezones. I want exactly that date have parsed ignoring the timezone in original string - and be always in the same timezone (my, for example), no matter what contains original string: UTC or UTC+3 or something else.

更新:我不需要在正确的时区格式化日期,我需要通过没有时区的值来比较这些日期。我希望该日期完全解析为忽略原始字符串中的时区 - 并且始终处于同一时区(例如,我的时区),无论包含原始字符串的内容是什么:UTC 或 UTC+3 或其他内容。

采纳答案by sandwwraith

Upd2: Solved

Upd2:解决了

Okay, now i get what i want:

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

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);

Anyway, thanks for everyone

不管怎样,谢谢大家

回答by Basil Bourque

The accepted Answeris working too hard. Manipulating offsets is the province of a date-time library. Doing such work yourself is a waste of your time, and likely to be a source of bugs.

接受的答案是工作太辛苦。操作偏移量是日期时间库的职责。自己做这样的工作是在浪费你的时间,而且很可能是错误的来源。

The old java.util.Date/.Calendar classes are notoriously troublesome. Avoid them. Instead use either java.time or Joda-Time.

旧的 java.util.Date/.Calendar 类是出了名的麻烦。避开它们。而是使用 java.time 或 Joda-Time。

java.time

时间

Java 8 and later has a new java.timeframework built-in.

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

Confused Question

困惑的问题

Your Question is confused. You say you want to ignore time zone, yet you accept an answer that does indeed parse and process the time zone. And that answer then adjusts the result by an offset. So, it seems that you do notwant to ignore the time zone.

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

Indeed, ignoring the time zone rarely makes sense. Perhaps you want to compare a pair of factories in Berlin and in Detroit to see if they both take a lunch break at the same time. In this case you are comparing their respective wall-clock time. The java.time framework offers the “Local” classes for this purpose: LocalDate, LocalTime, and LocalDateTime. But this is rarely needed in most business scenarios in my experience. These objects are not tied to the timeline.

事实上,忽略时区几乎没有意义。或许您想比较柏林和底特律的两家工厂,看看它们是否同时午休。在这种情况下,您正在比较它们各自的挂钟时间。该java.time框架提供的“本地”类用于此目的:LocalDateLocalTime,和LocalDateTime。但是根据我的经验,在大多数业务场景中很少需要这样做。这些对象与时间线无关。

So it seems that what you dowant is to be able to compare date-time values across various time zones. The java.time classes do that implicitly. ZonedDateTimeobjects with various assigned time zones can be compared to one another with isBefore, isAfter, and isEqualmethods.

如此看来,你要的是能够跨越不同的时区比较日期时间值。java.time 类隐式地做到了这一点。ZonedDateTime与各种分配的时区的对象可以与具有彼此isBeforeisAfterisEqual方法。

Example Code

示例代码

First we parse the input string.

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

The zpattern code means to expect and parse a time zone. The resulting date-time object will also be assigned this object if no other specific time zone is specified.

z模式代码手段期望和分析的时区。如果未指定其他特定时区,则生成的日期时间对象也将被分配此对象。

We also assign a Localeobject with a human language component matching the text we expect to see in the input string. In this case, we need any Locale with English.

我们还分配了一个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 );

Next we get the current time for Québec. This arbitrary choice of time zone will demonstrate further below that we can compare this ZonedDateTimeobject to another with a different time zone. Specifically, comparing against the UTC time zone assigned to our thenobject above.

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

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

Do the comparison.

做比较。

Boolean isThenBeforeNow = then.isBefore( now );

By the way, generally-speaking, the best practice in date-time work is to convert all your date-time values to UTC time zone for business logic, storage, and data exchange. Adjust into a time zone only as need be to satisfy a user's expectations on-screen or in reports.

顺便说一下,一般来说,日期时间工作的最佳实践是将所有日期时间值转换为 UTC 时区,用于业务逻辑、存储和数据交换。仅根据需要调整到时区以满足用户在屏幕上或报告中的期望。

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

Dump to console.

转储到控制台。

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 );

When run.

跑的时候。

input: Oct 04, 2015 2:11:58,757 AM UTC

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

now: 2015-10-19T19:28:04.619-04:00[America/Montreal]

isThenBeforeNow: true

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

输入:UTC 时间 2015 年 10 月 4 日凌晨 2:11:58,757

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

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

isThenBeforeNow: 真

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



About java.time

关于java.time

The java.timeframework is built into Java 8 and later. These classes supplant the troublesome old legacydate-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如java.util.Date, Calendar, & SimpleDateFormat

The Joda-Timeproject, now in maintenance mode, advises migration to the java.timeclasses.

现在处于维护模式Joda-Time项目建议迁移到java.time类。

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

要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规范是JSR 310

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

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

Where to obtain the java.time classes?

从哪里获得 java.time 类?

The ThreeTen-Extraproject extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多