63

HTTP Last-Modified header contains date in following format (example):
Wed, 09 Apr 2008 23:55:38 GMT
What is the easiest way to parse java.util.Date from this string?

the_drow
  • 18,571
  • 25
  • 126
  • 193
levanovd
  • 4,095
  • 6
  • 37
  • 56

5 Answers5

75

This should be pretty close

String dateString = "Wed, 09 Apr 2008 23:55:38 GMT";
SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");
Date d = format.parse(dateString);

SimpleDateFormat

Alexander Klimetschek
  • 3,585
  • 31
  • 36
Shaun
  • 1,478
  • 10
  • 9
  • 3
    +1 almost correct, the `hh` should be `HH`, as the hours are 0-23. – notnoop Dec 18 '09 at 19:24
  • I also had the timezone "ZZZ" instead of "zzz". Hopefully that will do it. If you still have issues you can reference the documentation linked above. – Shaun Dec 18 '09 at 19:59
  • 1
    Works great for me, thank you! The only thing that I should say is that this example is for Locale.ENGLISH. – levanovd Dec 18 '09 at 19:59
  • 7
    If you're doing this often make sure you reuse the SimpleDateFormat object (they're amazingly expensive to construct) and synchronize on it when calling `parse` (they're not threadsafe). – Ry4an Brase Dec 18 '09 at 20:08
  • 20
    The standard allows not one format, but **three** formats. http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3 – Sridhar Ratnakumar Jan 20 '10 at 21:34
  • 5
    If you are going to compare that Date object to a time stamp in your application, remember that the header **only include whole seconds** and you should discard the 3 least significant digits to be able to compare properly. So do (TS/1000)*1000 == headerTS if needed. – PålOliver May 12 '11 at 11:48
  • 8
    Anyone getting a "ParseException: Unparseable date"? – koppor Apr 12 '12 at 17:06
  • @Ry4an synchronizing is an option as DateFormat instances are not threadsafe, but using a ThreadLocal variable can be more efficient if the instance is going to be contended for often. – Mike Deck Jun 13 '12 at 21:36
  • 1
    java.text.ParseException: Unparseable date: "Wed, 09 Apr 2008 23:55:38 GMT"at java.text.DateFormat.parse(Unknown Source) – Daniel Magnusson Jul 09 '12 at 10:57
  • 3
    I think it could be `new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);` not to fail on other locales. – Iree Jan 09 '15 at 00:40
  • 12
    To avoid `ParseException` use `new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US)` instead – Roman Jan 11 '15 at 10:22
  • 1
    https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified states that the time zone must always be exactly "GMT". Therefore, a `format.setTimeZone(TimeZone.getTimeZone("GMT"));` is is necessary, when using the same format for also creating `Last-Modified` header values. – haui Jan 25 '17 at 07:53
  • 5
    @SridharRatnakumar Two of the three formats are now obsolete, so `new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US)` is all you need now. [https://tools.ietf.org/html/rfc7231#page-65](https://tools.ietf.org/html/rfc7231#page-65) – Dylan Smith Nov 13 '17 at 14:06
  • Submitted an edit request according to @DylanSmith 's comment. – Markus Appel Oct 01 '18 at 13:58
63

DateUtil.parseDate(dateString) from apache http-components

(legacy: DateUtil.parseDate(dateString) (from apache commons-httpclient))

It has the correct format defined as a Constant, which is guaranteed to be compliant with the protocol.

Korhan Ozturk
  • 11,148
  • 6
  • 36
  • 49
Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • 1
    BTW, commons-httpclient has been superseded by org.apache.httpcomponents:httpclient. – John Glassmyer Feb 20 '12 at 11:42
  • 2
    The class is now org.apache.http.impl.cookie.DateUtils http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/impl/cookie/DateUtils.html – daveb Feb 22 '13 at 10:07
  • 1
    I had to use `org.apache.http.client.utils.DateUtils`, `httpclient-4.3.3` – membersound Apr 23 '14 at 08:21
  • DateUtil still uses SimpleDateFormat inside with a ThreadLocal cache. If you are looking also for performance see joda DateTimeFormatter – Massimo Feb 11 '17 at 00:02
35

java.time

When using the new Java Date and Time API the code would simply be:

ZonedDateTime zdt = ZonedDateTime.parse("Wed, 09 Apr 2008 23:55:38 GMT", DateTimeFormatter.RFC_1123_DATE_TIME);

The DateTimeFormatter class pre-defines a constant for that particular format in RFC_1123_DATE_TIME. As the name suggests, RFC 1123 defines that format.

Community
  • 1
  • 1
Stan Svec
  • 449
  • 1
  • 5
  • 8
25

RFC 2616 defines three different date formats that a conforming client must understand.

The Apache HttpClient provides a DateUtil that complies with the standard:

https://hc.apache.org/httpcomponents-client-4.3.x/httpclient/apidocs/org/apache/http/client/utils/DateUtils.html

https://apache.googlesource.com/httpclient/+/4.3.x/httpclient/src/main/java/org/apache/http/client/utils/DateUtils.java

Date date = DateUtils.parseDate( headerValue );

Loda
  • 1,970
  • 2
  • 20
  • 40
ralfstx
  • 3,893
  • 2
  • 25
  • 41
  • 3
    Just a minor point in case people get confused: the date format RFC is 1123, which is referred to from RFC 2616 here: http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1 – daveb Feb 22 '13 at 10:04
  • 1
    @Raedwald which itself is superseded by [RFC 2822](https://www.ietf.org/rfc/rfc2822.txt). – ian Jul 19 '13 at 07:47
5

If you're using URLConnections, there is already a handy method.

See URLConnection#getLastModified

This method parses the date string and returns a milliseconds value. Then you can happily create a Date with that value.

Jin Kwon
  • 20,295
  • 14
  • 115
  • 184
  • 1
    Note that this method uses the deprecated `Date.parse` method, at least as of Oracle JDK 7, which _seems_ to support all three HTTP 1.1 [Full Date](http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1) formats. – Trevor Robinson Dec 08 '14 at 20:53