我需要在Java中解析RFC 2822日期的字符串表示。以下是一个示例字符串:
Sat, 13 Mar 2010 11:29:05 -0800
这看起来相当复杂,因此我想确保我做的一切都是正确的,并且不会出现日期通过AM-PM / 军事时间问题、UTC时间问题等错误被解释错误的奇怪问题。
谢谢!
这是快速代码,使用SimpleDateFormat实现了你的需求。
String rfcDate = "Sat, 13 Mar 2010 11:29:05 -0800";
String pattern = "EEE, dd MMM yyyy HH:mm:ss Z";
SimpleDateFormat format = new SimpleDateFormat(pattern);
Date javaDate = format.parse(rfcDate);
//Done.
PS. 我在这里没有处理异常和并发(因为SimpleDateFormat在解析日期时不是同步的)。
SimpleDateFormat
和 Date
类已经被现代的 JSR 310 中定义的 java.time 类取代多年了。请参阅 pathfinder78 的答案。 - Basil Bourque如果你的应用程序使用的语言不是英语,你可能想要通过使用另一个SimpleDateFormat构造函数来强制指定日期解析/格式化的本地化信息:
String pattern = "EEE, dd MMM yyyy HH:mm:ss Z";
SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.ENGLISH);
day-of-week
是可选的,而且 time-of-day
中的秒也被声明为可选项:time-of-day = hour ":" minute [ ":" second ]
。 - Roman VottnerDateTimeFormatter.RFC_1123_DATE_TIME
自Java 8以来,新的日期时间类被实现:java.time.ZonedDateTime
和java.time.LocalDateTime
。 ZonedDateTime
几乎可以直接支持解析RFC字符串:
String rfcDate = "Tue, 4 Dec 2018 17:37:31 +0100 (CET)";
if (rfcDate.matches(".*[ ]\\(\\w\\w\\w\\)$")) {
//Brackets with time zone are added sometimes, for example by JavaMail
//This must be removed before parsing
//from: "Tue, 4 Dec 2018 17:37:31 +0100 (CET)"
// to: "Tue, 4 Dec 2018 17:37:31 +0100"
rfcDate = rfcDate.substring(0, rfcDate.length() - 6);
}
//and now parsing...
DateTimeFormatter dateFormat = DateTimeFormatter.RFC_1123_DATE_TIME;
try {
ZonedDateTime zoned = ZonedDateTime.parse(rfcDate, dateFormat);
LocalDateTime local = zoned.toLocalDateTime();
} catch (DateTimeParseException e) { ... }
ZonedDateTime
转换为LocalDateTime
。这样做会丢失有价值的信息——时区,而没有获得任何好处。就像没有特定货币背景下的金额一样,LocalDateTime
是模糊的,因此无法表示一个时刻。 - Basil Bourque有一个javax.mail类可以执行RFC-2822日期的解析:
javax.mail.internet.MailDateFormat
包括可选和过时的格式。
只需执行以下操作:
new javax.mail.internet.MailDateFormat().parse("Sat, 13 Mar 2010 11:29:00 -0800")
new javax.mail.internet.MailDateFormat().parse("13 Mar 2010 11:29:00 -0800")
new javax.mail.internet.MailDateFormat().parse("13 Mar 2010 11:29 -0800")
它将正确解析这些有效的RFC-2822日期。
至于其他旧的日期格式化程序,MailDateFormat
类不是线程安全的。
OffsetDateTime
用于表示带有时区偏移量的日期时间。请注意保留HTML标签。import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
class Main {
public static void main(String[] args) {
String strRFC2822DateTimeStr = "Sat, 13 Mar 2010 11:29:05 -0800";
OffsetDateTime odt = OffsetDateTime.parse(strRFC2822DateTimeStr, DateTimeFormatter.RFC_1123_DATE_TIME);
System.out.println(odt);
// Alternatively: using a custom DateTimeFormatter
DateTimeFormatter parser = DateTimeFormatter.ofPattern("EEE, dd MMM uuuu HH:mm:ss XX", Locale.ENGLISH);
System.out.println(OffsetDateTime.parse(strRFC2822DateTimeStr, parser));
// In case you need the equivalent date-time at UTC
OffsetDateTime odtUtc = odt.withOffsetSameInstant(ZoneOffset.UTC);
System.out.println(odtUtc);
}
}
输出:
2010-03-13T11:29:05-08:00
2010-03-13T11:29:05-08:00
2010-03-13T19:29:05Z
了解有关现代日期时间API的更多信息,请参阅Trail: Date Time。
一些有用的链接:
试试这个:
String dateTime = OffsetDateTime.now().format(DateTimeFormatter.RFC_1123_DATE_TIME);
//RFC_1123 == RFC_2822
OffsetDateTme
(或其他日期时间对象)的。感谢您的贡献。 - Ole V.V.
java.text.SimpleDateFormat
吗? - skaffman