简体   繁体   English

在 JAVA 中解析 RFC 2822 日期

[英]Parsing RFC 2822 date in JAVA

I need to parse an RFC 2822 string representation of a date in Java.我需要解析 Java 中日期的 RFC 2822 字符串表示形式。 An example string is here:示例字符串在这里:

Sat, 13 Mar 2010 11:29:05 -0800 2010 年 3 月 13 日星期六 11:29:05 -0800

It looks pretty nasty so I wanted to make sure I was doing everything right and would run into weird problems later with the date being interpreted wrong either through AM-PM/Military time problems, UTC time problems, problems I don't anticipate, etc...它看起来很糟糕,所以我想确保我做的一切都是正确的,并且以后会遇到奇怪的问题,因为日期被错误地解释为 AM-PM/军事时间问题、UTC 时间问题、我没有预料到的问题等...

Thanks!谢谢!

This is quick code that does what you ask (using SimpleDateFormat )这是执行您要求的快速代码(使用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.附注。 I've not dealt with exceptions and concurrency here (as SimpleDateFormat is not synchronized when parsing date).我没有在这里处理异常和并发(因为 SimpleDateFormat 在解析日期时不同步)。

If your application is using another language than English, you may want to force the locale for the date parsing/formatting by using an alternate SimpleDateFormat constructor:如果您的应用程序使用的不是英语的另一种语言,您可能希望通过使用备用 SimpleDateFormat 构造函数来强制日期解析/格式化的语言环境:

String pattern = "EEE, dd MMM yyyy HH:mm:ss Z";
SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.ENGLISH);

Please keep in mind that the [day-of-week ","] is optional in RFC-2822, hence the suggested examples are not covering all RFC-2822 date formats.请记住,[星期几“,”] 在 RFC-2822 中是可选的,因此建议的示例并未涵盖所有 RFC-2822 日期格式。 Additional, the RFC-822 date type allowed many different time zone notations(obs-zone), which are not covered by the "Z" format specifier.此外,RFC-822 日期类型允许许多不同的时区符号(obs-zone),“Z”格式说明符未涵盖这些符号。

I guess there is no easy way out, other than looking for "," and "-|+" to determine which pattern to use.我想没有简单的出路,除了寻找“,”和“-|+”来确定使用哪种模式。

DateTimeFormatter.RFC_1123_DATE_TIME

Since Java 8 new datetime classes were implemented: java.time.ZonedDateTime and java.time.LocalDateTime .由于实现了 Java 8 新的日期时间类: java.time.ZonedDateTimejava.time.LocalDateTime ZonedDateTime supports the parsing of RFC strings nearly out of the box: 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) { ... }

There is a javax.mail class that perform the parsing of RFC-2822 dates :有一个 javax.mail 类执行 RFC-2822 日期的解析:

javax.mail.internet.MailDateFormat javax.mail.internet.MailDateFormat

including the optional and obsolete formats.包括可选的和过时的格式。

Just do :做就是了 :

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

It will correctly parse these valid RFC-2822 dates它将正确解析这些有效的 RFC-2822 日期

As for other old DateFormatters, the MailDateFormat class is not thread safe.至于其他旧的 DateFormatter, MailDateFormat类不是线程安全的。

String dateTime = OffsetDateTime.now().format(DateTimeFormatter.RFC_1123_DATE_TIME); //RFC_1123 == RFC_2822

RFC 2822 date-time string contains timezone offset eg the given string Sat, 13 Mar 2010 11:29:05 -0800 has a timezone offset of -08:00 hours from UTC ie the equivalent date-time at UTC can be obtained by adding 8 hours to Sat, 13 Mar 2010 11:29:05 . RFC 2822 日期时间字符串包含时区偏移量,例如给定的字符串Sat, 13 Mar 2010 11:29:05 -0800的时区偏移量为 -08:00 时距 UTC,即 UTC 的等效日期时间可以通过添加获得距 2010 年 3 月 13 日星期六 11:29:05 还有8 小时。

java.time java.time

The modern date-time API API has OffsetDateTime to represent a date-time with timezone offset. 现代日期时间 API API 具有OffsetDateTime来表示具有时区偏移的日期时间。

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";
        DateTimeFormatter parser = DateTimeFormatter.ofPattern("EEE, dd MMM uuuu HH:mm:ss XX", Locale.ENGLISH);
        OffsetDateTime odt = OffsetDateTime.parse(strRFC2822DateTimeStr, parser);
        System.out.println(odt);

        // In case you need the equivalent date-time at UTC
        OffsetDateTime odtUtc = odt.withOffsetSameInstant(ZoneOffset.UTC);
        System.out.println(odtUtc);
    }
}

Output :输出

2010-03-13T11:29:05-08:00
2010-03-13T19:29:05Z

Learn more about the modern Date-Time API from Trail: Date Time .Trail 了解有关现代日期时间 API 的更多信息:日期时间

Some useful links :一些有用的链接

  1. Never use SimpleDateFormat or DateTimeFormatter without a Locale .切勿在没有 Locale 的情况下使用 SimpleDateFormat 或 DateTimeFormatter
  2. You can use y instead of u but I prefer u to y .您可以使用y而不是u我更喜欢uy
  3. How to use OffsetDateTime with JDBC .如何将OffsetDateTime与 JDBC 一起使用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM