Revert "remove redundant code under appc-common-bundle/java"
[appc.git] / appc-core / appc-common-bundle / java / org / onap / appc / util / Time.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP : APPC
4  * ================================================================================
5  * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Copyright (C) 2017 Amdocs
8  * ================================================================================
9  * Modifications Copyright (c) 2019 IBM
10  * ================================================================================
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  * 
15  *      http://www.apache.org/licenses/LICENSE-2.0
16  * 
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  * 
23  * ============LICENSE_END=========================================================
24  */
25
26
27
28 package org.onap.appc.util;
29
30 import java.sql.Timestamp;
31 import java.text.DateFormat;
32 import java.text.ParseException;
33 import java.text.SimpleDateFormat;
34 import java.util.ArrayList;
35 import java.util.Calendar;
36 import java.util.Date;
37 import java.util.GregorianCalendar;
38 import java.util.List;
39 import java.util.Locale;
40 import java.util.SimpleTimeZone;
41 import java.util.TimeZone;
42 import javax.xml.datatype.DatatypeConfigurationException;
43 import javax.xml.datatype.DatatypeFactory;
44 import javax.xml.datatype.XMLGregorianCalendar;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48 /**
49  * This class is a general purpose helper class to augment standard Java time support.
50  *
51  */
52
53 public final class Time {
54
55     /**
56      * Logger to log operations
57      */
58     private static final Logger LOG = LoggerFactory.getLogger(Time.class);
59
60     /**
61      * A formatter to be used to format values
62      */
63     private static SimpleDateFormat dateformatter = null;
64
65     /**
66      * The UTC timezone (for UTC or GMT time)
67      */
68     @SuppressWarnings("nls")
69     private static final TimeZone utcTZ = TimeZone.getTimeZone("UTC");
70
71     /**
72      * The cached reference to the datatype factory
73      */
74     private static DatatypeFactory xmlDatatypeFactory = null;
75
76     /**
77      * Private default constructor prevents instantiation
78      */
79     private Time() {
80         //
81     }
82
83     /**
84      * Increments a date by the indicated months, days, hours, minutes, and seconds, and returns the
85      * updated date.
86      *
87      * @param date The date to be manipulated
88      * @param months The number of months to be added to the date
89      * @param days The number of days to be added to the date
90      * @param hours The number of hours to be added to the date
91      * @param minutes The number of minutes to be added to the date
92      * @param seconds The number of seconds to be added to the date
93      * @return The updated date.
94      */
95     public static Date addTime(final Date date, final int months, final int days, final int hours,
96             final int minutes, final int seconds) {
97         Calendar cal = Calendar.getInstance();
98         cal.setTime(date);
99         cal.add(Calendar.MONTH, months);
100         cal.add(Calendar.DATE, days);
101         cal.add(Calendar.HOUR_OF_DAY, hours);
102         cal.add(Calendar.MINUTE, minutes);
103         cal.add(Calendar.SECOND, seconds);
104         return cal.getTime();
105     }
106
107     /**
108      * Clears the time components of a calendar to zero, leaving the date components unchanged.
109      *
110      * @param cal the calendar to be updated
111      * @return The updated calendar object
112      */
113     public static Calendar dateOnly(final Calendar cal) {
114         cal.set(Calendar.HOUR_OF_DAY, 0);
115         cal.set(Calendar.MINUTE, 0);
116         cal.set(Calendar.SECOND, 0);
117         cal.set(Calendar.MILLISECOND, 0);
118         return cal;
119     }
120
121     /**
122      * This method returns the local time that corresponds to the end of the current day
123      *
124      * @return The time that corresponds to the end of the current day, expressed as local time
125      */
126     public static Date endOfDayLocal() {
127         return endOfDayLocal(new Date());
128     }
129
130     /**
131      * This method returns the last moment of the day for the supplied local time. This is defined
132      * as the millisecond before midnight of the current date represented by the local time.
133      *
134      * @param localTime The local time for which the last moment of the day is desired.
135      * @return The millisecond prior to midnight, local time.
136      */
137     public static Date endOfDayLocal(final Date localTime) {
138         // @sonar:off
139         GregorianCalendar calendar = new GregorianCalendar();
140         calendar.setTime(localTime);
141         calendar.set(Calendar.HOUR, 11);
142         calendar.set(Calendar.AM_PM, Calendar.PM);
143         calendar.set(Calendar.MINUTE, 59);
144         calendar.set(Calendar.SECOND, 59);
145         calendar.set(Calendar.MILLISECOND, 999);
146         // @sonar:on
147
148         return calendar.getTime();
149     }
150
151     /**
152      * The end of the current day and in the current time zone expressed as a UTC time.
153      *
154      * @return The UTC time that corresponds to the end of the current day
155      */
156     public static Date endOfDayUTC() {
157         return endOfDayUTC(new Date());
158     }
159
160     /**
161      * Returns the UTC time that corresponds to the end of the day for the local time specified,
162      * using the current (default) time zone.
163      *
164      * @param localTime The local time for which we are requesting the UTC time that corresponds to
165      *        the end of the day
166      * @return The UTC time that corresponds to the end of the local day specified by the local
167      *         time.
168      */
169     public static Date endOfDayUTC(final Date localTime) {
170         return endOfDayUTC(localTime, TimeZone.getDefault());
171     }
172
173     /**
174      * Returns the time expressed in UTC time of the end of the day specified in local time and
175      * within the local time zone.
176      *
177      * @param localTime The local time for which we will compute the end of the local day, and then
178      *        convert to UTC time.
179      * @param localTimeZone The time zone that the local time is within.
180      * @return The UTC date that corresponds to the end of the day local time and in the local time
181      *         zone.
182      */
183     public static Date endOfDayUTC(final Date localTime, final TimeZone localTimeZone) {
184         Date endOfDay = endOfDayLocal(localTime);
185         return utcDate(endOfDay, localTimeZone);
186     }
187
188     /**
189      * returns current Date in 'UTC' Timezone
190      *
191      * @return The current date, expressed in the UTC timezone.
192      */
193     @SuppressWarnings("nls")
194     public static Date getCurrentUTCDate() {
195
196         // This code incorrectly changes the default timezone for the entire JVM in order to compute
197         // the UTC
198         // date for the current time.
199
200         GregorianCalendar calendar = new GregorianCalendar();
201         calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
202         calendar.setTimeInMillis(utcTime());
203         return calendar.getTime();
204     }
205
206     /**
207      * This method loads and caches the reference to the XML data type factory object.
208      *
209      * @return The XML Data Type Factory object
210      */
211     public static DatatypeFactory getDatatypeFactory() {
212         if (xmlDatatypeFactory == null) {
213             try {
214                 xmlDatatypeFactory = DatatypeFactory.newInstance();
215             } catch (DatatypeConfigurationException e) {
216                 LOG.error("Error while getting DatatypeFactory ::", e);
217             }
218         }
219         return xmlDatatypeFactory;
220     }
221
222     /**
223      * Gives the date-time String based on given Locale and Timezone
224      *
225      * @param date The date to be formatted
226      * @param locale The locale that we want to format the value for
227      * @param timezone The time zone that the date is within
228      * @return The formatted value
229      */
230     public static String getDateByLocaleAndTimeZone(final Date date, final Locale locale,
231             final TimeZone timezone) {
232         String strDate = null;
233         DateFormat df =
234                 DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, locale);
235         df.setTimeZone(timezone);
236         synchronized (df) {
237             strDate = df.format(date);
238         }
239         return strDate;
240     }
241
242     /**
243      * Returns singleton UTC date formatter.
244      *
245      * @return
246      */
247     @SuppressWarnings("nls")
248     private static SimpleDateFormat getDateFormatter() {
249         if (dateformatter == null) {
250             dateformatter = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
251             dateformatter.setTimeZone(new SimpleTimeZone(SimpleTimeZone.UTC_TIME, "UTC"));
252         }
253         return dateformatter;
254     }
255
256     /**
257      * This method returns the local time that corresponds to a given UTC time in the current time
258      * zone.
259      *
260      * @param utcTime The UTC time for which we desire the equivalent local time in the current time
261      *        zone.
262      * @return The local time that is equivalent to the given UTC time for the current time zone
263      */
264     public static long localTime(final long utcTime) {
265         return localTime(utcTime, TimeZone.getDefault());
266     }
267
268     /**
269      * This method can be used to get the local time that corresponds to a specific UTC time.
270      * <p>
271      * This method has a problem since the offset can only be determined by having a local time. So,
272      * we take the UTC time and add the raw offset to it to come up with an approximation of the
273      * local time. This gives us a local time that we can use to determine what the offset should
274      * be, which is what we actually add to the UTC time to get the local time.
275      * </p>
276      *
277      * @param utcTime The UTC time for which we want to obtain the equivalent local time
278      * @param localTZ The time zone that we want the local time to be within
279      * @return The local time for the specified time zone and the given UTC time
280      */
281     public static long localTime(final long utcTime, final TimeZone localTZ) {
282         int offset = localTZ.getOffset(utcTime + localTZ.getRawOffset());
283         long result = utcTime + offset;
284
285         return result;
286     }
287
288     /**
289      * Sets the date components of a calendar to the specified values, leaving the time components
290      * unchanged.
291      *
292      * @param cal The calendar to be updated
293      * @param year The year to be set
294      * @param month The month to be set
295      * @param day The day to be set
296      * @return The updated calendar object
297      */
298     public static Calendar setDate(final Calendar cal, final int year, final int month,
299             final int day) {
300         cal.set(Calendar.YEAR, year);
301         cal.set(Calendar.MONTH, month);
302         cal.set(Calendar.DAY_OF_MONTH, day);
303         return cal;
304     }
305
306     /**
307      * Returns the start of the day expressed in local time for the current local time.
308      *
309      * @return The start of the day
310      */
311     public static Date startOfDayLocal() {
312         return startOfDayLocal(new Date());
313     }
314
315     /**
316      * This method returns the date that corresponds to the start of the day local time. The date
317      * returned represents midnight of the previous day represented in local time. If the UTC time
318      * is desired, use the methods {@link #startOfDayUTC(Date, TimeZone)},
319      * {@link #startOfDayUTC(Date)}, or {@link #startOfDayUTC()}
320      *
321      * @param localTime The local date that we wish to compute the start of day for.
322      * @return The date that corresponds to the start of the local day
323      */
324     public static Date startOfDayLocal(final Date localTime) {
325         GregorianCalendar calendar = new GregorianCalendar();
326         calendar.setTime(localTime);
327         calendar.set(Calendar.HOUR, 0);
328         calendar.set(Calendar.AM_PM, Calendar.AM);
329         calendar.set(Calendar.MINUTE, 0);
330         calendar.set(Calendar.SECOND, 0);
331         calendar.set(Calendar.MILLISECOND, 0);
332
333         return calendar.getTime();
334     }
335
336     /**
337      * This method returns the UTC date that corresponds to the start of the local day based on the
338      * current time and the default time zone (the time zone we are running in).
339      *
340      * @return The start of the local day expressed as a UTC time.
341      */
342     public static Date startOfDayUTC() {
343         return startOfDayUTC(new Date());
344     }
345
346     /**
347      * This method returns the UTC date that corresponds to the start of the local day specified in
348      * the current time zone.
349      *
350      * @param localTime The local time to be used to compute the start of the day
351      * @return The start of the local day expressed as a UTC time.
352      */
353     public static Date startOfDayUTC(final Date localTime) {
354         return startOfDayUTC(localTime, TimeZone.getDefault());
355     }
356
357     /**
358      * This method returns the UTC date that corresponds to the start of the local day specified in
359      * the local timezone.
360      *
361      * @param localTime The local time to be used to compute start of day
362      * @param localTimeZone The time zone that the local time was recorded within
363      * @return The corresponding UTC date
364      */
365     public static Date startOfDayUTC(final Date localTime, final TimeZone localTimeZone) {
366         Date startOfDay = startOfDayLocal(localTime);
367         return utcDate(startOfDay, localTimeZone);
368     }
369
370     /**
371      * This method creates and returns an XML timestamp expressed as the current UTC value for the
372      * system. The caller does not specify the time value or time zone using this method. This
373      * ensures that the timestamp value is always expressed as UTC time.
374      *
375      * @return The XMLGregorianCalendar that can be used to record the timestamp
376      */
377
378     public static XMLGregorianCalendar timestamp() {
379         getDatatypeFactory();
380         XMLGregorianCalendar ts = xmlDatatypeFactory.newXMLGregorianCalendar();
381         GregorianCalendar utc = new GregorianCalendar();
382         utc.setTime(utcDate());
383         ts.setTimezone(0);
384         ts.setYear(utc.get(Calendar.YEAR));
385         // Calendar Months are from 0-11 need to +1
386         ts.setMonth(utc.get(Calendar.MONTH) + 1);
387         ts.setDay(utc.get(Calendar.DAY_OF_MONTH));
388         ts.setHour(utc.get(Calendar.HOUR_OF_DAY));
389         ts.setMinute(utc.get(Calendar.MINUTE));
390         ts.setSecond(utc.get(Calendar.SECOND));
391         ts.setMillisecond(utc.get(Calendar.MILLISECOND));
392         return ts;
393     }
394
395     /**
396      * Converts XMLGregorianCalendar to java.util.Date in Java
397      *
398      * @param calendar the calendar object to be converted
399      * @return The equivalent Date object
400      */
401     public static Date toDate(final XMLGregorianCalendar calendar) {
402         if (calendar == null) {
403             return null;
404         }
405         return calendar.toGregorianCalendar().getTime();
406     }
407
408     /**
409      * Converts java Date to XMLGregorianCalendar.
410      *
411      * @param date The date to convert
412      * @return The XMLGregorianCalendar for the specified date
413      */
414     @SuppressWarnings("nls")
415     public static XMLGregorianCalendar toXMLCalendar(final Date date) {
416         GregorianCalendar cal = (GregorianCalendar) Calendar.getInstance();
417         cal.setTime(date);
418
419         XMLGregorianCalendar xmlCal = null;
420         try {
421             xmlCal = DatatypeFactory.newInstance().newXMLGregorianCalendar(cal);
422         } catch (DatatypeConfigurationException e) {
423             LOG.error("toXMLCalendar", e);
424         }
425         return xmlCal;
426     }
427
428     /**
429      * Truncates the provided date so that only the date, hours, and minutes portions are
430      * significant. This method returns the date with the seconds and milliseconds forced to zero.
431      *
432      * @param date The date to truncate
433      * @return The date with only the year, month, day, hours, and minutes significant.
434      */
435     public static Date truncDate(final Date date) {
436         Calendar cal = Calendar.getInstance();
437         cal.setTime(date);
438         cal.set(Calendar.SECOND, 0);
439         cal.set(Calendar.MILLISECOND, 0);
440         return cal.getTime();
441     }
442
443     /**
444      * The UTC date that corresponds to the current date in the local time zone.
445      *
446      * @return The UTC date for now in the current time zone.
447      */
448     public static Date utcDate() {
449         return new Date();
450     }
451
452     /**
453      * The UTC date for the specified date in the current (default) time zone.
454      *
455      * @param date The local date for which the UTC date is desired.
456      * @return The UTC date that corresponds to the date in the current time zone.
457      */
458     public static Date utcDate(final Date date) {
459         TimeZone tz = TimeZone.getDefault();
460         return utcDate(date, tz);
461     }
462
463     /**
464      * Returns the UTC date for the specified date in the specified time zone.
465      *
466      * @param date The date for which the UTC date is desired in the specified zone
467      * @param tz The time zone that corresponds to the date to be converted to UTC
468      * @return The UTC date that corresponds to the local date in the local time zone.
469      */
470     public static Date utcDate(final Date date, final TimeZone tz) {
471         return new Date(utcTime(date.getTime(), tz));
472     }
473
474     /**
475      * Format incoming date as string in GMT or UTC.
476      *
477      * @param dt The date to be formatted
478      * @return The date formatted for UTC timezone
479      */
480     public static String utcFormat(final Date dt) {
481         String strDate = null;
482         DateFormat df = getDateFormatter();
483         synchronized (df) {
484             strDate = df.format(dt);
485         }
486         return strDate;
487     }
488
489     /**
490      * Parse previously formated Date object back to a Date object.
491      *
492      * @param dateStr The representation of a UTC date as a string
493      * @return The date object containing the parsed representation, or null if the representation
494      *         cannot be parsed
495      */
496     @SuppressWarnings("nls")
497     public static Date utcParse(final String dateStr) {
498         String[] adtl = {"yyyy-MM-dd"};
499         return utcParse(dateStr, adtl);
500     }
501
502     /**
503      * Parse previously formated Date object back to a Date object.
504      *
505      * @param dateStr The representation of a UTC date as a string
506      * @param adtlFormatStrings A list of strings that represent additional date format
507      *        representations to try and parse.
508      * @return The date object containing the parsed representation, or null if the representation
509      *         cannot be parsed
510      */
511     @SuppressWarnings("nls")
512     public static Date utcParse(final String dateStr, String... adtlFormatStrings) {
513         if (dateStr != null) {
514             // Build the list of formatters starting with the default defined in the class
515             List<DateFormat> formats = new ArrayList<>();
516             formats.add(getDateFormatter());
517
518             if (adtlFormatStrings != null) {
519                 for (String s : adtlFormatStrings) {
520                     formats.add(new SimpleDateFormat(s));
521                 }
522             }
523
524             // Return the first matching date formatter's result
525             for (DateFormat df : formats) {
526                 df.setTimeZone(utcTZ);
527                 try {
528                     return df.parse(dateStr);
529                 } catch (ParseException e) {
530                     LOG.debug(String.format("IGNORE - Date string [%s] does not fit pattern [%s]",
531                             dateStr, df.toString()));
532                 }
533             }
534         }
535         return null;
536     }
537
538     /**
539      * This method returns the current time for the UTC timezone
540      *
541      * @return The time in the UTC time zone that corresponds to the current local time.
542      */
543     public static long utcTime() {
544         return new Date().getTime();
545     }
546
547     /**
548      * Get the UTC time that corresponds to the given time in the default time zone (current time
549      * zone for the system).
550      *
551      * @param localTime The time in the current time zone for which the UTC time is desired.
552      * @return The UTC time
553      */
554     public static long utcTime(final long localTime) {
555         TimeZone tz = TimeZone.getDefault();
556         return utcTime(localTime, tz);
557     }
558
559     /**
560      * Get the UTC time that corresponds to the given time in the specified timezone.
561      * <p>
562      * Note that the java <code>getOffset()</code> method works a little counter-intuitive. It
563      * returns the offset that would be added to the current UTC time to get the LOCAL time
564      * represented by the local time zone. That means to get the UTC time, we need to SUBTRACT this
565      * offset from the local time.
566      * </p>
567      *
568      * @param localTime The time in the specified time zone for which the UTC time is desired.
569      * @param localTZ The time zone which the local time is in.
570      * @return The UTC time for the specified local time in the specified local time zone.
571      */
572     public static long utcTime(final long localTime, final TimeZone localTZ) {
573         int offset = localTZ.getOffset(localTime);
574         return localTime - offset;
575
576     }
577
578     /**
579      * Creates a timestamp value from a time
580      *
581      * @param utcTime The UTC time to convert to a timestamp
582      * @return The timestamp
583      */
584     public static Timestamp utcTimestamp(final long utcTime) {
585         TimeZone tz = TimeZone.getDefault();
586         return new Timestamp(utcTime(utcTime, tz));
587     }
588
589     public static String dateToStringConverterMillis(Date date) {
590         SimpleDateFormat customDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
591         if (date != null) {
592             return customDate.format(date);
593         }
594         return null;
595     }
596
597     public static Date stringToDateConverterMillis(String dateString) throws ParseException {
598         SimpleDateFormat customDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
599         return customDate.parse(dateString);
600     }
601 }