Frames | No Frames |
1: /* =========================================================== 2: * JFreeChart : a free chart library for the Java(tm) platform 3: * =========================================================== 4: * 5: * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors. 6: * 7: * Project Info: http://www.jfree.org/jfreechart/index.html 8: * 9: * This library is free software; you can redistribute it and/or modify it 10: * under the terms of the GNU Lesser General Public License as published by 11: * the Free Software Foundation; either version 2.1 of the License, or 12: * (at your option) any later version. 13: * 14: * This library is distributed in the hope that it will be useful, but 15: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 17: * License for more details. 18: * 19: * You should have received a copy of the GNU Lesser General Public 20: * License along with this library; if not, write to the Free Software 21: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 22: * USA. 23: * 24: * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 25: * in the United States and other countries.] 26: * 27: * ---------------------- 28: * RegularTimePeriod.java 29: * ---------------------- 30: * (C) Copyright 2001-2007, by Object Refinery Limited. 31: * 32: * Original Author: David Gilbert (for Object Refinery Limited); 33: * Contributor(s): -; 34: * 35: * Changes 36: * ------- 37: * 11-Oct-2001 : Version 1 (DG); 38: * 26-Feb-2002 : Changed getStart(), getMiddle() and getEnd() methods to 39: * evaluate with reference to a particular time zone (DG); 40: * 29-May-2002 : Implemented MonthConstants interface, so that these constants 41: * are conveniently available (DG); 42: * 10-Sep-2002 : Added getSerialIndex() method (DG); 43: * 10-Jan-2003 : Renamed TimePeriod --> RegularTimePeriod (DG); 44: * 13-Mar-2003 : Moved to com.jrefinery.data.time package (DG); 45: * 29-Apr-2004 : Changed getMiddleMillisecond() methods to fix bug 943985 (DG); 46: * 25-Nov-2004 : Added utility methods (DG); 47: * ------------- JFREECHART 1.0.x --------------------------------------------- 48: * 06-Oct-2006 : Deprecated the WORKING_CALENDAR field and several methods, 49: * added new peg() method (DG); 50: * 51: */ 52: 53: package org.jfree.data.time; 54: 55: import java.lang.reflect.Constructor; 56: import java.util.Calendar; 57: import java.util.Date; 58: import java.util.TimeZone; 59: 60: import org.jfree.date.MonthConstants; 61: 62: /** 63: * An abstract class representing a unit of time. Convenient methods are 64: * provided for calculating the next and previous time periods. Conversion 65: * methods are defined that return the first and last milliseconds of the time 66: * period. The results from these methods are timezone dependent. 67: * <P> 68: * This class is immutable, and all subclasses should be immutable also. 69: */ 70: public abstract class RegularTimePeriod implements TimePeriod, Comparable, 71: MonthConstants { 72: 73: /** 74: * Creates a time period that includes the specified millisecond, assuming 75: * the given time zone. 76: * 77: * @param c the time period class. 78: * @param millisecond the time. 79: * @param zone the time zone. 80: * 81: * @return The time period. 82: */ 83: public static RegularTimePeriod createInstance(Class c, Date millisecond, 84: TimeZone zone) { 85: RegularTimePeriod result = null; 86: try { 87: Constructor constructor = c.getDeclaredConstructor( 88: new Class[] {Date.class, TimeZone.class}); 89: result = (RegularTimePeriod) constructor.newInstance( 90: new Object[] {millisecond, zone}); 91: } 92: catch (Exception e) { 93: // do nothing, so null is returned 94: } 95: return result; 96: } 97: 98: /** 99: * Returns a subclass of {@link RegularTimePeriod} that is smaller than 100: * the specified class. 101: * 102: * @param c a subclass of {@link RegularTimePeriod}. 103: * 104: * @return A class. 105: */ 106: public static Class downsize(Class c) { 107: if (c.equals(Year.class)) { 108: return Quarter.class; 109: } 110: else if (c.equals(Quarter.class)) { 111: return Month.class; 112: } 113: else if (c.equals(Month.class)) { 114: return Day.class; 115: } 116: else if (c.equals(Day.class)) { 117: return Hour.class; 118: } 119: else if (c.equals(Hour.class)) { 120: return Minute.class; 121: } 122: else if (c.equals(Minute.class)) { 123: return Second.class; 124: } 125: else if (c.equals(Second.class)) { 126: return Millisecond.class; 127: } 128: else { 129: return Millisecond.class; 130: } 131: } 132: 133: /** 134: * Returns the time period preceding this one, or <code>null</code> if some 135: * lower limit has been reached. 136: * 137: * @return The previous time period (possibly <code>null</code>). 138: */ 139: public abstract RegularTimePeriod previous(); 140: 141: /** 142: * Returns the time period following this one, or <code>null</code> if some 143: * limit has been reached. 144: * 145: * @return The next time period (possibly <code>null</code>). 146: */ 147: public abstract RegularTimePeriod next(); 148: 149: /** 150: * Returns a serial index number for the time unit. 151: * 152: * @return The serial index number. 153: */ 154: public abstract long getSerialIndex(); 155: 156: ////////////////////////////////////////////////////////////////////////// 157: 158: /** 159: * The default time zone. 160: */ 161: public static final TimeZone DEFAULT_TIME_ZONE = TimeZone.getDefault(); 162: 163: /** 164: * A working calendar (recycle to avoid unnecessary object creation). 165: * 166: * @deprecated This was a bad idea, don't use it! 167: */ 168: public static final Calendar WORKING_CALENDAR 169: = Calendar.getInstance(DEFAULT_TIME_ZONE); 170: 171: /** 172: * Recalculates the start date/time and end date/time for this time period 173: * relative to the supplied calendar (which incorporates a time zone). 174: * 175: * @param calendar the calendar (<code>null</code> not permitted). 176: * 177: * @since 1.0.3 178: */ 179: public abstract void peg(Calendar calendar); 180: 181: /** 182: * Returns the date/time that marks the start of the time period. This 183: * method returns a new <code>Date</code> instance every time it is called. 184: * 185: * @return The start date/time. 186: * 187: * @see #getFirstMillisecond() 188: */ 189: public Date getStart() { 190: return new Date(getFirstMillisecond()); 191: } 192: 193: /** 194: * Returns the date/time that marks the end of the time period. This 195: * method returns a new <code>Date</code> instance every time it is called. 196: * 197: * @return The end date/time. 198: * 199: * @see #getLastMillisecond() 200: */ 201: public Date getEnd() { 202: return new Date(getLastMillisecond()); 203: } 204: 205: /** 206: * Returns the first millisecond of the time period. This will be 207: * determined relative to the time zone specified in the constructor, or 208: * in the calendar instance passed in the most recent call to the 209: * {@link #peg(Calendar)} method. 210: * 211: * @return The first millisecond of the time period. 212: * 213: * @see #getLastMillisecond() 214: */ 215: public abstract long getFirstMillisecond(); 216: 217: /** 218: * Returns the first millisecond of the time period, evaluated within a 219: * specific time zone. 220: * 221: * @param zone the time zone (<code>null</code> not permitted). 222: * 223: * @return The first millisecond of the time period. 224: * 225: * @deprecated As of 1.0.3, you should avoid using this method (it creates 226: * a new Calendar instance every time it is called). You are advised 227: * to call {@link #getFirstMillisecond(Calendar)} instead. 228: * 229: * @see #getLastMillisecond(TimeZone) 230: */ 231: public long getFirstMillisecond(TimeZone zone) { 232: Calendar calendar = Calendar.getInstance(zone); 233: return getFirstMillisecond(calendar); 234: } 235: 236: /** 237: * Returns the first millisecond of the time period, evaluated using the 238: * supplied calendar (which incorporates a timezone). 239: * 240: * @param calendar the calendar (<code>null</code> not permitted). 241: * 242: * @return The first millisecond of the time period. 243: * 244: * @throws NullPointerException if <code>calendar,/code> is 245: * </code>null</code>. 246: * 247: * @see #getLastMillisecond(Calendar) 248: */ 249: public abstract long getFirstMillisecond(Calendar calendar); 250: 251: /** 252: * Returns the last millisecond of the time period. This will be 253: * determined relative to the time zone specified in the constructor, or 254: * in the calendar instance passed in the most recent call to the 255: * {@link #peg(Calendar)} method. 256: * 257: * @return The last millisecond of the time period. 258: * 259: * @see #getFirstMillisecond() 260: */ 261: public abstract long getLastMillisecond(); 262: 263: /** 264: * Returns the last millisecond of the time period, evaluated within a 265: * specific time zone. 266: * 267: * @param zone the time zone (<code>null</code> not permitted). 268: * 269: * @return The last millisecond of the time period. 270: * 271: * @deprecated As of 1.0.3, you should avoid using this method (it creates 272: * a new Calendar instance every time it is called). You are advised 273: * to call {@link #getLastMillisecond(Calendar)} instead. 274: * 275: * @see #getFirstMillisecond(TimeZone) 276: */ 277: public long getLastMillisecond(TimeZone zone) { 278: Calendar calendar = Calendar.getInstance(zone); 279: return getLastMillisecond(calendar); 280: } 281: 282: /** 283: * Returns the last millisecond of the time period, evaluated using the 284: * supplied calendar (which incorporates a timezone). 285: * 286: * @param calendar the calendar (<code>null</code> not permitted). 287: * 288: * @return The last millisecond of the time period. 289: * 290: * @see #getFirstMillisecond(Calendar) 291: */ 292: public abstract long getLastMillisecond(Calendar calendar); 293: 294: /** 295: * Returns the millisecond closest to the middle of the time period. 296: * 297: * @return The middle millisecond. 298: */ 299: public long getMiddleMillisecond() { 300: long m1 = getFirstMillisecond(); 301: long m2 = getLastMillisecond(); 302: return m1 + (m2 - m1) / 2; 303: } 304: 305: /** 306: * Returns the millisecond closest to the middle of the time period, 307: * evaluated within a specific time zone. 308: * 309: * @param zone the time zone (<code>null</code> not permitted). 310: * 311: * @return The middle millisecond. 312: * 313: * @deprecated As of 1.0.3, you should avoid using this method (it creates 314: * a new Calendar instance every time it is called). You are advised 315: * to call {@link #getMiddleMillisecond(Calendar)} instead. 316: */ 317: public long getMiddleMillisecond(TimeZone zone) { 318: Calendar calendar = Calendar.getInstance(zone); 319: long m1 = getFirstMillisecond(calendar); 320: long m2 = getLastMillisecond(calendar); 321: return m1 + (m2 - m1) / 2; 322: } 323: 324: /** 325: * Returns the millisecond closest to the middle of the time period, 326: * evaluated using the supplied calendar (which incorporates a timezone). 327: * 328: * @param calendar the calendar. 329: * 330: * @return The middle millisecond. 331: */ 332: public long getMiddleMillisecond(Calendar calendar) { 333: long m1 = getFirstMillisecond(calendar); 334: long m2 = getLastMillisecond(calendar); 335: return m1 + (m2 - m1) / 2; 336: } 337: 338: /** 339: * Returns a string representation of the time period. 340: * 341: * @return The string. 342: */ 343: public String toString() { 344: return String.valueOf(getStart()); 345: } 346: 347: }