Reputation: 50422
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!
Upvotes: 21
Views: 17122
Reputation: 76
Try this:
String dateTime = OffsetDateTime.now().format(DateTimeFormatter.RFC_1123_DATE_TIME);
//RFC_1123 == RFC_2822
Upvotes: 2
Reputation: 79620
RFC 2822 date-time string contains timezone offset e.g. the given string Sat, 13 Mar 2010 11:29:05 -0800 has a timezone offset of -08:00 hours from UTC i.e. the equivalent date-time at UTC can be obtained by adding 8 hours to Sat, 13 Mar 2010 11:29:05.
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";
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);
}
}
Output:
2010-03-13T11:29:05-08:00
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:
y
instead of u
but I prefer u
to y
.OffsetDateTime
with JDBC.Upvotes: 1
Reputation: 71
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) { ... }
Upvotes: 4
Reputation: 5440
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.
Upvotes: 3
Reputation: 89209
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).
Upvotes: 27
Reputation: 61
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.
Upvotes: 6
Reputation: 1207
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);
Upvotes: 20