All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hurence.logisland.util.time.CalendarUtil Maven / Gradle / Ivy

There is a newer version: 1.4.1
Show newest version
/**
 * Copyright (C) 2016 Hurence ([email protected])
 *
 * 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 com.hurence.logisland.util.time;

import java.util.Calendar;

/**
 * Useful Calendar utilities.
 *
 * @author BalusC
 * @link http://balusc.omnifaces.org/2007/09/calendarutil.html
 */
public final class CalendarUtil {

    // Init ---------------------------------------------------------------------------------------

    private CalendarUtil() {
        // Utility class, hide the constructor.
    }

    // Validators ---------------------------------------------------------------------------------

    /**
     * Checks whether the given day, month and year combination is a valid date or not.
     * @param year The year part of the date.
     * @param month The month part of the date.
     * @param day The day part of the date.
     * @return True if the given day, month and year combination is a valid date.
     */
    public static boolean isValidDate(int year, int month, int day) {
        return isValidDate(year, month, day, 0, 0, 0);
    }

    /**
     * Checks whether the given hour, minute and second combination is a valid time or not.
     * @param hour The hour part of the time.
     * @param minute The minute part of the time.
     * @param second The second part of the time.
     * @return True if the given hour, minute and second combination is a valid time.
     */
    public static boolean isValidTime(int hour, int minute, int second) {
        return isValidDate(1, 1, 1, hour, minute, second);
    }

    /**
     * Checks whether the given day, month, year, hour, minute and second combination is a valid
     * date or not.
     * @param year The year part of the date.
     * @param month The month part of the date.
     * @param day The day part of the date.
     * @param hour The hour part of the date.
     * @param minute The minute part of the date.
     * @param second The second part of the date.
     * @return True if the given day, month, year, hour, minute and second combination is a valid
     * date.
     */
    public static boolean isValidDate(
            int year, int month, int day, int hour, int minute, int second)
    {
        try {
            getValidCalendar(year, month, day, hour, minute, second);
            return true;
        } catch (IllegalArgumentException e) {
            return false;
        }
    }

    /**
     * Validate the actual date of the given date elements and returns a calendar instance based on
     * the given date elements. The time is forced to 00:00:00.
     * @param year The year part of the date.
     * @param month The month part of the date.
     * @param day The day part of the date.
     * @return A Calendar instance prefilled with the given date elements.
     * @throws IllegalArgumentException If the given date elements does not represent a valid date.
     */
    public static Calendar getValidCalendar(int year, int month, int day) {
        return getValidCalendar(year, month, day, 0, 0, 0);
    }

    /**
     * Validate the actual date of the given date elements and returns a calendar instance based on
     * the given date elements.
     * @param year The year part of the date.
     * @param month The month part of the date.
     * @param day The day part of the date.
     * @param hour The hour part of the date.
     * @param minute The minute part of the date.
     * @param second The second part of the date.
     * @return A Calendar instance prefilled with the given date elements.
     * @throws IllegalArgumentException If the given date elements does not represent a valid date.
     */
    public static Calendar getValidCalendar(
            int year, int month, int day, int hour, int minute, int second)
    {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.setLenient(false); // Don't automatically convert invalid date.
        calendar.set(year, month - 1, day, hour, minute, second);
        calendar.getTimeInMillis(); // Lazy update, throws IllegalArgumentException if invalid date.
        return calendar;
    }

    // Changers -----------------------------------------------------------------------------------

    /**
     * Add the given amount of years to the given calendar. The changes are reflected in the given
     * calendar.
     * @param calendar The calendar to add the given amount of years to.
     * @param years The amount of years to be added to the given calendar. Negative values are also
     * allowed, it will just go back in time.
     */
    public static void addYears(Calendar calendar, int years) {
        calendar.add(Calendar.YEAR, years);
    }

    /**
     * Add the given amount of months to the given calendar. The changes are reflected in the given
     * calendar.
     * @param calendar The calendar to add the given amount of months to.
     * @param months The amount of months to be added to the given calendar. Negative values are
     * also allowed, it will just go back in time.
     */
    public static void addMonths(Calendar calendar, int months) {
        calendar.add(Calendar.MONTH, months);
    }

