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

Java tutorial

Introduction

Here is the source code for nl.strohalm.cyclos.utils.TimePeriod.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.io.Serializable;
import java.util.Calendar;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.time.DateUtils;

/**
 * Defines a time period, with a number and a field. It represents an amount of time in the specified unit, i.e.: 5 DAYS.
 * @author luis
 */
public class TimePeriod implements Serializable, Cloneable {

    /**
     * A given time field
     * @author luis
     */
    public static enum Field implements IntValuedEnum {
        MILLIS(Calendar.MILLISECOND), SECONDS(Calendar.SECOND), MINUTES(Calendar.MINUTE), HOURS(
                Calendar.HOUR_OF_DAY, Calendar.HOUR), DAYS(
                        Calendar.DATE), WEEKS(Calendar.WEEK_OF_YEAR), MONTHS(Calendar.MONTH), YEARS(Calendar.YEAR);

        public static Field findByCalendarField(final int value) {
            for (final Field field : values()) {
                if (ArrayUtils.contains(field.calendarValues, value)) {
                    return field;
                }
            }
            return null;
        }

        private int[] calendarValues;

        private Field(final int calendarValue) {
            calendarValues = new int[] { calendarValue };
        }

        private Field(final int... calendarValues) {
            this.calendarValues = calendarValues;
        }

        public int getCalendarValue() {
            return calendarValues[0];
        }

        @Override
        public int getValue() {
            return getCalendarValue();
        }
    }

    /**
     * A time period of 1 month
     */
    public static final TimePeriod ONE_MONTH = new TimePeriod(1, Field.MONTHS);

    /**
     * A time period of 1 day
     */
    public static final TimePeriod ONE_DAY = new TimePeriod(1, Field.DAYS);

    private static final long serialVersionUID = 859616150477032565L;

    private int number;
    private Field field;

    public TimePeriod() {
    }

    public TimePeriod(final int number, final Field field) {
        this.number = number;
        this.field = field == null ? Field.DAYS : field;
    }

    /**
     * Return a new calendar adding this time period
     */
    public Calendar add(final Calendar date) {
        if (date == null) {
            return null;
        }
        if (!isValid()) {
            return date;
        }
        final Calendar ret = (Calendar) date.clone();
        ret.add(field.getCalendarValue(), number);
        return ret;
    }

    @Override
    public TimePeriod clone() {
        try {
            return (TimePeriod) super.clone();
        } catch (final CloneNotSupportedException e) {
            return null;
        }
    }

    /**
     * Returns the full period which includes the given date
     */
    public Period currentPeriod(final Calendar date) {
        final Calendar start = previousPeriod(date).getEnd();
        start.add(Calendar.SECOND, 1);
        return periodStartingAt(start);
    }

    @Override
    public boolean equals(final Object obj) {
        if (!(obj instanceof TimePeriod)) {
            return false;
        }
        final TimePeriod tp = (TimePeriod) obj;
        return new EqualsBuilder().append(number, tp.number).append(field, tp.field).isEquals();
    }

    public Field getField() {
        return field;
    }

    public int getNumber() {
        return number;
    }

    public float getValueIn(final Field field) {
        final Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(0L);
        final Calendar cal2 = add(cal);
        final float millisDiff = cal2.getTimeInMillis() - cal.getTimeInMillis();
        switch (field) {
        case MILLIS:
            return millisDiff;
        case SECONDS:
            return millisDiff / DateUtils.MILLIS_PER_SECOND;
        case MINUTES:
            return millisDiff / DateUtils.MILLIS_PER_MINUTE;
        case HOURS:
            return millisDiff / DateUtils.MILLIS_PER_HOUR;
        case DAYS:
            return millisDiff / DateUtils.MILLIS_PER_DAY;
        case WEEKS:
            return millisDiff / (DateUtils.MILLIS_PER_DAY * 7);
        case MONTHS:
            return millisDiff / (DateUtils.MILLIS_PER_DAY * 30);
        case YEARS:
            return millisDiff / (DateUtils.MILLIS_PER_DAY * 365);
        }
        return 0F;
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder().append(number).append(field).toHashCode();
    }

    public boolean isValid() {
        return number > 0 && field != null;
    }

    /**
     * Returns a period ending at the given date (not including it), with this size
     */
    public Period periodEndingAt(Calendar endDate) {
        endDate = (Calendar) endDate.clone();
        final Calendar beginDate = remove(endDate);
        endDate.add(Calendar.SECOND, -1);
        return Period.between(beginDate, endDate);
    }

    /**
     * Returns a period starting at the given date, with this size
     */
    public Period periodStartingAt(final Calendar beginDate) {
        final Calendar endDate = add(beginDate);
        endDate.add(Calendar.SECOND, -1);
        return Period.between(beginDate, endDate);
    }

    /**
     * Returns the previous full period that does not include the given date. Example: date = 2007-02-15, field = month, number = 2 returns a period
     * of 2 months from 2006-12-01 to 2007-01-31
     */
    public Period previousPeriod(final Calendar date) {
        Calendar end;
        if (field == Field.WEEKS) {
            // Weeks are not supported on DateUtils.truncate, so, go back to the last monday, and get weeks before
            end = DateHelper.truncate(date);
            while (end.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
                end.add(Calendar.DATE, -1);
            }
        } else {
            end = DateUtils.truncate(date, field.getCalendarValue());
        }
        return periodEndingAt(end);
    }

    /**
     * Return a new calendar removing this time period
     */
    public Calendar remove(final Calendar date) {
        if (date == null) {
            return null;
        }
        if (!isValid()) {
            return date;
        }
        final Calendar ret = (Calendar) date.clone();
        ret.add(field.getCalendarValue(), -number);
        return ret;
    }

    public void setField(final Field field) {
        this.field = field;
    }

    public void setNumber(final int number) {
        this.number = number;
    }

    @Override
    public String toString() {
        return number + " " + field;
    }

}