nl.strohalm.cyclos.utils.DateHelper.java Source code

Java tutorial

Introduction

Here is the source code for nl.strohalm.cyclos.utils.DateHelper.java

Source

/*
This file is part of Cyclos (www.cyclos.org).
A project of the Social Trade Organisation (www.socialtrade.org).
    
Cyclos 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 2 of the License, or
(at your option) any later version.
    
Cyclos 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 Cyclos; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    
 */
package nl.strohalm.cyclos.utils;

import java.math.BigDecimal;
import java.math.MathContext;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import nl.strohalm.cyclos.entities.reports.ThroughTimeRange;
import nl.strohalm.cyclos.entities.settings.LocalSettings;

import org.apache.commons.lang.time.DateUtils;

/**
 * Helper class for dates
 * @author luis
 */
public class DateHelper {

    /**
     * Returns the number of days between 2 dates. Will be negative if date2 < date1, 0 if both are the same day or positive otherwise
     */
    public static int daysBetween(Calendar date1, Calendar date2) {
        if (date1 == null || date2 == null) {
            return 0;
        }
        date1 = truncate(date1);
        date2 = truncate(date2);
        return (int) ((date2.getTimeInMillis() - date1.getTimeInMillis()) / DateUtils.MILLIS_PER_DAY);
    }

    /**
     * inverse function of decimalDaysBetween: adds a BigDecimal number of days to a Calendar.
     * @param date1 the date to which something is added
     * @param augend the number of days which is added, as a BigDecimal. May be negative.
     * @return null if one of the arguments is null, else the date + augend days.
     */
    public static Calendar decimalDaysAdd(final Calendar date1, final BigDecimal augend) {
        if (date1 == null || augend == null) {
            return null;
        }
        final BigDecimal date1InMillis = new BigDecimal(date1.getTimeInMillis());
        final BigDecimal augendInMillis = augend.multiply(new BigDecimal(DateUtils.MILLIS_PER_DAY));
        final BigDecimal resultAsBig = date1InMillis.add(augendInMillis);
        final Calendar result = Calendar.getInstance();
        result.setTimeInMillis(resultAsBig.longValue());
        return result;
    }

    /**
     * Returns the number of days between 2 dates as a BigDecimal. Will be negative if date2 < date1, or positive otherwise.
     */
    public static BigDecimal decimalDaysBetween(final Calendar date1, final Calendar date2) {
        if (date1 == null || date2 == null) {
            return BigDecimal.ZERO;
        }
        final BigDecimal difference = new BigDecimal(date2.getTimeInMillis() - date1.getTimeInMillis());
        final MathContext mathContext = new MathContext(LocalSettings.MAX_PRECISION);
        final BigDecimal result = difference.divide(new BigDecimal(DateUtils.MILLIS_PER_DAY), mathContext);
        return result;
    }

    /**
     * sets the time of the day of the first argument, so that it is equal to the time of the day of the second argument.
     * @param toEqualize a Calendar, whose time will be equalized to the source's time of the day
     * @param source the time of the day of this Calendar is taken.
     * @return a new Calendar object, with the date equal to toEqualize, but the time of the date is equal to that of the source Calendar.
     */
    public static Calendar equalizeTime(final Calendar toEqualize, final Calendar source) {
        if (source == null) {
            return null;
        }
        final int hourOfDay = source.get(Calendar.HOUR_OF_DAY);
        final int minute = source.get(Calendar.MINUTE);
        final int second = source.get(Calendar.SECOND);
        final int milliSecond = source.get(Calendar.MILLISECOND);
        final Calendar result = (Calendar) toEqualize.clone();
        result.set(Calendar.HOUR_OF_DAY, hourOfDay);
        result.set(Calendar.MINUTE, minute);
        result.set(Calendar.SECOND, second);
        result.set(Calendar.MILLISECOND, milliSecond);
        return result;
    }

    /**
     * compares two Calendars on a certain precision level. <br>
     * For example, if you had the datetime of 12 Mar 2011 14:31:07.847, and a second datetime of 12 Mar 2011 14:31:11.734, they would evaluate as
     * equal on the Calendar.MINUTE level and above. They would evaluate as not equal on levels Calendar.SECOND and Calendar.MILLISECOND.<br>
     * Fields are rounded, so 12 Mar 2011 14:31:07.847 and 12 Mar 2011 14:31:08.123 would evaluate as equal on the Calendar.SECOND level.
     * @param cal1 if null, returns false
     * @param cal2 if null, returns false
     * @param level, for example Calendar.MINUTE
     * @return true if equal on this level, false if not.
     */
    public static boolean equals(final Calendar cal1, final Calendar cal2, final int level) {
        if (cal1 == null || cal2 == null) {
            return false;
        }
        final Calendar temp1 = DateUtils.round((Calendar) cal1.clone(), level);
        final Calendar temp2 = DateUtils.round((Calendar) cal2.clone(), level);
        return (temp1.equals(temp2));
    }

    /**
     * Returns a date at 23:59:59 of the given day
     */
    public static Calendar getDayEnd(final Calendar date) {
        return TimePeriod.ONE_DAY.currentPeriod(date).getEnd();
    }

    /**
     * a null proof method returning the earliest of any number of Calendars
     * @param dates any null arguments are ignored. If all arguments are null just returns null.
     * @return the earliest date of the arguments.
     */
    public static Calendar getEarliest(final Calendar... dates) {
        Calendar oldest = null;
        for (final Calendar date : dates) {
            if (oldest == null || (date != null && oldest.after(date))) {
                oldest = date;
            }
        }
        return oldest;
    }

