DateUtils.java

/*
 * This file is part of Indicators.
 *
 * Indicators is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Indicators is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Indicators. If not, see <https://www.gnu.org/licenses/>.
 */
package fr.inrae.agroclim.indicators.util;

import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

import lombok.NonNull;

/**
 * Date manipulation utilities.
 *
 * Last changed : $Date$
 *
 * @author $Author$
 * @version $Revision$
 */
public final class DateUtils {
    /**
     * Number of days in leap year.
     */
    private static final int NB_OF_DAYS_IN_LEAP_YEAR = 366;

    /**
     * Number of days in usual year.
     */
    private static final int NB_OF_DAYS_IN_YEAR = 365;

    /**
     * Number of hours in a day.
     */
    public static final int NB_OF_HOURS_IN_DAY = 24;

    /**
     * Number of milliseconds in an hour.
     */
    public static final long NB_OF_MS_IN_HOUR = 60 * 60 * 1000L;

    /**
     * Number of milliseconds in a day.
     */
    public static final long NB_OF_MS_IN_DAY = NB_OF_MS_IN_HOUR * NB_OF_HOURS_IN_DAY;

    /**
     * @param date Date
     * @return Java8 LocalDate
     */
    public static LocalDate asLocalDate(@NonNull final Date date) {
        return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.of("UTC")).toLocalDate();
    }

    /**
     * @param year
     *            year
     * @return is it a leap year?
     */
    public static boolean isLeap(final int year) {
        boolean isLeap = false;
        // no leap year every 400 year.
        final int except = 400;
        final int century = 100;
        final int four = 4;
        if (year % four == 0 && year % century != 0) {
            isLeap = true;
        }
        if (year % except == 0) {
            isLeap = true;
        }
        return isLeap;
    }

    /**
     * @param year
     *            year
     * @return number of days in year
     */
    public static int nbOfDays(final int year) {
        if (isLeap(year)) {
            return NB_OF_DAYS_IN_LEAP_YEAR;
        } else {
            return NB_OF_DAYS_IN_YEAR;
        }
    }

    /**
     * @return calendar used for date handling.
     */
    public static Calendar getCalendar() {
        return Calendar.getInstance(TimeZone.getTimeZone("UTC"));
    }

    /**
     * Get Date from year and day of year.
     *
     * NB: with LocalDate, LocalDate.ofYearDay().
     *
     * @param year year
     * @param doy day of year (1-366)
     * @return date
     */
    public static Date getDate(final int year, final int doy) {
        final Calendar cal = getCalendar();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.DAY_OF_YEAR, doy);
        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();
    }

    /**
     * Get day of month from Date.
     *
     * NB: with LocalDate, LocalDate.getDayOfMonth().
     *
     * @param date date
     * @return day of month
     */
    public static Integer getDom(final Date date) {
        final Calendar cal = getCalendar();
        cal.setTime(date);
        return cal.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * Get day of year from Date.
     *
     * NB: with LocalDate, LocalDate.getDayOfYear().
     *
     * @param date date
     * @return day of year
     */
    public static Integer getDoy(final Date date) {
        final Calendar cal = getCalendar();
        cal.setTime(date);
        return cal.get(Calendar.DAY_OF_YEAR);
    }

    /**
     * Get month (1-12) from Date.
     *
     * NB: with LocalDate, LocalDate.getMonthValue().
     *
     * @param date date
     * @return day of year
     */
    public static Integer getMonth(final Date date) {
        final Calendar cal = getCalendar();
        cal.setTime(date);
        return cal.get(Calendar.MONTH) + 1;
    }

    /**
     * Get year from Date.
     *
     * NB: with LocalDate, LocalDate.getYear().
     *
     * @param date date
     * @return year
     */
    public static Integer getYear(final Date date) {
        final Calendar cal = getCalendar();
        cal.setTime(date);
        return cal.get(Calendar.YEAR);
    }

    /**
     * No constructor on helper class.
     */
    private DateUtils() {
    }
}