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