[英]Java convert ISO 8601 string to Date ignoring offset
I have a string coming to me in the following format "yyyy-MM-dd'T'HH:mm:ssZ" ex: 2020-09-09T09:58:00+0000" offset is UTC.我收到一个字符串,格式为“yyyy-MM-dd'T'HH:mm:ssZ”,例如:2020-09-09T09:58:00+0000" 偏移量是UTC。
I need the string to be converted to a Date object without the offset "+0000" being applied, but I keep getting a different time when running my code:我需要将字符串转换为 Date 对象而不应用偏移量“+0000”,但是在运行我的代码时我总是得到不同的时间:
DateTimeFormatter isoFormat = ISODateTimeFormat.dateTimeParser();
Date date = isoFormat.parseDateTime("2020-09-09T09:58:00+0000").toDate();
// Wed Sep 09 05:58:00 EDT 2020
As you can see above the date has changed.如您所见,日期已更改。
Instead, I would like to keep the same date and time like: Wed Sep 09 09:58:00, so I can convert this Date object to a String with "yyyy-MM-dd", "HH:mm:ss", and "yyyy-MM-dd'T'HH:mm:ss" format respectively.相反,我想保持相同的日期和时间,例如:Wed Sep 09 09:58:00,所以我可以将此日期对象转换为带有“yyyy-MM-dd”、“HH:mm:ss”的字符串,和“yyyy-MM-dd'T'HH:mm:ss”格式。
I recommend you do it with the modern java.time
date-time API and the corresponding formatting API (package, java.time.format
).我建议您使用现代
java.time
日期时间 API 和相应的格式化 API(包, java.time.format
)来完成。 Learn more about the modern date-time API from Trail: Date Time .从Trail: Date Time 中了解有关现代日期时间 API 的更多信息。
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
// The given date-time string
String strDateTime = "2020-09-09T09:58:00+0000";
// Define the formatter
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssZ");
// Parse the given date-time string into OffsetDateTime
OffsetDateTime odt = OffsetDateTime.parse(strDateTime, formatter);
// Output OffsetDateTime in the default format
System.out.println(odt);
// Print OffsetDateTime using the defined formatter
String formatted = formatter.format(odt);
System.out.println(formatted);
}
}
Output:输出:
2020-09-09T09:58Z
2020-09-09T09:58:00+0000
Note: java.util.Date
does not represent a Date/Time object.注意:
java.util.Date
不代表日期/时间对象。 It simply represents the no.它只是代表没有。 of milliseconds from the epoch of
1970-01-01T00:00:00Z
.从
1970-01-01T00:00:00Z
时代开始的毫秒数。 It does not have any time-zone or zone-offset information.它没有任何时区或区域偏移信息。 When you print it, Java prints the string obtained by applying the time-zone of your JVM.
当您打印它时,Java 会打印通过应用 JVM 的时区获得的字符串。 I suggest you stop using
java.util.Date
and switch to the modern date-time API.我建议您停止使用
java.util.Date
并切换到现代日期时间 API。
Using joda date-time API, you can do it as follows:使用 joda 日期时间 API,您可以按如下方式进行:
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
public class Main {
public static void main(String[] args) {
// The given date-time string
String strDateTime = "2020-09-09T09:58:00+0000";
// Define the formatter
DateTimeFormatter isoFormat = ISODateTimeFormat.dateTimeParser();
DateTime dateTime = isoFormat.parseDateTime("2020-09-09T09:58:00+0000");
// Display DateTime in the default format
System.out.println(dateTime);
// Define formatter for ouput
DateTimeFormatter outputFormat = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssZ").withZoneUTC();
// Display DateTime in the defined output format
String formatted = outputFormat.print(dateTime);
System.out.println(formatted);
}
}
Output:输出:
2020-09-09T10:58:00.000+01:00
2020-09-09T09:58:00+0000
The first and most important part of the answer is: don't convert to an old-fashioned Date
.答案的第一个也是最重要的部分是:不要转换为老式的
Date
。 Either stick to Joda-Time or migrate to java.time, the modern Java date and time API, as already covered in the good answer by Arvind Kumar Avinash.要么坚持使用 Joda-Time,要么迁移到 java.time,现代 Java 日期和时间 API,正如 Arvind Kumar Avinash 的好答案中已经介绍的那样。
Since you are already using Joda-Time, I am showing you a Joda-Time solution.由于您已经在使用 Joda-Time,我向您展示了一个 Joda-Time 解决方案。 The trick for persuading the formatter into keeping the time and offset from the string parsed is
withOffsetParsed()
.说服格式化程序保留解析字符串的时间和偏移量的技巧是
withOffsetParsed()
。
DateTimeFormatter isoFormat
= ISODateTimeFormat.dateTimeParser().withOffsetParsed();
String incomingString = "2020-09-09T09:58:00+0000";
DateTime dateTime = isoFormat.parseDateTime(incomingString);
However!然而! If I have guessed correctly that you want to store date and time in UTC (a recommended practice), better than
withOffsetParsed()
is to specify UTC on the parser:如果我猜对了您想以 UTC 存储日期和时间(推荐的做法),比
withOffsetParsed()
更好的是在解析器上指定 UTC:
DateTimeFormatter isoFormat
= ISODateTimeFormat.dateTimeParser().withZoneUTC();
Now you will also get the correct time if one day a string with a non-zero UTC offset comes in.现在,如果有一天出现具有非零 UTC 偏移量的字符串,您也将获得正确的时间。
In any case we may now format your obtained DateTime
into the strings you requested.在任何情况下,我们现在都可以将您获得的
DateTime
格式化为您请求的字符串。
String dateString = dateTime.toString(ISODateTimeFormat.date());
System.out.println(dateString);
String timeString = dateTime.toString(ISODateTimeFormat.hourMinuteSecond());
System.out.println(timeString);
String dateTimeString = dateTime.toString(ISODateTimeFormat.dateHourMinuteSecond());
System.out.println(dateTimeString);
Output:输出:
2020-09-09 09:58:00 2020-09-09T09:58:00
What was wrong with using Date
?使用
Date
什么问题? First, the Date
class is poorly designed and long outdated.首先,
Date
类的设计很差,而且已经过时了。 Second, a Date
was just a point in time, it didn't have a concept of date and time of day (they tried building that into it in Java 1.0, but gave up and deprecated it in Java 1.1 in 1997).其次,
Date
只是一个时间点,它没有日期和时间的概念(他们尝试在 Java 1.0 中构建它,但在 1997 年的 Java 1.1 中放弃并弃用了它)。 So a Date
cannot hold the date and time of day in UTC for you.因此
Date
不能为您保存 UTC 中的日期和时间。
What happened in your code was that you got a Date
representing the correct point in time.您的代码中发生的事情是您获得了一个代表正确时间点的
Date
。 Only when you printed that Date
you were implicitly invoking its toString
method.仅当您打印该
Date
时,您才隐式调用其toString
方法。 Date.toString()
confusingly grabs the JVM's time zone setting (in your case apparently North American Eastern Time) and uses it for rendering the string to be returned. Date.toString()
令人困惑地获取 JVM 的时区设置(在您的情况下显然是北美东部时间)并使用它来呈现要返回的字符串。 So in your case the point in time was rendered as Wed Sep 09 05:58:00 EDT 2020
.因此,在您的情况下,时间点呈现为
Wed Sep 09 05:58:00 EDT 2020
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.