| Frames | No Frames |
1: /* =========================================================== 2: * JFreeChart : a free chart library for the Java(tm) platform 3: * =========================================================== 4: * 5: * (C) Copyright 2000-2006, 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: * Year.java 29: * --------- 30: * (C) Copyright 2001-2006, by Object Refinery Limited. 31: * 32: * Original Author: David Gilbert (for Object Refinery Limited); 33: * Contributor(s): -; 34: * 35: * $Id: Year.java,v 1.9.2.4 2006/10/06 14:00:16 mungady Exp $ 36: * 37: * Changes 38: * ------- 39: * 11-Oct-2001 : Version 1 (DG); 40: * 14-Nov-2001 : Override for toString() method (DG); 41: * 19-Dec-2001 : Added a new constructor as suggested by Paul English (DG); 42: * 29-Jan-2002 : Worked on parseYear() method (DG); 43: * 14-Feb-2002 : Fixed bug in Year(Date) constructor (DG); 44: * 26-Feb-2002 : Changed getStart(), getMiddle() and getEnd() methods to 45: * evaluate with reference to a particular time zone (DG); 46: * 19-Mar-2002 : Changed API for TimePeriod classes (DG); 47: * 10-Sep-2002 : Added getSerialIndex() method (DG); 48: * 04-Oct-2002 : Fixed errors reported by Checkstyle (DG); 49: * 10-Jan-2003 : Changed base class and method names (DG); 50: * 05-Mar-2003 : Fixed bug in getFirstMillisecond() picked up in JUnit 51: * tests (DG); 52: * 13-Mar-2003 : Moved to com.jrefinery.data.time package, and implemented 53: * Serializable (DG); 54: * 21-Oct-2003 : Added hashCode() method (DG); 55: * ------------- JFREECHART 1.0.x --------------------------------------------- 56: * 05-Oct-2006 : Updated API docs (DG); 57: * 06-Oct-2006 : Refactored to cache first and last millisecond values (DG); 58: * 59: */ 60: 61: package org.jfree.data.time; 62: 63: import java.io.Serializable; 64: import java.util.Calendar; 65: import java.util.Date; 66: import java.util.TimeZone; 67: 68: import org.jfree.date.SerialDate; 69: 70: /** 71: * Represents a year in the range 1900 to 9999. This class is immutable, which 72: * is a requirement for all {@link RegularTimePeriod} subclasses. 73: */ 74: public class Year extends RegularTimePeriod implements Serializable { 75: 76: /** For serialization. */ 77: private static final long serialVersionUID = -7659990929736074836L; 78: 79: /** The year. */ 80: private short year; 81: 82: /** The first millisecond. */ 83: private long firstMillisecond; 84: 85: /** The last millisecond. */ 86: private long lastMillisecond; 87: 88: /** 89: * Creates a new <code>Year</code>, based on the current system date/time. 90: */ 91: public Year() { 92: this(new Date()); 93: } 94: 95: /** 96: * Creates a time period representing a single year. 97: * 98: * @param year the year. 99: */ 100: public Year(int year) { 101: if ((year < SerialDate.MINIMUM_YEAR_SUPPORTED) 102: || (year > SerialDate.MAXIMUM_YEAR_SUPPORTED)) { 103: 104: throw new IllegalArgumentException( 105: "Year constructor: year (" + year + ") outside valid range."); 106: } 107: this.year = (short) year; 108: peg(Calendar.getInstance()); 109: } 110: 111: /** 112: * Creates a new <code>Year</code>, based on a particular instant in time, 113: * using the default time zone. 114: * 115: * @param time the time (<code>null</code> not permitted). 116: */ 117: public Year(Date time) { 118: this(time, RegularTimePeriod.DEFAULT_TIME_ZONE); 119: } 120: 121: /** 122: * Constructs a year, based on a particular instant in time and a time zone. 123: * 124: * @param time the time. 125: * @param zone the time zone. 126: */ 127: public Year(Date time, TimeZone zone) { 128: Calendar calendar = Calendar.getInstance(zone); 129: calendar.setTime(time); 130: this.year = (short) calendar.get(Calendar.YEAR); 131: peg(calendar); 132: } 133: 134: /** 135: * Returns the year. 136: * 137: * @return The year. 138: */ 139: public int getYear() { 140: return this.year; 141: } 142: 143: /** 144: * Returns the first millisecond of the year. This will be determined 145: * relative to the time zone specified in the constructor, or in the 146: * calendar instance passed in the most recent call to the 147: * {@link #peg(Calendar)} method. 148: * 149: * @return The first millisecond of the year. 150: * 151: * @see #getLastMillisecond() 152: */ 153: public long getFirstMillisecond() { 154: return this.firstMillisecond; 155: } 156: 157: /** 158: * Returns the last millisecond of the year. This will be 159: * determined relative to the time zone specified in the constructor, or 160: * in the calendar instance passed in the most recent call to the 161: * {@link #peg(Calendar)} method. 162: * 163: * @return The last millisecond of the year. 164: * 165: * @see #getFirstMillisecond() 166: */ 167: public long getLastMillisecond() { 168: return this.lastMillisecond; 169: } 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 void peg(Calendar calendar) { 180: this.firstMillisecond = getFirstMillisecond(calendar); 181: this.lastMillisecond = getLastMillisecond(calendar); 182: } 183: 184: /** 185: * Returns the year preceding this one. 186: * 187: * @return The year preceding this one (or <code>null</code> if the 188: * current year is 1900). 189: */ 190: public RegularTimePeriod previous() { 191: if (this.year > SerialDate.MINIMUM_YEAR_SUPPORTED) { 192: return new Year(this.year - 1); 193: } 194: else { 195: return null; 196: } 197: } 198: 199: /** 200: * Returns the year following this one. 201: * 202: * @return The year following this one (or <code>null</code> if the current 203: * year is 9999). 204: */ 205: public RegularTimePeriod next() { 206: if (this.year < SerialDate.MAXIMUM_YEAR_SUPPORTED) { 207: return new Year(this.year + 1); 208: } 209: else { 210: return null; 211: } 212: } 213: 214: /** 215: * Returns a serial index number for the year. 216: * <P> 217: * The implementation simply returns the year number (e.g. 2002). 218: * 219: * @return The serial index number. 220: */ 221: public long getSerialIndex() { 222: return this.year; 223: } 224: 225: /** 226: * Returns the first millisecond of the year, evaluated using the supplied 227: * calendar (which determines the time zone). 228: * 229: * @param calendar the calendar (<code>null</code> not permitted). 230: * 231: * @return The first millisecond of the year. 232: * 233: * @throws NullPointerException if <code>calendar</code> is 234: * <code>null</code>. 235: */ 236: public long getFirstMillisecond(Calendar calendar) { 237: calendar.set(this.year, Calendar.JANUARY, 1, 0, 0, 0); 238: calendar.set(Calendar.MILLISECOND, 0); 239: // in the following line, we'd rather call calendar.getTimeInMillis() 240: // to avoid object creation, but that isn't supported in Java 1.3.1 241: return calendar.getTime().getTime(); 242: } 243: 244: /** 245: * Returns the last millisecond of the year, evaluated using the supplied 246: * calendar (which determines the time zone). 247: * 248: * @param calendar the calendar (<code>null</code> not permitted). 249: * 250: * @return The last millisecond of the year. 251: * 252: * @throws NullPointerException if <code>calendar</code> is 253: * <code>null</code>. 254: */ 255: public long getLastMillisecond(Calendar calendar) { 256: calendar.set(this.year, Calendar.DECEMBER, 31, 23, 59, 59); 257: calendar.set(Calendar.MILLISECOND, 999); 258: // in the following line, we'd rather call calendar.getTimeInMillis() 259: // to avoid object creation, but that isn't supported in Java 1.3.1 260: return calendar.getTime().getTime(); 261: } 262: 263: /** 264: * Tests the equality of this <code>Year</code> object to an arbitrary 265: * object. Returns <code>true</code> if the target is a <code>Year</code> 266: * instance representing the same year as this object. In all other cases, 267: * returns <code>false</code>. 268: * 269: * @param object the object (<code>null</code> permitted). 270: * 271: * @return <code>true</code> if the year of this and the object are the 272: * same. 273: */ 274: public boolean equals(Object object) { 275: if (object != null) { 276: if (object instanceof Year) { 277: Year target = (Year) object; 278: return (this.year == target.getYear()); 279: } 280: else { 281: return false; 282: } 283: } 284: else { 285: return false; 286: } 287: } 288: 289: /** 290: * Returns a hash code for this object instance. The approach described by 291: * Joshua Bloch in "Effective Java" has been used here: 292: * <p> 293: * <code>http://developer.java.sun.com/developer/Books/effectivejava 294: * /Chapter3.pdf</code> 295: * 296: * @return A hash code. 297: */ 298: public int hashCode() { 299: int result = 17; 300: int c = this.year; 301: result = 37 * result + c; 302: return result; 303: } 304: 305: /** 306: * Returns an integer indicating the order of this <code>Year</code> object 307: * relative to the specified object: 308: * 309: * negative == before, zero == same, positive == after. 310: * 311: * @param o1 the object to compare. 312: * 313: * @return negative == before, zero == same, positive == after. 314: */ 315: public int compareTo(Object o1) { 316: 317: int result; 318: 319: // CASE 1 : Comparing to another Year object 320: // ----------------------------------------- 321: if (o1 instanceof Year) { 322: Year y = (Year) o1; 323: result = this.year - y.getYear(); 324: } 325: 326: // CASE 2 : Comparing to another TimePeriod object 327: // ----------------------------------------------- 328: else if (o1 instanceof RegularTimePeriod) { 329: // more difficult case - evaluate later... 330: result = 0; 331: } 332: 333: // CASE 3 : Comparing to a non-TimePeriod object 334: // --------------------------------------------- 335: else { 336: // consider time periods to be ordered after general objects 337: result = 1; 338: } 339: 340: return result; 341: 342: } 343: 344: /** 345: * Returns a string representing the year.. 346: * 347: * @return A string representing the year. 348: */ 349: public String toString() { 350: return Integer.toString(this.year); 351: } 352: 353: /** 354: * Parses the string argument as a year. 355: * <P> 356: * The string format is YYYY. 357: * 358: * @param s a string representing the year. 359: * 360: * @return <code>null</code> if the string is not parseable, the year 361: * otherwise. 362: */ 363: public static Year parseYear(String s) { 364: 365: // parse the string... 366: int y; 367: try { 368: y = Integer.parseInt(s.trim()); 369: } 370: catch (NumberFormatException e) { 371: throw new TimePeriodFormatException("Cannot parse string."); 372: } 373: 374: // create the year... 375: try { 376: return new Year(y); 377: } 378: catch (IllegalArgumentException e) { 379: throw new TimePeriodFormatException("Year outside valid range."); 380: } 381: } 382: 383: }