简体   繁体   中英

Parsing RFC 2822 date in JAVA

I need to parse an RFC 2822 string representation of a date in Java. An example string is here:

Sat, 13 Mar 2010 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...

Thanks!

This is quick code that does what you ask (using 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).

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:

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. Additional, the RFC-822 date type allowed many different time zone notations(obs-zone), which are not covered by the "Z" format specifier.

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 . ZonedDateTime supports the parsing of RFC strings nearly out of the box:

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.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

As for other old DateFormatters, the MailDateFormat class is not thread safe.

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 .

java.time

The modern date-time API API has OffsetDateTime to represent a date-time with timezone offset.

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 .

Some useful links :

  1. Never use SimpleDateFormat or DateTimeFormatter without a Locale .
  2. You can use y instead of u but I prefer u to y .
  3. How to use OffsetDateTime with JDBC .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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