    public static Map<String, Object> getLastCompletedMonthAndYear() {
        final Calendar now = Calendar.getInstance();
        int month = now.get(Calendar.MONTH);
        int year = now.get(Calendar.YEAR);
        if (month == 0) {
            month = 12;
            year--;
        } else {
            month--;
        }
        final Map<String, Object> completedMonthAndYear = new HashMap<String, Object>();
        completedMonthAndYear.put("month", month);
        completedMonthAndYear.put("year", year);
        return completedMonthAndYear;
    }

    public static Map<String, Object> getLastCompletedQuarterAndYear() {
        final Calendar now = Calendar.getInstance();
        final int month = now.get(Calendar.MONTH);
        int year = now.get(Calendar.YEAR);
        Quarter quarter = null;
        switch (month) {
        case 0:
        case 1:
        case 2:
            quarter = Quarter.FOURTH;
            year--;
            break;
        case 3:
        case 4:
        case 5:
            quarter = Quarter.FIRST;
            break;
        case 6:
        case 7:
        case 8:
            quarter = Quarter.SECOND;
            break;
        case 9:
        case 10:
        case 11:
            quarter = Quarter.THIRD;
            break;
        }
        final Map<String, Object> completedQuarterAndYear = new HashMap<String, Object>();
        completedQuarterAndYear.put("quarter", quarter);
        completedQuarterAndYear.put("year", year);
        return completedQuarterAndYear;
    }

    public static Period[] getPeriodsThroughTheTime(final Period period, final ThroughTimeRange throughTimeRange) {
        final Calendar calendarIni = period.getBegin();
        final Calendar calendarFini = period.getEnd();
        final List<Period> result = new ArrayList<Period>();

        final int monthIni = calendarIni.get(Calendar.MONTH);
        final int monthFini = calendarFini.get(Calendar.MONTH);
        final int yearIni = calendarIni.get(Calendar.YEAR);
        final int yearFini = calendarFini.get(Calendar.YEAR);

        for (int year = calendarIni.get(Calendar.YEAR); year <= calendarFini.get(Calendar.YEAR); year++) {
            Period periodAux = null;
            int monthIniAux = 0;
            int monthFiniAux = 11;

            if (year == yearIni) {
                monthIniAux = monthIni;
            } else {
                monthIniAux = 0;
            }

            if (year == yearFini) {
                monthFiniAux = monthFini;
            } else {
                monthFiniAux = 11;
            }
            int increment = 1;

            // months or quarters
            if (throughTimeRange == ThroughTimeRange.MONTH || throughTimeRange == ThroughTimeRange.QUARTER) {
                // only quarters
                if (throughTimeRange == ThroughTimeRange.QUARTER) {
                    increment = 3;
                }
                for (int month = monthIniAux; month <= monthFiniAux; month = month + increment) {
                    final Calendar calendarIniAux = new GregorianCalendar(year, month, 1, 0, 0, 0);
                    final Calendar calendarFiniHlp = new GregorianCalendar(year, (month + increment - 1), 1);
                    final Calendar calendarFiniAux = new GregorianCalendar(year, (month + increment - 1),
                            calendarFiniHlp.getActualMaximum(Calendar.DAY_OF_MONTH), 23, 59, 59);
                    periodAux = new Period(calendarIniAux, calendarFiniAux);
                    result.add(periodAux);
                }
            }
            // years, it doesn't need to iterate over months.
            else if (throughTimeRange == ThroughTimeRange.YEAR) {
                final Calendar calendarIniAux = new GregorianCalendar(year, 0, 1, 0, 0, 0);
                final Calendar calendarFiniAux = new GregorianCalendar(year, 11, 31, 23, 59, 59);
                periodAux = new Period(calendarIniAux, calendarFiniAux);
                result.add(periodAux);
            }
        }
        final Period[] periodResult = new Period[result.size()];
        return result.toArray(periodResult);
    }

    public static Period getYearPeriod(final int year) {
        // First day of the year
        Calendar begin = Calendar.getInstance();
        begin.set(Calendar.YEAR, year);
        begin = truncate(begin);

        // First day of the next year
        final Calendar end = Calendar.getInstance();
        end.set(Calendar.YEAR, year + 1);

        final Period yearPeriod = new Period();
        yearPeriod.setBegin(begin);
        yearPeriod.setEnd(end);
        return yearPeriod;
    }

    /**
     * checks if the two dates are on the same calendar day.
     */
    public static boolean sameDay(final Calendar first, final Calendar second) {
        final Calendar equalizedFirst = DateHelper.equalizeTime(first, second);
        return (equalizedFirst.equals(second));
    }

    /**
     * Returns the number of seconds since the given time
     */
    public static double secondsSince(final long since) {
        return (System.currentTimeMillis() - since) / 1000.0;
    }

    /**
     * Truncates a date, handling null. Doesn't modify the Calendar parameter, returning a new modified instance
     */
    public static Calendar truncate(final Calendar date) {
        if (date == null) {
            return null;
        }
        return DateUtils.truncate(date, Calendar.DATE);
    }

    /**
     * Truncates a date and adds 1 day, handling null. Doesn't modify the Calendar parameter, returning a new modified instance
     */
    public static Calendar truncateNextDay(Calendar date) {
        if (date == null) {
            return null;
        }
        date = (Calendar) date.clone();
        date.add(Calendar.DATE, 1);
        return truncate(date);
    }

    /**
     * Truncates a date and subtracts 1 day, handling null. Doesn't modify the Calendar parameter, returning a new modified instance
     */
    public static Calendar truncatePreviosDay(Calendar date) {
        if (date == null) {
            return null;
        }
        date = (Calendar) date.clone();
        date.add(Calendar.DATE, -1);
        return truncate(date);
    }

}