DateUtils.java

package com.tradecloud.domain.base.utils;

import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import org.joda.time.Period;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;

public class DateUtils {

    // Extremes
    public static final Date FIRST_DATE = new Date(Long.MIN_VALUE);
    public static final Date LAST_DATE = new Date(Long.MAX_VALUE);
    public static final SimpleDateFormat ZA_YMDHMS_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
    // Format used by treasury
    public static final SimpleDateFormat T_YMD_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
    public static final SimpleDateFormat HMS_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public static final SimpleDateFormat T_DMY_FORMAT = new SimpleDateFormat("dd-MM-yyyy");
    public static final SimpleDateFormat T_MY_FORMAT = new SimpleDateFormat("MMM yyyy");
    private static final SimpleDateFormat FULL_DAY_OF_WEEK_FORMAT = new SimpleDateFormat("EEEE");
    private static final SimpleDateFormat ABBR_DAY_OF_WEEK_FORMAT = new SimpleDateFormat("E");
    private static final DateFormat DEF_SHORT_DATE_FORMAT = DateFormat.getDateInstance(DateFormat.SHORT);
    private static final SimpleDateFormat ZA_LONG_DATE_FORMAT = new SimpleDateFormat("d MMMM yyyy");
    private static final SimpleDateFormat ZA_YMD_FORMAT = new SimpleDateFormat("yyyy/MM/dd");
    private static final SimpleDateFormat ZA_DMY_FORMAT = new SimpleDateFormat("dd/MM/yyyy");
    private static final SimpleDateFormat ZA_DMYHMS_FORMAT = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
    private static final SimpleDateFormat ZA_DMYHMSSS_FORMAT = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss:SSS");
    private static final SimpleDateFormat ZA_HMS_FORMAT = new SimpleDateFormat("HH:mm:ss");
    private static final SimpleDateFormat ZA_HM_FORMAT = new SimpleDateFormat("HH:mm");
    public static long ONE_DAY = 1000L * 60L * 60L * 24L;

    public static Date combine(Date date, Date time) {

        if (date == null || time == null) {
            return null;
        }

        Calendar cal = new GregorianCalendar();
        cal.setTime(date);

        Calendar cal2 = new GregorianCalendar();
        cal2.setTime(time);

        cal.set(Calendar.HOUR_OF_DAY, cal2.get(Calendar.HOUR_OF_DAY));
        cal.set(Calendar.MINUTE, cal2.get(Calendar.MINUTE));
        cal.set(Calendar.SECOND, cal2.get(Calendar.SECOND));
        cal.set(Calendar.MILLISECOND, cal2.get(Calendar.MILLISECOND));

        return cal.getTime();
    }

    public static Date getStartOfDay(Date date) {
        if (date == null) {
            return null;
        }
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    public static boolean inThePast(Date date) {
        if (date == null) {
            throw new IllegalArgumentException("Must supply date");
        }
        return date.before(DateUtils.getStartOfDay(new Date()));
    }

    /**
     * Returns an array containing two <code>Date</code> objects: the 1st of
     * which contains a date representing the first millisecond; and the 2nd of
     * which contains a date representing the last millisecond of the day
     * represented by the given date.
     */
    public static DateRange getStartAndEndOfDay(Date date) {

        Date[] results = new Date[2];
        if (date == null) {
            return null;
        }

        Calendar cal = new GregorianCalendar();
        cal.setTime(date);

        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        results[0] = cal.getTime();

        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 999);
        results[1] = cal.getTime();

        return new DateRange(results[0], results[1]);
    }

