    001    /* ===========================================================
    002     * JFreeChart : a free chart library for the Java(tm) platform
    003     * ===========================================================
    004     *
    005     * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
    006     *
    007     * Project Info:  http://www.jfree.org/jfreechart/index.html
    008     *
    009     * This library is free software; you can redistribute it and/or modify it
    010     * under the terms of the GNU Lesser General Public License as published by
    011     * the Free Software Foundation; either version 2.1 of the License, or
    012     * (at your option) any later version.
    013     *
    014     * This library is distributed in the hope that it will be useful, but
    015     * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    016     * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
    017     * License for more details.
    018     *
    019     * You should have received a copy of the GNU Lesser General Public
    020     * License along with this library; if not, write to the Free Software
    021     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
    022     * USA.
    023     *
    024     * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
    025     * in the United States and other countries.]
    026     *
    027     * ----------------------
    028     * RegularTimePeriod.java
    029     * ----------------------
    030     * (C) Copyright 2001-2005, by Object Refinery Limited.
    031     *
    032     * Original Author:  David Gilbert (for Object Refinery Limited);
    033     * Contributor(s):   -;
    034     *
    035     * $Id: RegularTimePeriod.java,v 1.6.2.1 2005/10/25 21:35:24 mungady Exp $
    036     *
    037     * Changes
    038     * -------
    039     * 11-Oct-2001 : Version 1 (DG);
    040     * 26-Feb-2002 : Changed getStart(), getMiddle() and getEnd() methods to
    041     *               evaluate with reference to a particular time zone (DG);
    042     * 29-May-2002 : Implemented MonthConstants interface, so that these constants
    043     *               are conveniently available (DG);
    044     * 10-Sep-2002 : Added getSerialIndex() method (DG);
    045     * 10-Jan-2003 : Renamed TimePeriod --> RegularTimePeriod (DG);
    046     * 13-Mar-2003 : Moved to com.jrefinery.data.time package (DG);
    047     * 29-Apr-2004 : Changed getMiddleMillisecond() methods to fix bug 943985 (DG);
    048     * 25-Nov-2004 : Added utility methods (DG);
    049     *
    050     */
    051
    052    package org.jfree.data.time;
    053
    054    import java.lang.reflect.Constructor;
    055    import java.util.Calendar;
    056    import java.util.Date;
    057    import java.util.TimeZone;
    058
    059    import org.jfree.date.MonthConstants;
    060
    061    /**
    062     * An abstract class representing a unit of time.  Convenient methods are
    063     * provided for calculating the next and previous time periods.  Conversion
    064     * methods are defined that return the first and last milliseconds of the time
    065     * period.  The results from these methods are timezone dependent.
    066     * <P>
    067     * This class is immutable, and all subclasses should be immutable also.
    068     */
    069    public abstract class RegularTimePeriod implements TimePeriod, Comparable,
    070                                                       MonthConstants {
    071
    072        /**
    073         * Creates a time period that includes the specified millisecond, assuming
    074         * the given time zone.
    075         *
    076         * @param c  the time period class.
    077         * @param millisecond  the time.
    078         * @param zone  the time zone.
    079         *
    080         * @return The time period.
    081         */
    082        public static RegularTimePeriod createInstance(Class c, Date millisecond,
    083                                                       TimeZone zone) {
    084            RegularTimePeriod result = null;
    085            try {
    086                Constructor constructor = c.getDeclaredConstructor(
    087                    new Class[] {Date.class, TimeZone.class}
    088                );
    089                result = (RegularTimePeriod) constructor.newInstance(
    090                    new Object[] {millisecond, zone}
    091                );
    092            }
    093            catch (Exception e) {
    094                // do nothing, so null is returned
    095            }
    096            return result;
    097        }
    098
    099        /**
    100         * Returns a subclass of {@link RegularTimePeriod} that is smaller than
    101         * the specified class.
    102         *
    103         * @param c  a subclass of {@link RegularTimePeriod}.
    104         *
    105         * @return A class.
    106         */
    107        public static Class downsize(Class c) {
    108            if (c.equals(Year.class)) {
    109                return Quarter.class;
    110            }
    111            else if (c.equals(Quarter.class)) {
    112                return Month.class;
    113            }
    114            else if (c.equals(Month.class)) {
    115                return Day.class;
    116            }
    117            else if (c.equals(Day.class)) {
    118                return Hour.class;
    119            }
    120            else if (c.equals(Hour.class)) {
    121                return Minute.class;
    122            }
    123            else if (c.equals(Minute.class)) {
    124                return Second.class;
    125            }
    126            else if (c.equals(Second.class)) {
    127                return Millisecond.class;
    128            }
    129            else {
    130                return Millisecond.class;
    131            }
    132        }
    133
    134        /**
    135         * Returns the time period preceding this one, or <code>null</code> if some
    136         * lower limit has been reached.
    137         *
    138         * @return The previous time period (possibly <code>null</code>).
    139         */
    140        public abstract RegularTimePeriod previous();
    141
    142        /**
    143         * Returns the time period following this one, or <code>null</code> if some
    144         * limit has been reached.
    145         *
    146         * @return The next time period (possibly <code>null</code>).
    147         */
    148        public abstract RegularTimePeriod next();
    149
    150        /**
    151         * Returns a serial index number for the time unit.
    152         *
    153         * @return The serial index number.
    154         */
    155        public abstract long getSerialIndex();
    156
    157        //////////////////////////////////////////////////////////////////////////
    158
    159        /** The default time zone. */
    160        public static final TimeZone DEFAULT_TIME_ZONE = TimeZone.getDefault();
    161
    162        /** A working calendar (recycle to avoid unnecessary object creation). */
    163        public static final Calendar WORKING_CALENDAR
    164            = Calendar.getInstance(DEFAULT_TIME_ZONE);
    165
    166        /**
    167         * Returns the date/time that marks the start of the time period.
    168         *
    169         * @return The start date/time.
    170         */
    171        public Date getStart() {
    172            return new Date(getFirstMillisecond());
    173        }
    174
    175        /**
    176         * Returns the date/time that marks the end of the time period.
    177         *
    178         * @return The end date/time.
    179         */
    180        public Date getEnd() {
    181            return new Date(getLastMillisecond());
    182        }
    183
    184        /**
    185         * Returns the first millisecond of the time period, evaluated in the
    186         * default time zone.
    187         *
    188         * @return The first millisecond of the time period.
    189         */
    190        public long getFirstMillisecond() {
    191            return getFirstMillisecond(DEFAULT_TIME_ZONE);
    192        }
    193
    194        /**
    195         * Returns the first millisecond of the time period, evaluated within a
    196         * specific time zone.
    197         *
    198         * @param zone  the time zone.
    199         *
    200         * @return The first millisecond of the time period.
    201         */
    202        public long getFirstMillisecond(TimeZone zone) {
    203            WORKING_CALENDAR.setTimeZone(zone);
    204            return getFirstMillisecond(WORKING_CALENDAR);
    205        }
    206
    207        /**
    208         * Returns the first millisecond of the time period, evaluated using the
    209         * supplied calendar (which incorporates a timezone).
    210         *
    211         * @param calendar  the calendar.
    212         *
    213         * @return The first millisecond of the time period.
    214         */
    215        public abstract long getFirstMillisecond(Calendar calendar);
    216
    217        /**
    218         * Returns the last millisecond of the time period, evaluated in the
    219         * default time zone.
    220         *
    221         * @return The last millisecond of the time period.
    222         */
    223        public long getLastMillisecond() {
    224            return getLastMillisecond(DEFAULT_TIME_ZONE);
    225        }
    226
    227        /**
    228         * Returns the last millisecond of the time period, evaluated within a
    229         * specific time zone.
    230         *
    231         * @param zone  the time zone.
    232         *
    233         * @return The last millisecond of the time period.
    234         */
    235        public long getLastMillisecond(TimeZone zone) {
    236            WORKING_CALENDAR.setTimeZone(zone);
    237            return getLastMillisecond(WORKING_CALENDAR);
    238        }
    239
    240        /**
    241         * Returns the last millisecond of the time period, evaluated using the
    242         * supplied calendar (which incorporates a timezone).
    243         *
    244         * @param calendar  the calendar.
    245         *
    246         * @return The last millisecond of the time period.
    247         */
    248        public abstract long getLastMillisecond(Calendar calendar);
    249
    250        /**
    251         * Returns the millisecond closest to the middle of the time period,
    252         * evaluated in the default time zone.
    253         *
    254         * @return The middle millisecond.
    255         */
    256        public long getMiddleMillisecond() {
    257            long m1 = getFirstMillisecond();
    258            long m2 = getLastMillisecond();
    259            return m1 + (m2 - m1) / 2;
    260        }
    261
    262        /**
    263         * Returns the millisecond closest to the middle of the time period,
    264         * evaluated within a specific time zone.
    265         *
    266         * @param zone  the time zone.
    267         *
    268         * @return The middle millisecond.
    269         */
    270        public long getMiddleMillisecond(TimeZone zone) {
    271            long m1 = getFirstMillisecond(zone);
    272            long m2 = getLastMillisecond(zone);
    273            return m1 + (m2 - m1) / 2;
    274        }
    275
    276        /**
    277         * Returns the millisecond closest to the middle of the time period,
    278         * evaluated using the supplied calendar (which incorporates a timezone).
    279         *
    280         * @param calendar  the calendar.
    281         *
    282         * @return The middle millisecond.
    283         */
    284        public long getMiddleMillisecond(Calendar calendar) {
    285            long m1 = getFirstMillisecond(calendar);
    286            long m2 = getLastMillisecond(calendar);
    287            return m1 + (m2 - m1) / 2;
    288        }
    289
    290        /**
    291         * Returns a string representation of the time period.
    292         *
    293         * @return The string.
    294         */
    295        public String toString() {
    296            return String.valueOf(getStart());
    297        }
    298
    299    }