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