1 package org.duniter.elasticsearch.utils;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 import org.apache.commons.lang3.time.DateUtils;
25 import org.duniter.core.exception.TechnicalException;
26 import org.duniter.core.util.Preconditions;
27 import org.duniter.core.util.StringUtils;
28 import org.nuiton.util.DateUtil;
29
30 import java.sql.Timestamp;
31 import java.text.ParseException;
32 import java.text.SimpleDateFormat;
33 import java.util.Calendar;
34 import java.util.Date;
35 import java.util.TimeZone;
36 import java.util.regex.Pattern;
37
38 public class Dates extends org.apache.commons.lang3.time.DateUtils{
39
40
41
42 public static String ISO_TIMESTAMP_REGEXP = "\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d:[0-5]\\d|Z)";
43 public static Pattern ISO_TIMESTAMP_PATTERN = Pattern.compile("^" + ISO_TIMESTAMP_REGEXP + "$");
44
45 public static String ISO_TIMESTAMP_SPEC = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
46
47
48
49
50
51
52
53
54 public static Date removeMonth(Date date, int amount) {
55 Preconditions.checkNotNull(date);
56 Preconditions.checkArgument(amount > 0);
57
58
59 Calendar calendar = Calendar.getInstance();
60 calendar.setTimeInMillis(date.getTime());
61 calendar.set(Calendar.HOUR_OF_DAY, 0);
62 calendar.set(Calendar.DAY_OF_MONTH, 1);
63 calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH)-amount);
64 return calendar.getTime();
65 }
66
67
68
69
70
71
72
73
74 public static double hoursBetween(Date startDate, Date endDate){
75 double millis = endDate.getTime() - startDate.getTime();
76 return millis / (1000 * 60 * 60);
77 }
78
79
80
81
82
83
84
85
86 public static Date addHours(Date date, Double amount){
87 long millis = (long) (date.getTime() + amount * (1000 * 60 * 60));
88 return new Date(millis);
89 }
90
91
92
93
94
95
96
97
98 public static Date lastSecondOfTheDay(Date date) {
99 if (date == null) {
100 return null;
101 }
102 Calendar calendar = Calendar.getInstance();
103 calendar.setTime(date);
104 calendar.set(Calendar.HOUR_OF_DAY, 23);
105 calendar.set(Calendar.MINUTE, 59);
106 calendar.set(Calendar.SECOND, 59);
107 calendar.set(Calendar.MILLISECOND, 0);
108 return calendar.getTime();
109 }
110
111
112
113
114
115
116
117
118 public static Date resetTime(Date date, TimeZone timezone) {
119 if (date == null) {
120 return null;
121 }
122 Calendar calendar = timezone != null ? Calendar.getInstance(timezone) : Calendar.getInstance();
123 calendar.setTime(date);
124 resetTime(calendar);
125 return calendar.getTime();
126 }
127
128
129
130
131
132
133
134 public static Date resetTime(Date date) {
135 return resetTime(date, null);
136 }
137
138
139
140
141
142
143
144 public static Calendar resetTime(Calendar calendar) {
145 if (calendar == null) return null;
146 calendar.set(Calendar.HOUR_OF_DAY, 0);
147 calendar.set(Calendar.MINUTE, 0);
148 calendar.set(Calendar.SECOND, 0);
149 calendar.set(Calendar.MILLISECOND, 0);
150
151 return calendar;
152 }
153
154
155
156
157
158
159
160 public static Timestamp resetMillisecond(Timestamp date) {
161 if (date == null) return null;
162 Calendar calendar = Calendar.getInstance();
163 calendar.setTime(date);
164 calendar.set(Calendar.MILLISECOND, 0);
165
166 return new Timestamp(calendar.getTimeInMillis());
167 }
168
169
170
171
172
173
174
175 public static Timestamp resetMillisecond(Date date) {
176 if (date == null) return null;
177 Calendar calendar = Calendar.getInstance();
178 calendar.setTimeInMillis(date.getTime());
179 calendar.set(Calendar.MILLISECOND, 0);
180
181 return new Timestamp(calendar.getTime().getTime());
182 }
183
184
185
186
187
188
189
190 public static Calendar resetMillisecond(Calendar calendar) {
191 calendar.set(Calendar.MILLISECOND, 0);
192
193 return calendar;
194 }
195
196
197
198
199
200
201
202
203 public static int getDifferenceInDays(Date startDate, Date endDate) {
204 return DateUtil.getDifferenceInDays(startDate, endDate);
205 }
206
207
208
209
210
211
212
213
214 public static String formatDate(Date date, String pattern) {
215 return formatDate(date, pattern, null);
216 }
217
218
219
220
221
222
223
224
225 public static String formatDate(Date date, String pattern, TimeZone tz) {
226 if (date == null) return null;
227 SimpleDateFormat sdf = new SimpleDateFormat(pattern);
228 if (tz != null) sdf.setTimeZone(tz);
229 return sdf.format(date);
230 }
231
232
233
234
235
236
237
238
239 public static Date safeParseDate(String date, String pattern) {
240 Date result = null;
241 if (StringUtils.isNotBlank(date)) {
242 try {
243 SimpleDateFormat sdf = new SimpleDateFormat(pattern);
244 result = sdf.parse(date);
245 } catch (ParseException ignored) {
246 }
247 }
248 return result;
249 }
250
251
252
253
254
255
256
257
258 public static Date safeParseDate(String date, String... patterns) {
259 Date result = null;
260 if (StringUtils.isNotBlank(date)) {
261 for (String pattern: patterns) {
262 try {
263 SimpleDateFormat sdf = new SimpleDateFormat(pattern);
264 result = sdf.parse(date);
265 } catch (ParseException ignored) {
266
267 }
268 }
269 }
270 return result;
271 }
272
273
274
275
276
277
278
279
280
281
282 public static Timestamp addSeconds(Timestamp date, int amount) {
283 if(date == null) {
284 throw new IllegalArgumentException("The date must not be null");
285 } else {
286 Calendar c = Calendar.getInstance();
287 c.setTime(date);
288 c.add(Calendar.SECOND, amount);
289 return new Timestamp(c.getTimeInMillis());
290 }
291 }
292
293
294
295
296
297
298 protected Date newCreateDate() {
299 return dateWithNoTime(new Date());
300 }
301
302
303
304
305
306
307 protected Timestamp newUpdateTimestamp() {
308 return new Timestamp((new Date()).getTime());
309 }
310
311
312
313
314
315
316
317 protected Date dateWithNoTime(Date date) {
318 Calendar calendar = Calendar.getInstance();
319 calendar.setTime(date);
320 calendar.set(Calendar.HOUR_OF_DAY, 0);
321 calendar.set(Calendar.MINUTE, 0);
322 calendar.set(Calendar.SECOND, 0);
323 calendar.set(Calendar.MILLISECOND, 0);
324 return calendar.getTime();
325 }
326
327
328
329
330
331
332
333 protected Date dateWithNoMillisecond(Date date) {
334 Calendar calendar = Calendar.getInstance();
335 calendar.setTime(date);
336 calendar.set(Calendar.MILLISECOND, 0);
337 return calendar.getTime();
338 }
339
340
341
342
343
344
345
346 protected Date dateWithNoSecondAndMillisecond(Date date) {
347 Calendar calendar = Calendar.getInstance();
348 calendar.setTime(date);
349 calendar.set(Calendar.SECOND, 0);
350 calendar.set(Calendar.MILLISECOND, 0);
351 return calendar.getTime();
352 }
353
354
355
356
357
358
359
360 protected Date dateWithNoSecondAndOneMillisecond(Date date) {
361 Calendar calendar = Calendar.getInstance();
362 calendar.setTime(date);
363 calendar.add(Calendar.SECOND, 0);
364 calendar.add(Calendar.MILLISECOND, 1);
365 return calendar.getTime();
366 }
367
368
369
370
371
372
373
374 protected Date dateWithOneMillisecond(Date date) {
375 Calendar calendar = Calendar.getInstance();
376 calendar.setTime(date);
377 calendar.add(Calendar.MILLISECOND, 1);
378 return calendar.getTime();
379 }
380
381
382
383
384
385
386
387 protected Date dateOfYearWithOneMillisecond(int year) {
388 Calendar calendar = Calendar.getInstance();
389 calendar.setTimeInMillis(0);
390 calendar.set(Calendar.YEAR, year);
391 calendar.set(Calendar.MILLISECOND, 1);
392 return calendar.getTime();
393 }
394
395
396
397
398
399
400
401 protected long dateOfYearWithOneMillisecondInMillisecond(int year) {
402 Calendar calendar = Calendar.getInstance();
403 calendar.setTimeInMillis(0);
404 calendar.set(Calendar.YEAR, year);
405 calendar.set(Calendar.MILLISECOND, 1);
406 return calendar.getTimeInMillis();
407 }
408
409
410
411
412
413
414
415 protected Date convertDatabase2UI(Timestamp databaseValue) {
416 Date result;
417 if (databaseValue == null) {
418 result = null;
419 } else {
420 Calendar calendar = Calendar.getInstance();
421 calendar.setTimeInMillis(databaseValue.getTime());
422 if (calendar.get(Calendar.MILLISECOND) != 0) {
423 result = null;
424 } else {
425 result = calendar.getTime();
426 }
427 }
428 return result;
429 }
430
431
432
433
434
435
436
437
438
439
440 protected Date convertUI2DatabaseMandatoryDate(Date uiValue,
441 Date defaultNotEmptyDate,
442 boolean addOneSecondToDefaultDate) {
443 Date result;
444
445
446 if (uiValue == null) {
447
448 Preconditions.checkArgument(
449 defaultNotEmptyDate != null,
450 "'defaultNotEmptyDate' could not be null.");
451 Calendar calendar = Calendar.getInstance();
452 calendar.setTime(defaultNotEmptyDate);
453 if (addOneSecondToDefaultDate) {
454 calendar.add(Calendar.SECOND, 1);
455 }
456 calendar.set(Calendar.MILLISECOND, 1);
457 result = calendar.getTime();
458 } else {
459
460 result = dateWithNoMillisecond(uiValue);
461 }
462
463 return result;
464 }
465
466 public static Date getFirstDayOfYear(int year) {
467 Calendar calendar = Calendar.getInstance();
468 calendar.set(Calendar.YEAR, year);
469 calendar.set(Calendar.DAY_OF_YEAR, 1);
470 resetTime(calendar);
471 return calendar.getTime();
472 }
473 public static Date getLastSecondOfYear(int year) {
474 Calendar calendar = Calendar.getInstance();
475 calendar.set(Calendar.YEAR, year+1);
476 calendar.set(Calendar.DAY_OF_YEAR, 1);
477 resetTime(calendar);
478 calendar.add(Calendar.SECOND, -1);
479 return calendar.getTime();
480 }
481
482 public static String elapsedTime(long timeInMs) {
483 long elapsedTime = System.currentTimeMillis() - timeInMs;
484 StringBuilder sb = new StringBuilder();
485 sb.append("in ");
486 if (elapsedTime < 1000) {
487 return sb.append(elapsedTime).append("ms").toString();
488 }
489 double seconds = (double) elapsedTime / 1_000;
490 if (seconds < 60) {
491 return sb.append(seconds).append("s").toString();
492 }
493 int minutesFloor = (int) Math.floor(seconds / 60);
494 int secondsFloor = (int) Math.floor(seconds - minutesFloor * 60);
495 int millis = (int) Math.floor((seconds - secondsFloor) * 1_000);
496
497 return sb.append(minutesFloor).append("min ")
498 .append(secondsFloor).append("s ")
499 .append(millis).append("ms")
500 .toString();
501 }
502
503 public static String checkISODateTimeString(String isoDate) throws TechnicalException {
504 if (isoDate == null) return null;
505 if (!ISO_TIMESTAMP_PATTERN.matcher(isoDate).matches()) {
506 throw new TechnicalException(String.format("Invalid date time '%s'. Expected ISO format 'YYYY-MM-DDThh:mm:ss.sssZ'.", isoDate));
507 }
508 return isoDate;
509 }
510
511 public static String toISODateTimeString(Date date) {
512 return formatDate(date, ISO_TIMESTAMP_SPEC, null);
513 }
514
515 public static String toISODateTimeString(Date date, TimeZone tz) {
516 return formatDate(date, ISO_TIMESTAMP_SPEC, tz);
517 }
518
519 public static Date fromISODateTimeString(String dateStr) {
520 try {
521 return parseDate(dateStr, ISO_TIMESTAMP_SPEC);
522 } catch(ParseException e) {
523 throw new TechnicalException(e);
524 }
525 }
526
527 public static long toUnixTimestamp(Date date) {
528 return date.getTime() / 1000;
529 }
530
531
532
533
534
535
536
537 public static boolean equals(Date d1, Date d2) {
538 return (d1 == null && d2 == null)
539 || (d1 != null && d2 != null && d1.getTime() == d2.getTime());
540 }
541 }