1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 package org.apache.commons.httpclient.util;
31
32 import java.text.ParseException;
33 import java.text.SimpleDateFormat;
34 import java.util.Arrays;
35 import java.util.Collection;
36 import java.util.Date;
37 import java.util.Iterator;
38 import java.util.Locale;
39 import java.util.TimeZone;
40
41 import org.apache.commons.httpclient.params.DefaultHttpParams;
42 import org.apache.commons.logging.Log;
43 import org.apache.commons.logging.LogFactory;
44
45 /***
46 * A utility class for parsing HTTP dates as used in cookies and other headers.
47 * This class handles dates as defined by RFC 2616 section 3.3.1 as well as
48 * some other common non-standard formats.
49 *
50 * @author Christopher Brown
51 * @author Michael Becke
52 */
53 public class DateParser {
54
55 /*** Log object for this class. */
56 private static final Log LOG = LogFactory.getLog(DateParser.class);
57
58 /***
59 * The key used to look up the date patterns used for parsing. The String patterns are stored
60 * in a {@link Collection} and must be compatible with {@link SimpleDateFormat}.
61 *
62 * @see org.apache.commons.httpclient.params.DefaultHttpParams
63 */
64 public static final String KEY_DATE_PATTERNS = "http.dateParser.patterns";
65
66 /***
67 * Date format pattern used to parse HTTP date headers in RFC 1123 format.
68 */
69 public static final String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz";
70
71 /***
72 * Date format pattern used to parse HTTP date headers in RFC 1036 format.
73 */
74 public static final String PATTERN_RFC1036 = "EEEE, dd-MMM-yy HH:mm:ss zzz";
75
76 /***
77 * Date format pattern used to parse HTTP date headers in ANSI C
78 * <code>asctime()</code> format.
79 */
80 public static final String PATTERN_ASCTIME = "EEE MMM d HH:mm:ss yyyy";
81
82 /***
83 * Parses a date value. The formats used for parsing the date value are retrieved from
84 * the default http params.
85 *
86 * @param dateValue the date value to parse
87 *
88 * @return the parsed date
89 *
90 * @throws DateParseException if the value could not be parsed using any of the
91 * supported date formats
92 *
93 * @see DefaultHttpParams#getDefaultParams()
94 */
95 public static Date parseDate(String dateValue) throws DateParseException {
96
97 Collection patterns = (Collection) DefaultHttpParams.getDefaultParams().getParameter(
98 KEY_DATE_PATTERNS
99 );
100 if (patterns == null) {
101 LOG.warn("DateParser patterns not included in the default params.");
102 patterns = Arrays.asList(
103 new String[] { PATTERN_ASCTIME, PATTERN_RFC1036, PATTERN_RFC1123 }
104 );
105 }
106 return parseDate(dateValue, patterns);
107 }
108
109 /***
110 * Parses the date value using the given date formats.
111 *
112 * @param dateValue the date value to parse
113 * @param dateFormats the date formats to use
114 *
115 * @return the parsed date
116 *
117 * @throws DateParseException if none of the dataFormats could parse the dateValue
118 */
119 private static Date parseDate(
120 String dateValue,
121 Collection dateFormats
122 ) throws DateParseException {
123
124 if (dateValue == null) {
125 throw new IllegalArgumentException("dateValue is null");
126 }
127
128
129
130 if (dateValue.length() > 1
131 && dateValue.startsWith("'")
132 && dateValue.endsWith("'")
133 ) {
134 dateValue = dateValue.substring (1, dateValue.length() - 1);
135 }
136
137 SimpleDateFormat dateParser = null;
138 Iterator formatIter = dateFormats.iterator();
139
140 while (formatIter.hasNext()) {
141 String format = (String) formatIter.next();
142 if (dateParser == null) {
143 dateParser = new SimpleDateFormat(format, Locale.US);
144 dateParser.setTimeZone(TimeZone.getTimeZone("GMT"));
145 } else {
146 dateParser.applyPattern(format);
147 }
148 try {
149 return dateParser.parse(dateValue);
150 } catch (ParseException pe) {
151
152 }
153 }
154
155
156 throw new DateParseException("Unable to parse the date " + dateValue);
157 }
158
159 /*** This class should not be instantiated. */
160 private DateParser() { }
161
162 }