/*******************************************************************************
* Copyright 2017 Capital One Services, LLC and Bitwise, Inc.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*******************************************************************************/
package hydrograph.engine.transformation.standardfunctions;
import hydrograph.engine.transformation.standardfunctions.helper.StandardFunctionHelper;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;
/**
* The Class DateFunctions.
*
* @author Bitwise
*
*/
public class DateFunctions {
/**
* Returns number of days since 1st January 1900
*
* @return number of days since 1st January 1900
*/
public static <T> Integer today() {
int date = 0;
try {
SimpleDateFormat formatter = new SimpleDateFormat("dd MM yyyy");
Date d1 = formatter.parse("1 01 1900");
Date d2 = new Date();
int DateFraction = (1000 * 60 * 60 * 24);
date = (int) ((d2.getTime() - d1.getTime()) / DateFraction);
} catch (Exception e) {
// since we are parsing static date value, parse function will never
// throw exception
}
return date;
}
/**
* Returns current date and time in yyyyMMddHmmssS format
*
* @return current date and time in yyyyMMddHmmssS format
*/
@SuppressWarnings("unchecked")
public static <T> T now() {
return (T) now("yyyyMMddHmmssS");
}
/**
* Returns current date and time in the required format
*
* @param dateFormat the format for the date
* @return current date and time in the required format
*/
public static String now(String dateFormat) {
DateFormat sdf = new SimpleDateFormat(dateFormat);
Date date = new Date();
return sdf.format(date);
}
/**
* Formats and converts a date value into string representation in the
* desired new date format
*
* @param inputValue
* the date value in old format
* @param oldFormat
* the date format of the date passed in {@code inputValue}
* @param newFormat
* the desired date format
* @return string representation of date in new date format
* <p>
* the method returns null if any parameter is null
* @deprecated This method is deprecated, Use
* {@link DateFunctions#dateFormatter(String inputValue, String oldFormat, String newFormat)}
* instead
* @throws ParseException
* if the date value passed in {@code inputValue} does not match
* the {@code oldFormat}
*/
@Deprecated
public static <T> String dateFormatter(T inputValue, String oldFormat, String newFormat) throws ParseException {
if (inputValue == null || oldFormat == null || newFormat == null)
return null;
String oldDateString = String.valueOf(StandardFunctionHelper.convertComparableObjectToString(inputValue));
String newDateString = null;
SimpleDateFormat sdf = new SimpleDateFormat(oldFormat);
sdf.setLenient(false);
Date date = null;
date = sdf.parse(oldDateString);
sdf.applyPattern(newFormat);
newDateString = sdf.format(date);
return newDateString;
}
/**
* Formats and converts a date value into string representation in the
* desired new date format
*
* @param inputValue
* the date value in old format
* @param oldFormat
* the date format of the date passed in {@code inputValue}
* @param newFormat
* the desired date format
* @return string representation of date in new date format
* <p>
* the method returns null if any parameter is null
* @throws ParseException
* if the date value passed in {@code inputValue} does not match
* the {@code oldFormat}
*/
public static String dateFormatter(String inputValue, String oldFormat, String newFormat) throws ParseException {
if (inputValue == null || oldFormat == null || newFormat == null)
return null;
String newDateString = null;
SimpleDateFormat sdf = new SimpleDateFormat(oldFormat);
sdf.setLenient(false);
Date date = null;
date = sdf.parse(inputValue);
sdf.applyPattern(newFormat);
newDateString = sdf.format(date);
return newDateString;
}
/**
* Formats and converts a date value into string representation in the
* desired new date format
*
* @param inputValue
* the date value in old format
* @param oldFormat
* the date format of the date passed in {@code inputValue}
* @param newFormat
* the desired date format
* @return string representation of date in new date format
* <p>
* the method returns null if any parameter is null
* @throws ParseException
* if the date value passed in {@code inputValue} does not match
* the {@code oldFormat}
*/
public static String dateFormatter(Date inputValue, String oldFormat, String newFormat) throws ParseException {
if (inputValue == null || oldFormat == null || newFormat == null)
return null;
String newDateString = null;
SimpleDateFormat sdf = new SimpleDateFormat(newFormat);
sdf.setLenient(false);
newDateString = sdf.format(inputValue);
return newDateString;
}
/**
* Returns a date object from a string date value
*
* @param inputDateInStringFormat
* the date value in string
* @param dateFormat
* the date format of the date value passed in
* {@code inputDateInStringFormat}
* @return a date object of the corresponding date value
* <p>
* the method returns null if any parameter is null
* @deprecated This method is deprecated, Use
* {@link DateFunctions#getDateFromString(String inputDateInStringFormat, String dateFormat)}
* instead
* @throws ParseException
* if the date value passed in {@code inputDateInStringFormat}
* does not match the {@code dateFormat}
*/
@Deprecated
public static <T> Date getDateFromString(T inputDateInStringFormat, String dateFormat) throws ParseException {
if (inputDateInStringFormat == null || dateFormat == null)
return null;
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
sdf.setLenient(false);
Date date = sdf.parse((String) inputDateInStringFormat);
return date;
}
/**
* Returns a date object from a string date value
*
* @param inputDateInStringFormat
* the date value in string
* @param dateFormat
* the date format of the date value passed in
* {@code inputDateInStringFormat}
* @return a date object of the corresponding date value
* <p>
* the method returns null if any parameter is null
* @throws ParseException
* if the date value passed in {@code inputDateInStringFormat}
* does not match the {@code dateFormat}
*/
public static Date getDateFromString(String inputDateInStringFormat, String dateFormat) throws ParseException {
if (inputDateInStringFormat == null || dateFormat == null)
return null;
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
sdf.setLenient(false);
Date date = sdf.parse(inputDateInStringFormat);
return date;
}
/**
* Returns a string value of the date
*
* @param inputDate
* the date to fetch the string value
* @param dateFormat
* the date format of the date value passed in {@code inputDate}
* @return a string value of the date
* <p>
* the method returns null if any parameter is null
*
* @throws ParseException
* if the date value passed in {@code inputDate} does not match
* the {@code dateFormat}
*/
public static <T> String getStringDateFromDateObject(T inputDate, String dateFormat) throws ParseException {
if (inputDate == null || dateFormat == null)
return null;
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
sdf.setLenient(false);
String stringDate = sdf.format(inputDate);
return stringDate;
}
/**
* Returns a string value of the date
*
* @param inputDate
* the date to fetch the string value
* @param dateFormat
* the date format of the date value passed in {@code inputDate}
* @return a string value of the date
* <p>
* the method returns null if any parameter is null
* @throws ParseException
* if the date value passed in {@code inputDate} does not match
* the {@code dateFormat}
*/
public static String getStringDateFromDateObject(Date inputDate, String dateFormat) throws ParseException {
if (inputDate == null || dateFormat == null)
return null;
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
sdf.setLenient(false);
String stringDate = sdf.format(inputDate);
return stringDate;
}
/**
* Validates the string date value to the format specified
*
* @param inputDate
* the date value in string to be validated
* @param dateFormat
* the date format to validate the string value against
* @return <b>{@code true}</b> if the date value passed in {@code inputDate}
* matches the date format passed in {@code dateFormat}
* <p>
* <b>{@code false}</b> if the date value passed in
* {@code inputDate} does not match the date format passed in
* {@code dateFormat}
*/
public static boolean validateStringDate(String inputDate, String dateFormat) {
if (dateFormat != null && !dateFormat.equals("") && inputDate != null && !inputDate.equals("")) {
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
sdf.setLenient(false);
try {
sdf.parse(inputDate);
return true;
} catch (ParseException e) {
return false;
}
}
return false;
}
/**
* Returns an integer value which holds the day value retrieved from {@code date} parameter
*
* @param date the date from which the day value is to be retrieved
* @return the day value from {@code date} parameter
*/
public static Integer getDay(Date date) {
String day = new SimpleDateFormat("dd").format(date);
return Integer.parseInt(day);
}
/**
* Returns an integer value which holds the month value retrieved from {@code date} parameter
*
* @param date the date from which the month value is to be retrieved
* @return the month value from {@code date} parameter
*/
public static Integer getMonth(Date date) {
String month = new SimpleDateFormat("MM").format(date);
return Integer.parseInt(month);
}
/**
* Returns an integer value which holds the year value retrieved from {@code date} parameter
*
* @param date the date from which the year value is to be retrieved
* @return the year value from {@code date} parameter
*/
public static Integer getYear(Date date) {
String year = new SimpleDateFormat("yyyy").format(date);
return Integer.parseInt(year);
}
/**
* Returns Date object which holds last date value of the month retrieved from {@code date} parameter
*
* @param date the date from which the last date of the month is to be retrieved
* @return the last date value of the month retrieved from {@code date} parameter
*/
public static Date getLastDateOfMonth(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
return calendar.getTime();
}
/**
* Returns an integer value which holds the last day value of the month retrieved from {@code date}
*
* @param date the date from which the last day value of the month is to be retrieved
* @return the last day value of the month retrieved from {@code date} parameter
*/
public static Integer getLastDayOfMonth(Date date) {
Calendar c = Calendar.getInstance();
c.setTime(date);
c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
String lastDayOfMonth = new SimpleDateFormat("dd").format(c.getTime());
return Integer.parseInt(lastDayOfMonth);
}
/**
* Returns date which hold last date retrieved for {@code month} for the current year
*
* @param month the month from which the last date value is to be retrieved
* @return the last date value from {@code month} parameter for the current year
*/
public static Date getLastDateOfMonth(int month) {
Calendar calendar = Calendar.getInstance();
calendar.set(calendar.get(Calendar.YEAR), month - 1, 1);
calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DATE));
return calendar.getTime();
}
/**
* Returns date which holds last date for that {@code month} and {@code year}
*
* @param month the month from which the last date value is to be retrieved
* @param year the year from which the last date value is to be retrieved
* @return last date value for {@code month} of {@code year}
*/
public static Date getLastDateOfMonthAndYear(int month, int year) {
Calendar calendar = Calendar.getInstance();
calendar.set(year, month - 1, 1);
calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DATE));
return calendar.getTime();
}
/**
* Returns an integer which holds day of week retrieved from {@code date}
*
* @param date the date for which the day of week is to be retrieved
* @return day of week for {@code date}
*/
public static Integer getDayOfWeek(Date date) {
Calendar c = Calendar.getInstance();
c.setTime(date);
int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);
return dayOfWeek;
}
/**
* Returns an integer which hold day of year retrieved from {@code date}
*
* @param date the date from which the day of year is to be retrieved
* @return day of year for {@code date}
*/
public static Integer getDayOfYear(Date date) {
Calendar c = Calendar.getInstance();
c.setTime(date);
int dayOfYear = c.get(Calendar.DAY_OF_YEAR);
return dayOfYear;
}
/**
* Returns an integer which holds difference between {@code fromDate} to {@code toDate} in days
*
* @param fromDate the date from which the difference is to be calculated
* @param toDate the date to which the difference is to be calculated
* @return the difference of days between {@code fromDate} to {@code toDate}
*/
public static Integer getDayDifference(Date fromDate, Date toDate) {
LocalDateTime firstDate = LocalDateTime.ofInstant(fromDate.toInstant(), ZoneId.systemDefault());
LocalDateTime secondDate = LocalDateTime.ofInstant(toDate.toInstant(), ZoneId.systemDefault());
long daysLong = Math.abs(ChronoUnit.DAYS.between(firstDate, secondDate));
return (int) daysLong;
}
/**
* Returns an integer which holds the difference of months between {@code fromDate} and {@code toDate}
*
* @param fromDate the date from which the difference is to be calculated
* @param toDate the date to which the difference is to be calculated
* @return the difference of months between {@code fromDate} and {@code toDate}
*/
public static Integer getMonthDifference(Date fromDate, Date toDate) {
LocalDateTime firstDate = LocalDateTime.ofInstant(fromDate.toInstant(), ZoneId.systemDefault());
LocalDateTime secondDate = LocalDateTime.ofInstant(toDate.toInstant(), ZoneId.systemDefault());
long months = Math.abs(ChronoUnit.MONTHS.between(firstDate, secondDate));
return (int) months;
}
/**
* Returns an integer which hold difference of years between two dates
*
* @param fromDate the date from which the difference is to be calculated
* @param toDate the date to which the difference is to be calculated
* @return difference of years between {@code fromDate} and {@code toDate}
*/
public static Integer getYearDifference(Date fromDate, Date toDate) {
LocalDateTime firstDate = LocalDateTime.ofInstant(fromDate.toInstant(), ZoneId.systemDefault());
LocalDateTime secondDate = LocalDateTime.ofInstant(toDate.toInstant(), ZoneId.systemDefault());
long years = Math.abs(ChronoUnit.YEARS.between(firstDate, secondDate));
return (int) (long) years;
}
/**
* Returns date with {@code days} added to {@code date}
*
* @param date the date to which days are to be added
* @param days days to be added to given {@code date}
* @return date after adding {@code days} to {@code date}
* if {@code date} is null then return null
*/
public static Date addDaysToDate(Date date, int days) {
if(date == null)
return null;
LocalDateTime ldt = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
Date newDate = Date.from(ldt.plusDays((long) days).atZone(ZoneId.systemDefault()).toInstant());
return newDate;
}
/**
* Returns date with {@code hours} added to {@code date}
*
* @param date the date to which hours are to be added
* @param hours hours to be added to given {@code date}
* @return date after adding {@code hours} to {@code date}
* if {@code date} is null then return null
*/
public static Date addHoursToDate(Date date, int hours) {
if(date == null)
return null;
Calendar c = Calendar.getInstance();
c.setTime(date);
c.add(Calendar.HOUR_OF_DAY, hours);
return c.getTime();
}
/**
* Returns date with {@code mins} added to {@code date}
*
* @param date the date to which minutes are to be added
* @param mins minutes to be added to given {@code date}
* @return date after adding {@code mins} to {@code date}
* if {@code date} is null then return null
*/
public static Date addMinutesToDate(Date date, int mins) {
if(date == null)
return null;
Calendar c = Calendar.getInstance();
c.setTime(date);
c.add(Calendar.MINUTE, mins);
return c.getTime();
}
/**
* Returns date with {@code secs} added to {@code date}
*
* @param date the date to which seconds are to be added
* @param secs seconds to be added to given {@code date}
* @return date after adding {@code secs} to {@code date}
* if {@code date} is null then return null
*/
public static Date addSecondsToDate(Date date, int secs) {
if(date == null)
return null;
Calendar c = Calendar.getInstance();
c.setTime(date);
c.add(Calendar.SECOND, secs);
return c.getTime();
}
/**
* Returns date with {@code milliSecs} added to {@code date}
*
* @param date the date to which milli seconds are to be added
* @param milliSecs milli seconds to be added to given {@code date}
* @return date after adding {@code milliSecs} seconds to {@code date}
* if {@code date} is null then return null
*/
public static Date addMilliSecondsToDate(Date date, long milliSecs) {
if(date == null)
return null;
Calendar c = Calendar.getInstance();
c.setTime(date);
c.setTimeInMillis(c.getTimeInMillis() + milliSecs);
return c.getTime();
}
/**
* Returns date with {@code days} and {@code hours} added to {@code date}
*
* @param date the date to which days are to be added
* @param days days to be added to given {@code date}
* @param hours hours to be added to given {@code date}
* @return date after adding {@code days} and {@code hours} to {@code date}
* if {@code date} is null then return null
*/
public static Date addToDate(Date date, int days, int hours) {
if(date == null)
return null;
date = addHoursToDate(date, hours);
date = addDaysToDate(date,days);
return date;
}
/**
* Returns date with {@code days}, {@code hours} and {@code mins} added to {@code date}
*
* @param date the date to which days are to be added
* @param days days to be added to given {@code date}
* @param hours hours to be added to given {@code date}
* @param mins minutes to be added to given {@code date}
* @return date after adding {@code days}, {@code hours} and {@code mins} to {@code date}
* if {@code date} is null then return null
*/
public static Date addToDate(Date date, int days, int hours, int mins) {
if(date == null)
return null;
date = addMinutesToDate(date, mins);
date = addToDate(date,days,hours);
return date;
}
/**
* Returns date with {@code days}, {@code hours}, {@code mins} and {@code secs} added to {@code date}
*
* @param date the date to which days are to be added
* @param days days to be added to given {@code date}
* @param hours hours to be added to given {@code date}
* @param mins minutes to be added to given {@code date}
* @param secs seconds to be added to given {@code date}
* @return date after adding {@code days}, {@code hours}, {@code mins} and {@code secs} to {@code date}
* if {@code date} is null then return null
*/
public static Date addToDate(Date date, int days, int hours, int mins, int secs) {
if(date == null)
return null;
date = addSecondsToDate(date, secs);
date = addToDate(date,days,hours,mins);
return date;
}
/**
* Returns date with {@code days}, {@code hours}, {@code mins}, {@code secs} and {@code milliSecs} added to {@code date}
*
* @param date the date to which days are to be added
* @param days days to be added to given {@code date}
* @param hours hours to be added to given {@code date}
* @param mins minutes to be added to given {@code date}
* @param secs seconds to be added to given {@code date}
* @param milliSecs milli seconds to be added to given {@code date}
* @return date after adding {@code days}, {@code hours}, {@code mins}, {@code secs} and {@code milliSecs} to {@code date}
* if {@code date} is null then return null
*/
public static Date addToDate(Date date, int days, int hours, int mins, int secs, int milliSecs) {
if(date == null)
return null;
date = addMilliSecondsToDate(date, milliSecs);
date = addToDate(date,days,hours,mins,secs);
return date;
}
/**
* Returns date with {@code weeks} added to {@code date}
*
* @param date the date to which weeks are to be added
* @param weeks weeks to be added to given {@code date}
* @return date after adding {@code weeks} to {@code date}
*/
public static Date addWeeksToDate(Date date, int weeks) {
LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
Date newDate = Date.from(localDateTime.plusWeeks((long) weeks).atZone(ZoneId.systemDefault()).toInstant());
return newDate;
}
/**
* Returns date with {@code months} added to {@code date}
*
* @param date the date to which months are to be added
* @param months months to be added to given {@code date}
* @return date after adding {@code months} to {@code date}
*/
public static Date addMonthsToDate(Date date, int months) {
LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
Date newDate = Date.from(localDateTime.plusMonths((long) months).atZone(ZoneId.systemDefault()).toInstant());
return newDate;
}
/**
* Returns date with {@code years} added to {@code date}
*
* @param date the date to which months are to be added
* @param years years to be added to given {@code date}
* @return date after adding years to it
*/
public static Date addYearsToDate(Date date, int years) {
LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
Date newDate = Date.from(localDateTime.plusYears((long) years).atZone(ZoneId.systemDefault()).toInstant());
return newDate;
}
/**
* Returns the number of days from {@code date} to today's date
*
* @param fromDate the date from which the days are to be counted
* @return number of days between {@code date} and today's date
*/
public static Integer getDaysCountFromDate(Date fromDate) {
return getDayDifference(fromDate, Calendar.getInstance().getTime());
}
/**
* Returns number of days from 1900/01/01 to today's date
*
* @return number of days from 1900/01/01 to today's date
*/
public static Integer getDaysCountTillDate() {
Date fromDate = null;
LocalDate localDate = LocalDate.parse("1900-01-01");
fromDate = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
return getDayDifference(fromDate, Calendar.getInstance().getTime());
}
/**
* Returns an integer which holds number of days from unix epoch i.e. 1970/01/01 to today's date
*
* @return number of days from 1970/01/01 to today's date
*/
public static Integer getDaysCountFromEpoch() {
Date fromDate = null;
LocalDate localDate = LocalDate.parse("1970-01-01");
fromDate = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
return getDayDifference(fromDate, Calendar.getInstance().getTime());
}
/**
* Returns the earlier date between {@code date1} and {@code date2}
*
* @param date1 input date value
* @param date2 input date value
* @return returns a value indicating the earlier of {@code date1} and {@code date2}
* if either {@code date1} or {@code date2} are null returns null
*/
public static Date dateCompare(Date date1, Date date2) {
if((date1==null)||(date2==null))
return null;
LocalDateTime localDateTime1 = LocalDateTime.ofInstant(date1.toInstant(), ZoneId.systemDefault());
LocalDateTime localDateTime2 = LocalDateTime.ofInstant(date2.toInstant(), ZoneId.systemDefault());
return (localDateTime1.isBefore(localDateTime2)) ? date1 : date2;
}
}