Frames | No Frames |
1: /* =========================================================== 2: * JFreeChart : a free chart library for the Java(tm) platform 3: * =========================================================== 4: * 5: * (C) Copyright 2000-2005, 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: * Hour.java 29: * --------- 30: * (C) Copyright 2001-2004, by Object Refinery Limited. 31: * 32: * Original Author: David Gilbert (for Object Refinery Limited); 33: * Contributor(s): -; 34: * 35: * $Id: Hour.java,v 1.5.2.1 2005/10/25 21:35:24 mungady Exp $ 36: * 37: * Changes 38: * ------- 39: * 11-Oct-2001 : Version 1 (DG); 40: * 18-Dec-2001 : Changed order of parameters in constructor (DG); 41: * 19-Dec-2001 : Added a new constructor as suggested by Paul English (DG); 42: * 14-Feb-2002 : Fixed bug in Hour(Date) constructor (DG); 43: * 26-Feb-2002 : Changed getStart(), getMiddle() and getEnd() methods to 44: * evaluate with reference to a particular time zone (DG); 45: * 15-Mar-2002 : Changed API (DG); 46: * 16-Apr-2002 : Fixed small time zone bug in constructor (DG); 47: * 10-Sep-2002 : Added getSerialIndex() method (DG); 48: * 07-Oct-2002 : Fixed errors reported by Checkstyle (DG); 49: * 10-Jan-2003 : Changed base class and method names (DG); 50: * 13-Mar-2003 : Moved to com.jrefinery.data.time package, and implemented 51: * Serializable (DG); 52: * 21-Oct-2003 : Added hashCode() method, and new constructor for 53: * convenience (DG); 54: * 30-Sep-2004 : Replaced getTime().getTime() with getTimeInMillis() (DG); 55: * 04-Nov-2004 : Reverted change of 30-Sep-2004, because it won't work for 56: * JDK 1.3 (DG); 57: * 58: */ 59: 60: package org.jfree.data.time; 61: 62: import java.io.Serializable; 63: import java.util.Calendar; 64: import java.util.Date; 65: import java.util.TimeZone; 66: 67: /** 68: * Represents an hour in a specific day. This class is immutable, which is a 69: * requirement for all {@link RegularTimePeriod} subclasses. 70: */ 71: public class Hour extends RegularTimePeriod implements Serializable { 72: 73: /** For serialization. */ 74: private static final long serialVersionUID = -835471579831937652L; 75: 76: /** Useful constant for the first hour in the day. */ 77: public static final int FIRST_HOUR_IN_DAY = 0; 78: 79: /** Useful constant for the last hour in the day. */ 80: public static final int LAST_HOUR_IN_DAY = 23; 81: 82: /** The day. */ 83: private Day day; 84: 85: /** The hour. */ 86: private int hour; 87: 88: /** 89: * Constructs a new Hour, based on the system date/time. 90: */ 91: public Hour() { 92: this(new Date()); 93: } 94: 95: /** 96: * Constructs a new Hour. 97: * 98: * @param hour the hour (in the range 0 to 23). 99: * @param day the day (<code>null</code> not permitted). 100: */ 101: public Hour(int hour, Day day) { 102: if (day == null) { 103: throw new IllegalArgumentException("Null 'day' argument."); 104: } 105: this.hour = hour; 106: this.day = day; 107: } 108: 109: /** 110: * Creates a new hour. 111: * 112: * @param hour the hour (0-23). 113: * @param day the day (1-31). 114: * @param month the month (1-12). 115: * @param year the year (1900-9999). 116: */ 117: public Hour(int hour, int day, int month, int year) { 118: this(hour, new Day(day, month, year)); 119: } 120: 121: /** 122: * Constructs a new Hour, based on the supplied date/time. 123: * 124: * @param time the date-time (<code>null</code> not permitted). 125: */ 126: public Hour(Date time) { 127: // defer argument checking... 128: this(time, RegularTimePeriod.DEFAULT_TIME_ZONE); 129: } 130: 131: /** 132: * Constructs a new Hour, based on the supplied date/time evaluated in the 133: * specified time zone. 134: * 135: * @param time the date-time (<code>null</code> not permitted). 136: * @param zone the time zone (<code>null</code> not permitted). 137: */ 138: public Hour(Date time, TimeZone zone) { 139: if (time == null) { 140: throw new IllegalArgumentException("Null 'time' argument."); 141: } 142: if (zone == null) { 143: throw new IllegalArgumentException("Null 'zone' argument."); 144: } 145: Calendar calendar = Calendar.getInstance(zone); 146: calendar.setTime(time); 147: this.hour = calendar.get(Calendar.HOUR_OF_DAY); 148: this.day = new Day(time, zone); 149: } 150: 151: /** 152: * Returns the hour. 153: * 154: * @return The hour (0 <= hour <= 23). 155: */ 156: public int getHour() { 157: return this.hour; 158: } 159: 160: /** 161: * Returns the day in which this hour falls. 162: * 163: * @return The day. 164: */ 165: public Day getDay() { 166: return this.day; 167: } 168: 169: /** 170: * Returns the year in which this hour falls. 171: * 172: * @return The year. 173: */ 174: public int getYear() { 175: return this.day.getYear(); 176: } 177: 178: /** 179: * Returns the month in which this hour falls. 180: * 181: * @return The month. 182: */ 183: public int getMonth() { 184: return this.day.getMonth(); 185: } 186: 187: /** 188: * Returns the day-of-the-month in which this hour falls. 189: * 190: * @return The day-of-the-month. 191: */ 192: public int getDayOfMonth() { 193: return this.day.getDayOfMonth(); 194: } 195: 196: /** 197: * Returns the hour preceding this one. 198: * 199: * @return The hour preceding this one. 200: */ 201: public RegularTimePeriod previous() { 202: 203: Hour result; 204: if (this.hour != FIRST_HOUR_IN_DAY) { 205: result = new Hour(this.hour - 1, this.day); 206: } 207: else { // we are at the first hour in the day... 208: Day prevDay = (Day) this.day.previous(); 209: if (prevDay != null) { 210: result = new Hour(LAST_HOUR_IN_DAY, prevDay); 211: } 212: else { 213: result = null; 214: } 215: } 216: return result; 217: 218: } 219: 220: /** 221: * Returns the hour following this one. 222: * 223: * @return The hour following this one. 224: */ 225: public RegularTimePeriod next() { 226: 227: Hour result; 228: if (this.hour != LAST_HOUR_IN_DAY) { 229: result = new Hour(this.hour + 1, this.day); 230: } 231: else { // we are at the last hour in the day... 232: Day nextDay = (Day) this.day.next(); 233: if (nextDay != null) { 234: result = new Hour(FIRST_HOUR_IN_DAY, nextDay); 235: } 236: else { 237: result = null; 238: } 239: } 240: return result; 241: 242: } 243: 244: /** 245: * Returns a serial index number for the hour. 246: * 247: * @return The serial index number. 248: */ 249: public long getSerialIndex() { 250: return this.day.getSerialIndex() * 24L + this.hour; 251: } 252: 253: /** 254: * Returns the first millisecond of the hour. 255: * 256: * @param calendar the calendar/timezone. 257: * 258: * @return The first millisecond. 259: */ 260: public long getFirstMillisecond(Calendar calendar) { 261: 262: int year = this.day.getYear(); 263: int month = this.day.getMonth() - 1; 264: int dom = this.day.getDayOfMonth(); 265: 266: calendar.set(year, month, dom, this.hour, 0, 0); 267: calendar.set(Calendar.MILLISECOND, 0); 268: 269: //return calendar.getTimeInMillis(); // this won't work for JDK 1.3 270: return calendar.getTime().getTime(); 271: 272: } 273: 274: /** 275: * Returns the last millisecond of the hour. 276: * 277: * @param calendar the calendar/timezone. 278: * 279: * @return The last millisecond. 280: */ 281: public long getLastMillisecond(Calendar calendar) { 282: 283: int year = this.day.getYear(); 284: int month = this.day.getMonth() - 1; 285: int dom = this.day.getDayOfMonth(); 286: 287: calendar.set(year, month, dom, this.hour, 59, 59); 288: calendar.set(Calendar.MILLISECOND, 999); 289: 290: //return calendar.getTimeInMillis(); // this won't work for JDK 1.3 291: return calendar.getTime().getTime(); 292: 293: } 294: 295: /** 296: * Tests the equality of this object against an arbitrary Object. 297: * <P> 298: * This method will return true ONLY if the object is an Hour object 299: * representing the same hour as this instance. 300: * 301: * @param obj the object to compare (<code>null</code> permitted). 302: * 303: * @return <code>true</code> if the hour and day value of the object 304: * is the same as this. 305: */ 306: public boolean equals(Object obj) { 307: if (obj == this) { 308: return true; 309: } 310: if (!(obj instanceof Hour)) { 311: return false; 312: } 313: Hour that = (Hour) obj; 314: if (this.hour != that.hour) { 315: return false; 316: } 317: if (!this.day.equals(that.day)) { 318: return false; 319: } 320: return true; 321: } 322: 323: /** 324: * Returns a hash code for this object instance. The approach described by 325: * Joshua Bloch in "Effective Java" has been used here: 326: * <p> 327: * <code>http://developer.java.sun.com/developer/Books/effectivejava 328: * /Chapter3.pdf</code> 329: * 330: * @return A hash code. 331: */ 332: public int hashCode() { 333: int result = 17; 334: result = 37 * result + this.hour; 335: result = 37 * result + this.day.hashCode(); 336: return result; 337: } 338: 339: /** 340: * Returns an integer indicating the order of this Hour object relative to 341: * the specified object: 342: * 343: * negative == before, zero == same, positive == after. 344: * 345: * @param o1 the object to compare. 346: * 347: * @return negative == before, zero == same, positive == after. 348: */ 349: public int compareTo(Object o1) { 350: 351: int result; 352: 353: // CASE 1 : Comparing to another Hour object 354: // ----------------------------------------- 355: if (o1 instanceof Hour) { 356: Hour h = (Hour) o1; 357: result = getDay().compareTo(h.getDay()); 358: if (result == 0) { 359: result = this.hour - h.getHour(); 360: } 361: } 362: 363: // CASE 2 : Comparing to another TimePeriod object 364: // ----------------------------------------------- 365: else if (o1 instanceof RegularTimePeriod) { 366: // more difficult case - evaluate later... 367: result = 0; 368: } 369: 370: // CASE 3 : Comparing to a non-TimePeriod object 371: // --------------------------------------------- 372: else { 373: // consider time periods to be ordered after general objects 374: result = 1; 375: } 376: 377: return result; 378: 379: } 380: 381: /** 382: * Creates an Hour instance by parsing a string. The string is assumed to 383: * be in the format "YYYY-MM-DD HH", perhaps with leading or trailing 384: * whitespace. 385: * 386: * @param s the hour string to parse. 387: * 388: * @return <code>null</code> if the string is not parseable, the hour 389: * otherwise. 390: */ 391: public static Hour parseHour(String s) { 392: 393: Hour result = null; 394: s = s.trim(); 395: 396: String daystr = s.substring(0, Math.min(10, s.length())); 397: Day day = Day.parseDay(daystr); 398: if (day != null) { 399: String hourstr = s.substring( 400: Math.min(daystr.length() + 1, s.length()), s.length() 401: ); 402: hourstr = hourstr.trim(); 403: int hour = Integer.parseInt(hourstr); 404: // if the hour is 0 - 23 then create an hour 405: if ((hour >= FIRST_HOUR_IN_DAY) && (hour <= LAST_HOUR_IN_DAY)) { 406: result = new Hour(hour, day); 407: } 408: } 409: 410: return result; 411: 412: } 413: 414: }