    /**
     * Add the given amount of days to the given calendar. The changes are reflected in the given
     * calendar.
     * @param calendar The calendar to add the given amount of days to.
     * @param days The amount of days to be added to the given calendar. Negative values are also
     * allowed, it will just go back in time.
     */
    public static void addDays(Calendar calendar, int days) {
        calendar.add(Calendar.DATE, days);
    }

    /**
     * Add the given amount of hours to the given calendar. The changes are reflected in the given
     * calendar.
     * @param calendar The calendar to add the given amount of hours to.
     * @param hours The amount of hours to be added to the given calendar. Negative values are also
     * allowed, it will just go back in time.
     */
    public static void addHours(Calendar calendar, int hours) {
        calendar.add(Calendar.HOUR, hours);
    }

    /**
     * Add the given amount of minutes to the given calendar. The changes are reflected in the given
     * calendar.
     * @param calendar The calendar to add the given amount of minutes to.
     * @param minutes The amount of minutes to be added to the given calendar. Negative values are
     * also allowed, it will just go back in time.
     */
    public static void addMinutes(Calendar calendar, int minutes) {
        calendar.add(Calendar.MINUTE, minutes);
    }

    /**
     * Add the given amount of seconds to the given calendar. The changes are reflected in the given
     * calendar.
     * @param calendar The calendar to add the given amount of seconds to.
     * @param seconds The amount of seconds to be added to the given calendar. Negative values are
     * also allowed, it will just go back in time.
     */
    public static void addSeconds(Calendar calendar, int seconds) {
        calendar.add(Calendar.SECOND, seconds);
    }

    /**
     * Add the given amount of millis to the given calendar. The changes are reflected in the given
     * calendar.
     * @param calendar The calendar to add the given amount of millis to.
     * @param millis The amount of millis to be added to the given calendar. Negative values are
     * also allowed, it will just go back in time.
     */
    public static void addMillis(Calendar calendar, int millis) {
        calendar.add(Calendar.MILLISECOND, millis);
    }

    // Comparators --------------------------------------------------------------------------------

    /**
     * Returns true if the two given calendars are dated on the same year.
     * @param one The one calendar.
     * @param two The other calendar.
     * @return True if the two given calendars are dated on the same year.
     */
    public static boolean sameYear(Calendar one, Calendar two) {
        return one.get(Calendar.YEAR) == two.get(Calendar.YEAR);
    }

    /**
     * Returns true if the two given calendars are dated on the same year and month.
     * @param one The one calendar.
     * @param two The other calendar.
     * @return True if the two given calendars are dated on the same year and month.
     */
    public static boolean sameMonth(Calendar one, Calendar two) {
        return one.get(Calendar.MONTH) == two.get(Calendar.MONTH) && sameYear(one, two);
    }

    /**
     * Returns true if the two given calendars are dated on the same year, month and day.
     * @param one The one calendar.
     * @param two The other calendar.
     * @return True if the two given calendars are dated on the same year, month and day.
     */
    public static boolean sameDay(Calendar one, Calendar two) {
        return one.get(Calendar.DATE) == two.get(Calendar.DATE) && sameMonth(one, two);
    }

    /**
     * Returns true if the two given calendars are dated on the same year, month, day and
     * hour.
     * @param one The one calendar.
     * @param two The other calendar.
     * @return True if the two given calendars are dated on the same year, month, day and hour.
     */
    public static boolean sameHour(Calendar one, Calendar two) {
        return one.get(Calendar.HOUR_OF_DAY) == two.get(Calendar.HOUR_OF_DAY) && sameDay(one, two);
    }

    /**
     * Returns true if the two given calendars are dated on the same year, month, day,
     * hour and minute.
     * @param one The one calendar.
     * @param two The other calendar.
     * @return True if the two given calendars are dated on the same year, month, day, hour and
     * minute.
     */
    public static boolean sameMinute(Calendar one, Calendar two) {
        return one.get(Calendar.MINUTE) == two.get(Calendar.MINUTE) && sameHour(one, two);
    }

