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 package org.apache.http.client.utils;
29
30 import java.lang.ref.SoftReference;
31 import java.text.ParsePosition;
32 import java.text.SimpleDateFormat;
33 import java.util.Calendar;
34 import java.util.Date;
35 import java.util.HashMap;
36 import java.util.Locale;
37 import java.util.Map;
38 import java.util.TimeZone;
39
40 import org.apache.http.util.Args;
41
42
43
44
45
46
47
48
49 public final class DateUtils {
50
51
52
53
54 public static final String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz";
55
56
57
58
59 public static final String PATTERN_RFC1036 = "EEE, dd-MMM-yy HH:mm:ss zzz";
60
61
62
63
64
65 public static final String PATTERN_ASCTIME = "EEE MMM d HH:mm:ss yyyy";
66
67 private static final String[] DEFAULT_PATTERNS = new String[] {
68 PATTERN_RFC1123,
69 PATTERN_RFC1036,
70 PATTERN_ASCTIME
71 };
72
73 private static final Date DEFAULT_TWO_DIGIT_YEAR_START;
74
75 public static final TimeZone GMT = TimeZone.getTimeZone("GMT");
76
77 static {
78 final Calendar calendar = Calendar.getInstance();
79 calendar.setTimeZone(GMT);
80 calendar.set(2000, Calendar.JANUARY, 1, 0, 0, 0);
81 calendar.set(Calendar.MILLISECOND, 0);
82 DEFAULT_TWO_DIGIT_YEAR_START = calendar.getTime();
83 }
84
85
86
87
88
89
90
91
92
93 public static Date parseDate(final String dateValue) {
94 return parseDate(dateValue, null, null);
95 }
96
97
98
99
100
101
102
103
104
105 public static Date parseDate(final String dateValue, final String[] dateFormats) {
106 return parseDate(dateValue, dateFormats, null);
107 }
108
109
110
111
112
113
114
115
116
117
118
119
120
121 public static Date parseDate(
122 final String dateValue,
123 final String[] dateFormats,
124 final Date startDate) {
125 Args.notNull(dateValue, "Date value");
126 final String[] localDateFormats = dateFormats != null ? dateFormats : DEFAULT_PATTERNS;
127 final Date localStartDate = startDate != null ? startDate : DEFAULT_TWO_DIGIT_YEAR_START;
128 String v = dateValue;
129
130
131 if (v.length() > 1 && v.startsWith("'") && v.endsWith("'")) {
132 v = v.substring (1, v.length() - 1);
133 }
134
135 for (final String dateFormat : localDateFormats) {
136 final SimpleDateFormat dateParser = DateFormatHolder.formatFor(dateFormat);
137 dateParser.set2DigitYearStart(localStartDate);
138 final ParsePosition pos = new ParsePosition(0);
139 final Date result = dateParser.parse(v, pos);
140 if (pos.getIndex() != 0) {
141 return result;
142 }
143 }
144 return null;
145 }
146
147
148
149
150
151
152
153
154
155 public static String formatDate(final Date date) {
156 return formatDate(date, PATTERN_RFC1123);
157 }
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172 public static String formatDate(final Date date, final String pattern) {
173 Args.notNull(date, "Date");
174 Args.notNull(pattern, "Pattern");
175 final SimpleDateFormat formatter = DateFormatHolder.formatFor(pattern);
176 return formatter.format(date);
177 }
178
179
180
181
182
183
184 public static void clearThreadLocal() {
185 DateFormatHolder.clearThreadLocal();
186 }
187
188
189 private DateUtils() {
190 }
191
192
193
194
195
196
197
198 final static class DateFormatHolder {
199
200 private static final ThreadLocal<SoftReference<Map<String, SimpleDateFormat>>>
201 THREADLOCAL_FORMATS = new ThreadLocal<SoftReference<Map<String, SimpleDateFormat>>>();
202
203
204
205
206
207
208
209
210
211
212
213
214
215 public static SimpleDateFormat formatFor(final String pattern) {
216 final SoftReference<Map<String, SimpleDateFormat>> ref = THREADLOCAL_FORMATS.get();
217 Map<String, SimpleDateFormat> formats = ref == null ? null : ref.get();
218 if (formats == null) {
219 formats = new HashMap<String, SimpleDateFormat>();
220 THREADLOCAL_FORMATS.set(
221 new SoftReference<Map<String, SimpleDateFormat>>(formats));
222 }
223
224 SimpleDateFormat format = formats.get(pattern);
225 if (format == null) {
226 format = new SimpleDateFormat(pattern, Locale.US);
227 format.setTimeZone(TimeZone.getTimeZone("GMT"));
228 formats.put(pattern, format);
229 }
230
231 return format;
232 }
233
234 public static void clearThreadLocal() {
235 THREADLOCAL_FORMATS.remove();
236 }
237
238 }
239
240 }