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