    /**
     * Returns true if the two given calendars are dated on the same year, month, day,
     * hour, minute and second.
     * @param one The one calendar.
     * @param two The other calendar.
     * @return True if the two given calendars are dated on the same year, month, day, hour, minute
     * and second.
     */
    public static boolean sameSecond(Calendar one, Calendar two) {
        return one.get(Calendar.SECOND) == two.get(Calendar.SECOND) && sameMinute(one, two);
    }

    /**
     * Returns true if the two given calendars are dated on the same time. The difference
     * from one.equals(two) is that this method does not respect the time zone.
     * @param one The one calendar.
     * @param two The other calendar.
     * @return True if the two given calendars are dated on the same time.
     */
    public static boolean sameTime(Calendar one, Calendar two) {
        return one.getTimeInMillis() == two.getTimeInMillis();
    }

    // Calculators --------------------------------------------------------------------------------

    /**
     * Retrieve the amount of elapsed years between the two given calendars.
     * @param before The first calendar with expected date before the second calendar.
     * @param after The second calendar with expected date after the first calendar.
     * @return The amount of elapsed years between the two given calendars.
     * @throws IllegalArgumentException If the first calendar is dated after the second calendar.
     */
    public static int elapsedYears(Calendar before, Calendar after) {
        return elapsed(before, after, Calendar.YEAR);
    }

    /**
     * Retrieve the amount of elapsed months between the two given calendars.
     * @param before The first calendar with expected date before the second calendar.
     * @param after The second calendar with expected date after the first calendar.
     * @return The amount of elapsed months between the two given calendars.
     * @throws IllegalArgumentException If the first calendar is dated after the second calendar.
     */
    public static int elapsedMonths(Calendar before, Calendar after) {
        return elapsed(before, after, Calendar.MONTH);
    }

    /**
     * Retrieve the amount of elapsed days between the two given calendars.
     * @param before The first calendar with expected date before the second calendar.
     * @param after The second calendar with expected date after the first calendar.
     * @return The amount of elapsed days between the two given calendars.
     * @throws IllegalArgumentException If the first calendar is dated after the second calendar.
     */
    public static int elapsedDays(Calendar before, Calendar after) {
        return elapsed(before, after, Calendar.DATE);
    }

    /**
     * Retrieve the amount of elapsed hours between the two given calendars.
     * @param before The first calendar with expected date before the second calendar.
     * @param after The second calendar with expected date after the first calendar.
     * @return The amount of elapsed hours between the two given calendars.
     * @throws IllegalArgumentException If the first calendar is dated after the second calendar.
     */
    public static int elapsedHours(Calendar before, Calendar after) {
        return (int) elapsedMillis(before, after, 3600000); // 1h = 60m = 3600s = 3600000ms
    }

    /**
     * Retrieve the amount of elapsed minutes between the two given calendars.
     * @param before The first calendar with expected date before the second calendar.
     * @param after The second calendar with expected date after the first calendar.
     * @return The amount of elapsed minutes between the two given calendars.
     * @throws IllegalArgumentException If the first calendar is dated after the second calendar.
     */
    public static int elapsedMinutes(Calendar before, Calendar after) {
        return (int) elapsedMillis(before, after, 60000); // 1m = 60s = 60000ms
    }

    /**
     * Retrieve the amount of elapsed seconds between the two given calendars.
     * @param before The first calendar with expected date before the second calendar.
     * @param after The second calendar with expected date after the first calendar.
     * @return The amount of elapsed seconds between the two given calendars.
     * @throws IllegalArgumentException If the first calendar is dated after the second calendar.
     */
    public static int elapsedSeconds(Calendar before, Calendar after) {
        return (int) elapsedMillis(before, after, 1000); // 1sec = 1000ms.
    }