    public static Date getEndOfDay(Date date) {
        if (date == null) {
            return null;
        }
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 999);
        return cal.getTime();
    }

    public static Date getEndOfYesterday() {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.DAY_OF_MONTH, -1);
        return getEndOfDay(cal.getTime());
    }

    public static void setToStartOfDay(Date date) {
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        date.setTime(cal.getTime().getTime());
    }

    public static void setToEndOfDay(Date date) {
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);

        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 999);

        date.setTime(cal.getTime().getTime());
    }

    /**
     * Truncates the time part to the level specified. Usefull if comparison to
     * these levels are needed.
     *
     * @param date          object to be truncated
     * @param calendarField to what accuracy the Date object should be trucated.
     */
    public static void truncateTimeTo(Date date, int calendarField) {
        Calendar cal = new GregorianCalendar();

        cal.setTime(date);

        switch (calendarField) {
            case Calendar.DAY_OF_YEAR:
                cal.set(Calendar.HOUR_OF_DAY, 0);
            case Calendar.HOUR:
                cal.set(Calendar.MINUTE, 0);
            case Calendar.MINUTE:
                cal.set(Calendar.SECOND, 0);
            case Calendar.SECOND:
                cal.set(Calendar.MILLISECOND, 0);
        }

        date.setTime(cal.getTime().getTime());
    }

    public static java.sql.Date toSQLDate(Date date) {
        if (date == null) {
            return null;
        }
        if (date instanceof java.sql.Date) {
            return (java.sql.Date) date;
        } else {
            return new java.sql.Date(date.getTime());
        }
    }

    public static java.sql.Time toSQLTime(Date date) {
        if (date == null) {
            return null;
        }
        if (date instanceof java.sql.Time) {
            return (java.sql.Time) date;
        } else {
            return new java.sql.Time(date.getTime());
        }
    }

    public static java.sql.Timestamp toSQLTimestamp(Date date) {
        if (date == null) {
            return null;
        }
        if (date instanceof java.sql.Timestamp) {
            return (java.sql.Timestamp) date;
        } else {
            return new java.sql.Timestamp(date.getTime());
        }
    }

    /**
     * Calculates the difference in days between the given start and end dates.
     */
    // Use getDaysBetween2
    @Deprecated
    public static int getDaysBetween(Date first, Date last) {
        if (first == null || last == null) {
            throw new IllegalArgumentException("Neither first nor last date can be null.");
        }
        Calendar calFirst = new GregorianCalendar();
        calFirst.setTime(first);
        Calendar calLast = new GregorianCalendar();
        calLast.setTime(last);
        int doyFirst, doyLast, yFirst, yLast;
        if (first.after(last)) {
            yFirst = calLast.get(Calendar.YEAR);
            doyFirst = calLast.get(Calendar.DAY_OF_YEAR);
            yLast = calFirst.get(Calendar.YEAR);
            doyLast = calFirst.get(Calendar.DAY_OF_YEAR);
        } else {
            yFirst = calFirst.get(Calendar.YEAR);
            doyFirst = calFirst.get(Calendar.DAY_OF_YEAR);
            yLast = calLast.get(Calendar.YEAR);
            doyLast = calLast.get(Calendar.DAY_OF_YEAR);
        }

        if (yFirst == yLast) {
            return Math.abs(doyLast - doyFirst);
        } else {
            int days = doyLast;
            int year = yLast - 1;
            do {
                days += getDaysInYear(year--);
            } while (year >= yFirst);
            return Math.abs(days - doyFirst);
        }

    }

    public static long getDaysBetween2(Date first, Date last) {
        long diff = last.getTime() - first.getTime();
        return TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);
    }

    public static long getMilliSecondsBetween2(Date first, Date last) {
        long diff = last.getTime() - first.getTime();
        return TimeUnit.MILLISECONDS.convert(diff, TimeUnit.MILLISECONDS);
    }

    public static long getHoursBetween2(Date first, Date last) {
        long diff = last.getTime() - first.getTime();
        return TimeUnit.HOURS.convert(diff, TimeUnit.MILLISECONDS);
    }

    public static long getDaysBetween(DateRange dateRange) {
        return getDaysBetween2(dateRange.getFrom(), dateRange.getTo());
    }

    public static Long getDaysBetweenObject(Date first, Date last) {
        if (first != null && last != null) {
            return getDaysBetween2(first, last);
        } else {
            return null;
        }
    }

    public static int getDaysInYear(int year) {
        Calendar cal = new GregorianCalendar(year, Calendar.DECEMBER, 31);
        return cal.get(Calendar.DAY_OF_YEAR);
    }

    public static Date addDays(Date date, int days) {
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);
        cal.add(Calendar.DATE, days);
        return cal.getTime();
    }

    public static Date add(Date date, int calendarField, int amount) {
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);
        cal.add(calendarField, amount);
        return cal.getTime();
    }

    public static Date subtract(Date date, int calendarField, int amount) {
        Calendar cal = new GregorianCalendar();
        cal.setTime(new Date(0));
        cal.add(calendarField, amount);
        return new Date(date.getTime() - cal.getTimeInMillis());
    }

    public static boolean fallsBetween(Date date, Date startDate, Date endDate) {
        if (date == null) {
            return false;
        }
        return date.equals(startDate) || date.equals(endDate) || (date.after(startDate) && date.before(endDate));
    }

    public static boolean isWeekDay(Date date) {
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);
        int dow = cal.get(Calendar.DAY_OF_WEEK);
        return dow != Calendar.SATURDAY && dow != Calendar.SUNDAY;
    }

    public static boolean isWeekDay(Date date, Locale locale, TimeZone timeZone) {
        Calendar cal = new GregorianCalendar(timeZone, locale);
        cal.setTime(date);
        int dow = cal.get(Calendar.DAY_OF_WEEK);
        return dow != Calendar.SATURDAY && dow != Calendar.SUNDAY;
    }

    public static int getCurrentYear() {
        return new GregorianCalendar().get(Calendar.YEAR);
    }

    public static int getCurrentMonth() {
        return new GregorianCalendar().get(Calendar.MONTH);
    }

    public static int getCurrentDay() {
        return new GregorianCalendar().get(Calendar.DAY_OF_MONTH);
    }

    public static int[] getYearMonthDay(Date date) {
        int[] ymd = new int[3];
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);
        ymd[0] = cal.get(Calendar.YEAR);
        ymd[1] = cal.get(Calendar.MONTH);
        ymd[2] = cal.get(Calendar.DAY_OF_MONTH);
        return ymd;
    }

    public static String[] getZeroPaddedYearMonthDay(Date date) {
        String[] ymd = new String[3];
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);

        ymd[0] = "" + cal.get(Calendar.YEAR);
        int m = cal.get(Calendar.MONTH) + 1;
        if (m < 10) {
            ymd[1] = "0" + m;
        } else {
            ymd[1] = "" + m;
        }
        int d = cal.get(Calendar.DAY_OF_MONTH);
        if (d < 10) {
            ymd[2] = "0" + d;
        } else {
            ymd[2] = "" + d;
        }

        return ymd;
    }

    public static int[] getHourMinuteSecond(Date date) {
        int[] hms = new int[3];
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);
        hms[0] = cal.get(Calendar.HOUR_OF_DAY);
        hms[1] = cal.get(Calendar.MINUTE);
        hms[2] = cal.get(Calendar.SECOND);
        return hms;
    }

    public static int[] getYMDHMS(Date date) {
        int[] ymdhms = new int[6];
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);
        ymdhms[0] = cal.get(Calendar.YEAR);
        ymdhms[1] = cal.get(Calendar.MONTH);
        ymdhms[2] = cal.get(Calendar.DAY_OF_MONTH);
        ymdhms[3] = cal.get(Calendar.HOUR_OF_DAY);
        ymdhms[4] = cal.get(Calendar.MINUTE);
        ymdhms[5] = cal.get(Calendar.SECOND);
        return ymdhms;
    }

    public static String[] getMonths() {
        SimpleDateFormat formatter = new SimpleDateFormat();
        return formatter.getDateFormatSymbols().getMonths();
    }

    public static int getLastDayOfMonth(Date date) {
        // Set to the first of the given month
        Calendar lastDayOfMonth = new GregorianCalendar();
        lastDayOfMonth.setTime(date);
        lastDayOfMonth.set(Calendar.DAY_OF_MONTH, 1);

        // Roll back around to end of same month
        lastDayOfMonth.roll(Calendar.DAY_OF_MONTH, false);
        // or alternatively:
        // lastDayOfMonth.add( Calendar.MONTH, 1 );
        // lastDayOfMonth.add( Calendar.DAY_OF_MONTH, -1 );

        return lastDayOfMonth.get(Calendar.DAY_OF_MONTH);
    }

    public static int getLastDayOfMonth(int year, int month) {
        // Set to the first of the given month
        GregorianCalendar lastDayOfMonth = new GregorianCalendar(year, month, 1);

        // Roll back around to end of same month
        lastDayOfMonth.roll(Calendar.DAY_OF_MONTH, false);
        // or alternatively:
        // lastDayOfMonth.add( Calendar.MONTH, 1 );
        // lastDayOfMonth.add( Calendar.DAY_OF_MONTH, -1 );

        return lastDayOfMonth.get(Calendar.DAY_OF_MONTH);
    }

    public static int getDayOfWeek(Date date) {
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);
        return cal.get(Calendar.DAY_OF_WEEK);
    }

    public static char getDayOfWeek1stLetterOnly(Date date) {
        String dow = getDayOfWeekAsString(date);
        if (dow == null) {
            return '\0';
        }
        return Character.toUpperCase(dow.charAt(0));
    }

    public static String getDayOfWeekAbbreviated(Date date) {
        return ABBR_DAY_OF_WEEK_FORMAT.format(date);
    }

    public static String getDayOfWeekAsString(Date date) {
        return FULL_DAY_OF_WEEK_FORMAT.format(date);
    }

    public static String toDateFormat(Date date, DateFormat dateFormat) {
        if (date == null || dateFormat == null) {
            return null;
        }
        return dateFormat.format(date);
    }

    public static Date fromDateFormat(String date, DateFormat dateFormat) {
        if (date == null || dateFormat == null) {
            return null;
        }
        try {
            return dateFormat.parse(date);
        } catch (ParseException pe) {
            return null;
        }
    }

    public static String toShortFormat(Date date) {
        if (date == null) {
            return null;
        }
        return DEF_SHORT_DATE_FORMAT.format(date);
    }

    public static String toZALongFormat(Date date) {
        if (date == null) {
            return null;
        }
        return ZA_LONG_DATE_FORMAT.format(date);
    }

    public static String toT_MYFormat(Date date) {
        return toDateFormat(date, T_MY_FORMAT);
    }

    public static Date fromT_MYFormat(String date) {
        return fromDateFormat(date, T_MY_FORMAT);
    }

    public static String toT_YMDFormat(Date date) {
        return toDateFormat(date, T_YMD_FORMAT);
    }

    public static String toT_DMYFormat(Date date) {
        return toDateFormat(date, T_DMY_FORMAT);
    }

    public static Date fromT_YMDFormat(String date) {
        return fromDateFormat(date, T_YMD_FORMAT);
    }

    public static String toZA_YMDFormat(Date date) {
        return toDateFormat(date, ZA_YMD_FORMAT);
    }

    public static String toZA_DMYFormat(Date date) {
        return toDateFormat(date, ZA_DMY_FORMAT);
    }

    public static String toZA_DMYHMSFormat(Date date) {
        return toDateFormat(date, ZA_DMYHMS_FORMAT);
    }

    public static String toZA_DMYHMSSSFormat(Date date) {
        return toDateFormat(date, ZA_DMYHMSSS_FORMAT);
    }

    public static Date fromZA_YMDFormat(String date) {
        return fromDateFormat(date, ZA_YMD_FORMAT);
    }

    public static String toZA_YMDHMSFormat(Date date) {
        if (date == null) {
            return null;
        }
        return ZA_YMDHMS_FORMAT.format(date);
    }

    public static String toZA_HMSFormat(Date date) {
        if (date == null) {
            return null;
        }
        return ZA_HMS_FORMAT.format(date);
    }

    public static String toZA_HMFormat(Date date) {
        if (date == null) {
            return null;
        }
        return ZA_HM_FORMAT.format(date);
    }

    public static DateRange createDateRange(Date date, int days) {
        return date != null ? new DateRange(date, days) : null;
    }

    public static Date clone(Date date) {
        if (date == null)
            return null;
        return new Date(date.getTime());
    }

    /**
     * Returns an array containing two <code>Date</code> objects: the 1st of
     * which contains a date representing the first millisecond of the first day
     * of the month; and the 2nd of which contains a date representing the last
     * millisecond of the last day of the month in which the given date falls.
     *
     * @param date
     * @return
     */
    public static Date[] getStartAndEndOfMonth(Date date) {

        Date[] results = new Date[2];
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);

        cal.set(Calendar.DAY_OF_MONTH, 1);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        results[0] = cal.getTime();

        cal.set(Calendar.DAY_OF_MONTH, getLastDayOfMonth(date));
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 999);
        results[1] = cal.getTime();

        return results;
    }

    public static Date getStartOfMonth(Date date) {
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    public static Date getEndOfMonth(Date date) {
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, getLastDayOfMonth(date));
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 999);
        return cal.getTime();
    }

    /**
     * Converts the given date into a "standardized" / "normalized" time
     * relative to the epoch. Returns a new <code>java.sql.Time</code> instance
     * based on the given date's hour, minute, second and millisecond fields
     * combined with the date fields of the "epoch" (i.e. January 1st 1970).
     */
    public static java.sql.Time toEpochTime(Date dateTime) {
        if (dateTime == null) {
            return null;
        }
        Calendar cal = new GregorianCalendar();
        cal.setTime(dateTime);
        cal.set(Calendar.YEAR, 1970);
        cal.set(Calendar.MONTH, Calendar.JANUARY);
        cal.set(Calendar.DAY_OF_MONTH, 1);

        return new java.sql.Time(cal.getTime().getTime());
    }

    /**
     * Converts the given date into a "standardized" / "normalized" time
     * relative to the epoch. Returns a new <code>java.sql.Time</code> instance
     * based on the given date's hour, minute, second and millisecond fields
     * combined with the date fields of the "epoch" (i.e. January 1st 1970).
     *
     * Synonym for <code>toEpochTime( Date )</code>.
     */
    public static java.sql.Time toNormalizedTime(Date dateTime) {
        return toEpochTime(dateTime);
    }

    /**
     * Converts the given date into a "standardized" / "normalized" date with
     * its hours, minutes, seconds and milliseconds all set to zero.
     *
     * Returns a new <code>java.sql.Date</code> instance based on the given
     * date's year, month and day fields combined with zeroised time fields.
     */
    public static java.sql.Date toNormalizedSqlDate(Date dateTime) {
        if (dateTime == null) {
            return null;
        }
        return new java.sql.Date(getStartOfDay(dateTime).getTime());
    }

    /**
     * Converts the given date into a "standardized" / "normalized" date with
     * its hours, minutes, seconds and milliseconds all set to zero.
     *
     * Returns a new <code>java.util.Date</code> instance based on the given
     * date's year, month and day fields combined with zeroised time fields.
     */
    public static java.util.Date toNormalizedDate(Date dateTime) {
        if (dateTime == null) {
            return null;
        }
        return new java.util.Date(getStartOfDay(dateTime).getTime());
    }

    public static Date toDate(int year, int month, int day) {
        return new GregorianCalendar(year, month - 1, day).getTime();
    }

    /**
     * Strict validation, that is the given year, month and day values must
     * represent an actual date, i.e. given 2001, 1 and 33 this method would
     * return false. This validation differs from the approach taken by
     * <code>new GregorianCalendar(y,m,d)</code> and
     * <code>DateFormate.parse(s)</code>, which accept almost any year, month
     * and day values and simply end up with a possibly different valid date,
     * for example 2001/01/33 would be converted to 2001/02/02.
     */
    public static boolean isValid(int year, int month, int day) {
        if (year < 0) {
            return false;
        }
        if (month < 1 || month > 12) {
            return false;
        }
        if (day < 1 || day > 31) {
            return false;
        }
        Calendar c = new GregorianCalendar(year, month - 1, day);
        return (c.get(Calendar.DAY_OF_MONTH) == day && c.get(Calendar.MONTH) + 1 == month && c.get(Calendar.YEAR) == year);
    }

    /**
     * Strict validation, that is the given year, month and day values must
     * represent an actual date, i.e. given 2001, 1 and 33, or given empty
     * Strings, this method would return false.
     */
    public static boolean isValid(String year, String month, String day) {
        if (year.equalsIgnoreCase("") || month.equalsIgnoreCase("") || day.equalsIgnoreCase("")) {
            return false;
        }
        int y = Integer.parseInt(year);
        int m = Integer.parseInt(month);
        int d = Integer.parseInt(day);
        return isValid(y, m, d);
    }

    /**
     * Returns true if the difference in months between 'from' and 'to' exceeds, in months, 'months'.
     *
     * @param from
     * @param to
     * @param months
     * @return
     */
    public static boolean exceedsInMonths(Date from, Date to, int months) {
        Date nFrom = DateUtils.add(from, GregorianCalendar.MONTH, months);

        if (nFrom.getTime() == to.getTime()) return false;

        return !to.before(nFrom);

        //return DateUtils.add(from, GregorianCalendar.MONTH, months).before(to);
    }

    public static LocalDate toLocalDate(Date date) {
        if (date == null) {

            return null;
        } else {
            return LocalDate.fromDateFields(date);
        }
    }

    public static LocalDateTime toLocalDateTime(Date date) {
        if (date == null) {
            return null;
        } else {
            return LocalDateTime.fromDateFields(date);
        }
    }

    /**
     * Returns true if the difference in days between 'from' and 'to' exceeds, in days, 'days'.
     * Not tested.
     *
     * @param from
     * @param to
     * @param months
     * @return
     */
    public static boolean exceedsInDays(Date from, Date to, int days) {

        return !DateUtils.add(from, GregorianCalendar.DAY_OF_YEAR, days).before(to);
    }

    public static String toFormat(Date date, String format) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
        return dateFormat.format(date);
    }

    public static String toFormat(java.time.LocalDateTime date, String format) {
        return DateTimeFormatter.ofPattern(format).format(date);
    }

    public static boolean expiredDate(Date date, Period expiryPeriod) {
        if (expiryPeriod.getHours() == 0) {
            return false;
        }

        final LocalDateTime lastResetDate = LocalDateTime.fromDateFields(date);
        if ((LocalDateTime.now().toDate()).after(lastResetDate.plusHours(expiryPeriod.getHours()).toDate())) {
            return true;
        }
        return false;
    }

    static public Date addNanoSEcs(Date date, int plusNanos) {
        java.time.LocalDateTime localDateTime = toLdt(date);
        java.time.LocalDateTime localDateTime1 = localDateTime.plusNanos(plusNanos);
        return fromLdt(localDateTime1);
    }

    static public java.time.LocalDateTime toLdt(Date date) {
        ZonedDateTime zdt = getZonedDateTime(date);
        return zdt.toLocalDateTime();
    }

    private static ZonedDateTime getZonedDateTime(Date date) {
        GregorianCalendar cal = new GregorianCalendar();
        cal.setTime(date);
        return cal.toZonedDateTime();
    }

    static public java.time.LocalDate toLd(Date date) {
        ZonedDateTime zdt = getZonedDateTime(date);

        java.time.LocalDate localDate = zdt.toLocalDate();

        return localDate;
    }

    static public Date fromLdt(java.time.LocalDateTime ldt) {
        ZonedDateTime zdt = ZonedDateTime.of(ldt, ZoneId.systemDefault());
        GregorianCalendar cal = GregorianCalendar.from(zdt);
        return cal.getTime();
    }

    /**
     * <p>Checks if two dates are on the same day ignoring time.</p>
     *
     * @param date1 the first date, not altered, not null
     * @param date2 the second date, not altered, not null
     * @return true if they represent the same day
     * @throws IllegalArgumentException if either date is <code>null</code>
     */
    public static boolean isSameDayTime(Date date1, Date date2) {
        if (date1 == null || date2 == null) {
            throw new IllegalArgumentException("The dates must not be null");
        }
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);
        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);
        return isSameDay(cal1, cal2);
    }

    /**
     * <p>Checks if two calendars represent the same day ignoring time.</p>
     *
     * @param cal1 the first calendar, not altered, not null
     * @param cal2 the second calendar, not altered, not null
     * @return true if they represent the same day
     * @throws IllegalArgumentException if either calendar is <code>null</code>
     */
    public static boolean isSameDay(Calendar cal1, Calendar cal2) {
        if (cal1 == null || cal2 == null) {
            throw new IllegalArgumentException("The dates must not be null");
        }
        return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) &&
                cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&
                cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR));
    }

    /**
     * <p>Checks if a date is today.</p>
     *
     * @param date the date, not altered, not null.
     * @return true if the date is today.
     * @throws IllegalArgumentException if the date is <code>null</code>
     */
    public static boolean isToday(Date date) {
        return isSameDayTime(date, Calendar.getInstance().getTime());
    }

    public static XMLGregorianCalendar getXmlGregorianCalendar(Date date, int adddays) {
        XMLGregorianCalendar date2 = null;
        try {
            GregorianCalendar cal = new GregorianCalendar();
            cal.setTime(date);
            cal.add(Calendar.DAY_OF_MONTH, adddays);
            date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(cal);
        } catch (DatatypeConfigurationException ex) {

        }
        return date2;
    }

    public static java.time.LocalDateTime fromDateFields(Date date) {
        return date != null
                ? Instant.ofEpochMilli(date.getTime())
                .atZone(ZoneId.systemDefault())
                .toLocalDateTime()
                : null;
    }

    static public Date fromLd(java.time.LocalDate ldt) {
        return Date.from(ldt.atStartOfDay(ZoneId.systemDefault()).toInstant());
    }

}