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.hc.client5.http.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.hc.core5.http.Header;
41 import org.apache.hc.core5.http.MessageHeaders;
42 import org.apache.hc.core5.util.Args;
43
44
45
46
47
48
49
50
51 public final class DateUtils {
52
53
54
55
56 public static final String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz";
57
58
59
60
61 public static final String PATTERN_RFC1036 = "EEE, dd-MMM-yy HH:mm:ss zzz";
62
63
64
65
66
67 public static final String PATTERN_ASCTIME = "EEE MMM d HH:mm:ss yyyy";
68
69 private static final String[] DEFAULT_PATTERNS = new String[] {
70 PATTERN_RFC1123,
71 PATTERN_RFC1036,
72 PATTERN_ASCTIME
73 };
74
75 private static final Date DEFAULT_TWO_DIGIT_YEAR_START;
76
77 public static final TimeZone GMT = TimeZone.getTimeZone("GMT");
78
79 static {
80 final Calendar calendar = Calendar.getInstance();
81 calendar.setTimeZone(GMT);
82 calendar.set(2000, Calendar.JANUARY, 1, 0, 0, 0);
83 calendar.set(Calendar.MILLISECOND, 0);
84 DEFAULT_TWO_DIGIT_YEAR_START = calendar.getTime();
85 }
86
87
88
89
90
91
92
93
94
95 public static Date parseDate(final String dateValue) {
96 return parseDate(dateValue, null, null);
97 }
98
99
100
101
102
103
104
105
106
107
108
109 public static Date parseDate(final MessageHeaders headers, final String headerName) {
110 if (headers == null) {
111 return null;
112 }
113 final Header header = headers.getFirstHeader(headerName);
114 if (header == null) {
115 return null;
116 }
117 return parseDate(header.getValue(), null, null);
118 }
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134 public static boolean isAfter(
135 final MessageHeaders message1,
136 final MessageHeaders message2,
137 final String headerName) {
138 if (message1 != null && message2 != null) {
139 final Header dateHeader1 = message1.getFirstHeader(headerName);
140 if (dateHeader1 != null) {
141 final Header dateHeader2 = message2.getFirstHeader(headerName);
142 if (dateHeader2 != null) {
143 final Date date1 = parseDate(dateHeader1.getValue());
144 if (date1 != null) {
145 final Date date2 = parseDate(dateHeader2.getValue());
146 if (date2 != null) {
147 return date1.after(date2);
148 }
149 }
150 }
151 }
152 }
153 return false;
154 }
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170 public static boolean isBefore(
171 final MessageHeaders message1,
172 final MessageHeaders message2,
173 final String headerName) {
174 if (message1 != null && message2 != null) {
175 final Header dateHeader1 = message1.getFirstHeader(headerName);
176 if (dateHeader1 != null) {
177 final Header dateHeader2 = message2.getFirstHeader(headerName);
178 if (dateHeader2 != null) {
179 final Date date1 = parseDate(dateHeader1.getValue());
180 if (date1 != null) {
181 final Date date2 = parseDate(dateHeader2.getValue());
182 if (date2 != null) {
183 return date1.before(date2);
184 }
185 }
186 }
187 }
188 }
189 return false;
190 }
191
192
193
194
195
196
197
198
199
200 public static Date parseDate(final String dateValue, final String[] dateFormats) {
201 return parseDate(dateValue, dateFormats, null);
202 }
203
204
205
206
207
208
209
210
211
212
213
214
215
216 public static Date parseDate(
217 final String dateValue,
218 final String[] dateFormats,
219 final Date startDate) {
220 Args.notNull(dateValue, "Date value");
221 final String[] localDateFormats = dateFormats != null ? dateFormats : DEFAULT_PATTERNS;
222 final Date localStartDate = startDate != null ? startDate : DEFAULT_TWO_DIGIT_YEAR_START;
223 String v = dateValue;
224
225
226 if (v.length() > 1 && v.startsWith("'") && v.endsWith("'")) {
227 v = v.substring (1, v.length() - 1);
228 }
229
230 for (final String dateFormat : localDateFormats) {
231 final SimpleDateFormat dateParser = DateFormatHolder.formatFor(dateFormat);
232 dateParser.set2DigitYearStart(localStartDate);
233 final ParsePosition pos = new ParsePosition(0);
234 final Date result = dateParser.parse(v, pos);
235 if (pos.getIndex() != 0) {
236 return result;
237 }
238 }
239 return null;
240 }
241
242
243
244
245
246
247
248
249
250 public static String formatDate(final Date date) {
251 return formatDate(date, PATTERN_RFC1123);
252 }
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267 public static String formatDate(final Date date, final String pattern) {
268 Args.notNull(date, "Date");
269 Args.notNull(pattern, "Pattern");
270 final SimpleDateFormat formatter = DateFormatHolder.formatFor(pattern);
271 return formatter.format(date);
272 }
273
274
275
276
277
278
279 public static void clearThreadLocal() {
280 DateFormatHolder.clearThreadLocal();
281 }
282
283
284 private DateUtils() {
285 }
286
287
288
289
290
291
292
293 final static class DateFormatHolder {
294
295 private static final ThreadLocal<SoftReference<Map<String, SimpleDateFormat>>> THREADLOCAL_FORMATS = new ThreadLocal<>();
296
297
298
299
300
301
302
303
304
305
306
307
308
309 public static SimpleDateFormat formatFor(final String pattern) {
310 final SoftReference<Map<String, SimpleDateFormat>> ref = THREADLOCAL_FORMATS.get();
311 Map<String, SimpleDateFormat> formats = ref == null ? null : ref.get();
312 if (formats == null) {
313 formats = new HashMap<>();
314 THREADLOCAL_FORMATS.set(new SoftReference<>(formats));
315 }
316
317 SimpleDateFormat format = formats.get(pattern);
318 if (format == null) {
319 format = new SimpleDateFormat(pattern, Locale.US);
320 format.setTimeZone(TimeZone.getTimeZone("GMT"));
321 formats.put(pattern, format);
322 }
323
324 return format;
325 }
326
327 public static void clearThreadLocal() {
328 THREADLOCAL_FORMATS.remove();
329 }
330
331 }
332
333 }