    /**
     * Retrieve the amount of elapsed milliseconds between the two given calendars.
     * @param before The first calendar with expected date before the second calendar.
     * @param after The second calendar with expected date after the first calendar.
     * @return The amount of elapsed milliseconds between the two given calendars.
     * @throws IllegalArgumentException If the first calendar is dated after the second calendar.
     */
    public static long elapsedMillis(Calendar before, Calendar after) {
        return elapsedMillis(before, after, 1); // 1ms is apparently 1ms.
    }

    /**
     * Calculate the total of elapsed time from years up to seconds between the two given calendars.
     * It returns an int array with the elapsed years, months, days, hours, minutes and seconds
     * respectively.
     * @param before The first calendar with expected date before the second calendar.
     * @param after The second calendar with expected date after the first calendar.
     * @return The elapsed time between the two given calendars in years, months, days, hours,
     * minutes and seconds.
     * @throws IllegalArgumentException If the first calendar is dated after the second calendar.
     */
    public static int[] elapsedTime(Calendar before, Calendar after) {
        int[] elapsedTime = new int[6];
        Calendar clone = (Calendar) before.clone(); // Otherwise changes are been reflected.

        elapsedTime[0] = elapsedYears(clone, after);
        addYears(clone, elapsedTime[0]);

        elapsedTime[1] = elapsedMonths(clone, after);
        addMonths(clone, elapsedTime[1]);

        elapsedTime[2] = elapsedDays(clone, after);
        addDays(clone, elapsedTime[2]);

        elapsedTime[3] = elapsedHours(clone, after);
        addHours(clone, elapsedTime[3]);

        elapsedTime[4] = elapsedMinutes(clone, after);
        addMinutes(clone, elapsedTime[4]);

        elapsedTime[5] = elapsedSeconds(clone, after);

        return elapsedTime;
    }

    // Helpers ------------------------------------------------------------------------------------

    /**
     * Retrieve the amount of elapsed time between the two given calendars based on the given
     * calendar field as definied in the Calendar constants, e.g. Calendar.MONTH.
     * @param before The first calendar with expected date before the second calendar.
     * @param after The second calendar with expected date after the first calendar.
     * @param field The calendar field as definied in the Calendar constants.
     * @return The amount of elapsed time between the two given calendars based on the given
     * calendar field.
     * @throws IllegalArgumentException If the first calendar is dated after the second calendar.
     */
    private static int elapsed(Calendar before, Calendar after, int field) {
        checkBeforeAfter(before, after);
        Calendar clone = (Calendar) before.clone(); // Otherwise changes are been reflected.
        int elapsed = -1;
        while (!clone.after(after)) {
            clone.add(field, 1);
            elapsed++;
        }
        return elapsed;
    }

    /**
     * Retrieve the amount of elapsed milliseconds between the two given calendars and directly
     * divide the outcome by the given factor. E.g.: if the division factor is 1, then you will get
     * the elapsed milliseconds unchanged; if the division factor is 1000, then the elapsed
     * milliseconds will be divided by 1000, resulting in the amount of elapsed seconds.
     * @param before The first calendar with expected date before the second calendar.
     * @param after The second calendar with expected date after the first calendar.
     * @param factor The division factor which to divide the milliseconds with, expected to be at
     * least 1.
     * @return The amount of elapsed milliseconds between the two given calendars, divided by the
     * given factor.
     * @throws IllegalArgumentException If the first calendar is dated after the second calendar or
     * if the division factor is less than 1.
     */
    private static long elapsedMillis(Calendar before, Calendar after, int factor) {
        checkBeforeAfter(before, after);
        if (factor < 1) {
            throw new IllegalArgumentException(
                    "Division factor '" + factor + "' should not be less than 1.");
        }
        return (after.getTimeInMillis() - before.getTimeInMillis()) / factor;
    }

    /**
     * Check if the first calendar is actually dated before the second calendar.
     * @param before The first calendar with expected date before the second calendar.
     * @param after The second calendar with expected date after the first calendar.
     * @throws IllegalArgumentException If the first calendar is dated after the second calendar.
     */
    private static void checkBeforeAfter(Calendar before, Calendar after) {
        if (before.after(after)) {
            throw new IllegalArgumentException(
                    "The first calendar should be dated before the second calendar.");
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy