1 package com.bradmcevoy.http;
2
3 import java.text.DateFormat;
4 import java.text.ParseException;
5 import java.text.SimpleDateFormat;
6 import java.util.Arrays;
7 import java.util.Calendar;
8 import java.util.Collection;
9 import java.util.Date;
10 import java.util.Iterator;
11 import java.util.Locale;
12 import java.util.TimeZone;
13 import org.slf4j.Logger;
14 import org.slf4j.LoggerFactory;
15
16
17
18
19
20
21
22
23
24 public class DateUtils {
25
26 private static final Logger log = LoggerFactory.getLogger( DateUtils.class );
27
28 public static final String PATTERN_WEBDAV = "yyyy-MM-dd HH:mm:ss";
29
30
31
32 public static final String PATTERN_RESPONSE_HEADER = "E, dd MMM yyyy HH:mm:ss z";
33
34 private static final ThreadLocal<DateFormat> thHeaderDateFormat = new ThreadLocal<DateFormat>();
35
36
37
38 public static final String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz";
39
40
41
42 public static final String PATTERN_RFC1123_NOSECS = "EEE, dd MMM yyyy HH:mm zzz";
43
44
45
46 public static final String PATTERN_RFC1036 = "EEEE, dd-MMM-yy HH:mm:ss zzz";
47
48
49
50
51 public static final String PATTERN_ASCTIME = "EEE MMM d HH:mm:ss yyyy";
52
53
54
55
56 public static final String PATTERN_ASCTIME2 = "EEE MMM yyyy HH:mm:ss zzz";
57 private static final Collection<String> DEFAULT_PATTERNS = Arrays.asList(
58 new String[]{PATTERN_ASCTIME, PATTERN_ASCTIME2, PATTERN_RFC1036, PATTERN_RFC1123, PATTERN_RFC1123_NOSECS, PATTERN_WEBDAV} );
59 private static final Date DEFAULT_TWO_DIGIT_YEAR_START;
60
61 static {
62 Calendar calendar = Calendar.getInstance();
63 calendar.set( 2000, Calendar.JANUARY, 1, 0, 0 );
64 DEFAULT_TWO_DIGIT_YEAR_START = calendar.getTime();
65 }
66 public static final TimeZone GMT = TimeZone.getTimeZone( "GMT" );
67
68
69
70
71
72
73 public static Date parseWebDavDate(String s) throws DateParseException {
74
75 s = s.replace( 'Z', ' ');
76 s = s.replace( 'T', ' ');
77 s = s.trim();
78 return parseDate( s );
79 }
80
81
82
83
84
85
86
87
88
89
90
91
92 public static Date parseDate( String dateValue ) throws DateParseException {
93 return parseDate( dateValue, null, null );
94 }
95
96
97
98
99
100
101
102
103
104
105
106 public static Date parseDate( String dateValue, Collection<String> dateFormats )
107 throws DateParseException {
108 return parseDate( dateValue, dateFormats, null );
109 }
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125 public static Date parseDate(
126 String dateValue,
127 Collection<String> dateFormats,
128 Date startDate ) throws DateParseException {
129
130
131 if( dateValue == null ) {
132 throw new IllegalArgumentException( "dateValue is null" );
133 }
134 if( dateFormats == null ) {
135 dateFormats = DEFAULT_PATTERNS;
136 }
137 if( startDate == null ) {
138 startDate = DEFAULT_TWO_DIGIT_YEAR_START;
139 }
140
141
142 if( dateValue.length() > 1
143 && dateValue.startsWith( "'" )
144 && dateValue.endsWith( "'" ) ) {
145 dateValue = dateValue.substring( 1, dateValue.length() - 1 );
146 }
147
148 SimpleDateFormat dateParser = null;
149 Iterator<String> formatIter = dateFormats.iterator();
150
151 while( formatIter.hasNext() ) {
152 String format = formatIter.next();
153 if( dateParser == null ) {
154 dateParser = new SimpleDateFormat( format, Locale.US );
155 dateParser.setTimeZone( TimeZone.getTimeZone( "GMT" ) );
156 dateParser.set2DigitYearStart( startDate );
157 } else {
158 dateParser.applyPattern( format );
159 }
160 try {
161 Date dt = dateParser.parse( dateValue );
162 return dt;
163 } catch( ParseException pe ) {
164
165 }
166 }
167
168
169 throw new DateParseException( "Unable to parse the date " + dateValue );
170 }
171
172 public static String formatDate( Date date ) {
173 Calendar cal = Calendar.getInstance(GMT );
174 cal.setTime( date );
175 return formatDate( cal );
176 }
177
178
179
180
181
182 public static String formatDate( Calendar cal ) {
183
184 StringBuilder sb = new StringBuilder();
185 sb.append( cal.get( Calendar.YEAR ) + "" );
186 sb.append( '-' );
187 sb.append( pad2( cal.get( Calendar.MONTH ) + 1 ) );
188 sb.append( '-' );
189 sb.append( pad2( cal.get( Calendar.DAY_OF_MONTH ) ) );
190
191
192
193
194 sb.append( 'T' );
195 sb.append( pad2( cal.get( Calendar.HOUR_OF_DAY ) ) );
196 sb.append( ':' );
197 sb.append( pad2( cal.get( Calendar.MINUTE ) ) );
198 sb.append( ':' );
199 sb.append( pad2( cal.get( Calendar.SECOND ) ) );
200 sb.append( 'Z' );
201 String s = sb.toString();
202
203 return s;
204 }
205
206 public static String formatForHeader( Date date ) {
207 DateFormat df = thHeaderDateFormat.get();
208 if( df == null ) {
209 df = new SimpleDateFormat( DateUtils.PATTERN_RESPONSE_HEADER );
210 df.setTimeZone( TimeZone.getTimeZone( "GMT" ) );
211 thHeaderDateFormat.set( df );
212 }
213 return df.format( date );
214 }
215
216 public static String pad2( int i ) {
217 if( i < 10 ) {
218 return "0" + i;
219 } else {
220 return i + "";
221 }
222 }
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237 public static String formatDate( Date date, String pattern ) {
238 if( date == null ) throw new IllegalArgumentException( "date is null" );
239 if( pattern == null )
240 throw new IllegalArgumentException( "pattern is null" );
241
242 SimpleDateFormat formatter = new SimpleDateFormat( pattern, Locale.US );
243 formatter.setTimeZone( GMT );
244 return formatter.format( date );
245 }
246
247
248
249
250
251
252
253 public static String formatForWebDavModifiedDate( Date date ) {
254 return formatDate( date, PATTERN_RFC1123 );
255 }
256
257
258 private DateUtils() {
259 }
260
261 public static class DateParseException extends Exception {
262
263 static final long serialVersionUID = 4417696455000643370L;
264
265
266
267
268 public DateParseException() {
269 super();
270 }
271
272
273
274
275 public DateParseException( String message ) {
276 super( message );
277 }
278 }
279 }
280