Java 将 ISO 8601 字符串转换为日期,忽略偏移量
Java convert ISO 8601 string to Date ignoring offset
我收到以下格式的字符串“yyyy-MM-dd'T'HH:mm:ssZ”,例如:2020-09-09T09:58:00+0000”偏移量为 UTC。
我需要在不应用偏移量“+0000”的情况下将字符串转换为 Date 对象,但是当 运行 我的代码:
DateTimeFormatter isoFormat = ISODateTimeFormat.dateTimeParser();
Date date = isoFormat.parseDateTime("2020-09-09T09:58:00+0000").toDate();
// Wed Sep 09 05:58:00 EDT 2020
如您所见,日期已更改。
相反,我想保留相同的日期和时间,例如:Wed Sep 09 09:58:00,因此我可以将此 Date 对象转换为带有“yyyy-MM-dd”、“HH”的字符串: mm:ss”和“yyyy-MM-dd'T'HH:mm:ss”格式。
我建议您使用 modern java.time
date-time API and the corresponding formatting API (package, java.time.format
). Learn more about the modern date-time API from Trail: Date Time。
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);
}
}
输出:
2020-09-09T09:58Z
2020-09-09T09:58:00+0000
注意: java.util.Date
不代表 Date/Time 对象。它只是代表没有。从 1970-01-01T00:00:00Z
纪元算起的毫秒数。它没有任何 time-zone 或 zone-offset 信息。当您打印它时,Java 打印通过应用您的 JVM 的 time-zone 获得的字符串。我建议你停止使用 java.util.Date
并切换到现代 date-time API.
使用joda date-time 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);
}
}
输出:
2020-09-09T10:58:00.000+01:00
2020-09-09T09:58:00+0000
答案的第一个也是最重要的部分是:不要转换为 old-fashioned Date
。坚持使用 Joda-Time 或迁移到 java.time,现代的 Java 日期和时间 API,正如 Arvind Kumar Avinash 的好答案中所述。
由于您已经在使用 Joda-Time,我将向您展示一个 Joda-Time 解决方案。说服格式化程序保留解析字符串的时间和偏移量的技巧是 withOffsetParsed()
.
DateTimeFormatter isoFormat
= ISODateTimeFormat.dateTimeParser().withOffsetParsed();
String incomingString = "2020-09-09T09:58:00+0000";
DateTime dateTime = isoFormat.parseDateTime(incomingString);
但是!如果我猜对了你想以 UTC 格式存储日期和时间(推荐做法),比 withOffsetParsed()
更好的方法是在解析器上指定 UTC:
DateTimeFormatter isoFormat
= ISODateTimeFormat.dateTimeParser().withZoneUTC();
现在,如果有一天出现具有 non-zero UTC 偏移量的字符串,您也将获得正确的时间。
无论如何,我们现在可以将您获得的 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);
输出:
2020-09-09
09:58:00
2020-09-09T09:58:00
使用 Date
有什么问题? 首先,Date
class 设计不佳且早已过时。其次,Date
只是一个时间点,它没有日期和时间的概念(他们试图在 Java 1.0 中将其构建到其中,但放弃并弃用了它Java 1997 年的 1.1)。因此 Date
无法为您保存 UTC 日期和时间。
您的代码中发生的事情是您获得了代表正确时间点的 Date
。仅当您打印 Date
时,您才隐式调用其 toString
方法。 Date.toString()
混淆地获取 JVM 的时区设置(在您的情况下显然是北美东部时间)并使用它来呈现要返回的字符串。因此,在您的情况下,时间点呈现为 Wed Sep 09 05:58:00 EDT 2020
.
我收到以下格式的字符串“yyyy-MM-dd'T'HH:mm:ssZ”,例如:2020-09-09T09:58:00+0000”偏移量为 UTC。
我需要在不应用偏移量“+0000”的情况下将字符串转换为 Date 对象,但是当 运行 我的代码:
DateTimeFormatter isoFormat = ISODateTimeFormat.dateTimeParser();
Date date = isoFormat.parseDateTime("2020-09-09T09:58:00+0000").toDate();
// Wed Sep 09 05:58:00 EDT 2020
如您所见,日期已更改。
相反,我想保留相同的日期和时间,例如:Wed Sep 09 09:58:00,因此我可以将此 Date 对象转换为带有“yyyy-MM-dd”、“HH”的字符串: mm:ss”和“yyyy-MM-dd'T'HH:mm:ss”格式。
我建议您使用 modern java.time
date-time API and the corresponding formatting API (package, java.time.format
). Learn more about the modern date-time API from Trail: Date Time。
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);
}
}
输出:
2020-09-09T09:58Z
2020-09-09T09:58:00+0000
注意: java.util.Date
不代表 Date/Time 对象。它只是代表没有。从 1970-01-01T00:00:00Z
纪元算起的毫秒数。它没有任何 time-zone 或 zone-offset 信息。当您打印它时,Java 打印通过应用您的 JVM 的 time-zone 获得的字符串。我建议你停止使用 java.util.Date
并切换到现代 date-time API.
使用joda date-time 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);
}
}
输出:
2020-09-09T10:58:00.000+01:00
2020-09-09T09:58:00+0000
答案的第一个也是最重要的部分是:不要转换为 old-fashioned Date
。坚持使用 Joda-Time 或迁移到 java.time,现代的 Java 日期和时间 API,正如 Arvind Kumar Avinash 的好答案中所述。
由于您已经在使用 Joda-Time,我将向您展示一个 Joda-Time 解决方案。说服格式化程序保留解析字符串的时间和偏移量的技巧是 withOffsetParsed()
.
DateTimeFormatter isoFormat
= ISODateTimeFormat.dateTimeParser().withOffsetParsed();
String incomingString = "2020-09-09T09:58:00+0000";
DateTime dateTime = isoFormat.parseDateTime(incomingString);
但是!如果我猜对了你想以 UTC 格式存储日期和时间(推荐做法),比 withOffsetParsed()
更好的方法是在解析器上指定 UTC:
DateTimeFormatter isoFormat
= ISODateTimeFormat.dateTimeParser().withZoneUTC();
现在,如果有一天出现具有 non-zero UTC 偏移量的字符串,您也将获得正确的时间。
无论如何,我们现在可以将您获得的 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);
输出:
2020-09-09 09:58:00 2020-09-09T09:58:00
使用 Date
有什么问题? 首先,Date
class 设计不佳且早已过时。其次,Date
只是一个时间点,它没有日期和时间的概念(他们试图在 Java 1.0 中将其构建到其中,但放弃并弃用了它Java 1997 年的 1.1)。因此 Date
无法为您保存 UTC 日期和时间。
您的代码中发生的事情是您获得了代表正确时间点的 Date
。仅当您打印 Date
时,您才隐式调用其 toString
方法。 Date.toString()
混淆地获取 JVM 的时区设置(在您的情况下显然是北美东部时间)并使用它来呈现要返回的字符串。因此,在您的情况下,时间点呈现为 Wed Sep 09 05:58:00 EDT 2020
.