Frames | No Frames |
1: /* =========================================================== 2: * JFreeChart : a free chart library for the Java(tm) platform 3: * =========================================================== 4: * 5: * (C) Copyright 2000-2008, 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: * Millisecond.java 29: * ---------------- 30: * (C) Copyright 2001-2008, 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: * 19-Dec-2001 : Added new constructors as suggested by Paul English (DG); 39: * 26-Feb-2002 : Added new getStart() and getEnd() methods (DG); 40: * 29-Mar-2002 : Fixed bug in getStart(), getEnd() and compareTo() methods (DG); 41: * 10-Sep-2002 : Added getSerialIndex() method (DG); 42: * 07-Oct-2002 : Fixed errors reported by Checkstyle (DG); 43: * 10-Jan-2003 : Changed base class and method names (DG); 44: * 13-Mar-2003 : Moved to com.jrefinery.data.time package and implemented 45: * Serializable (DG); 46: * 21-Oct-2003 : Added hashCode() method (DG); 47: * ------------- JFREECHART 1.0.x --------------------------------------------- 48: * 05-Oct-2006 : Updated API docs (DG); 49: * 06-Oct-2006 : Refactored to cache first and last millisecond values (DG); 50: * 04-Apr-2007 : In Millisecond(Date, TimeZone), peg milliseconds to the 51: * specified zone (DG); 52: * 06-Jun-2008 : Added handling for general RegularTimePeriod in compareTo() 53: * method: 54: * see http://www.jfree.org/phpBB2/viewtopic.php?t=24805 (DG); 55: * 56: */ 57: 58: package org.jfree.data.time; 59: 60: import java.io.Serializable; 61: import java.util.Calendar; 62: import java.util.Date; 63: import java.util.TimeZone; 64: 65: /** 66: * Represents a millisecond. This class is immutable, which is a requirement 67: * for all {@link RegularTimePeriod} subclasses. 68: */ 69: public class Millisecond extends RegularTimePeriod implements Serializable { 70: 71: /** For serialization. */ 72: static final long serialVersionUID = -5316836467277638485L; 73: 74: /** A constant for the first millisecond in a second. */ 75: public static final int FIRST_MILLISECOND_IN_SECOND = 0; 76: 77: /** A constant for the last millisecond in a second. */ 78: public static final int LAST_MILLISECOND_IN_SECOND = 999; 79: 80: /** The day. */ 81: private Day day; 82: 83: /** The hour in the day. */ 84: private byte hour; 85: 86: /** The minute. */ 87: private byte minute; 88: 89: /** The second. */ 90: private byte second; 91: 92: /** The millisecond. */ 93: private int millisecond; 94: 95: /** 96: * The pegged millisecond. 97: */ 98: private long firstMillisecond; 99: 100: /** 101: * Constructs a millisecond based on the current system time. 102: */ 103: public Millisecond() { 104: this(new Date()); 105: } 106: 107: /** 108: * Constructs a millisecond. 109: * 110: * @param millisecond the millisecond (0-999). 111: * @param second the second. 112: */ 113: public Millisecond(int millisecond, Second second) { 114: this.millisecond = millisecond; 115: this.second = (byte) second.getSecond(); 116: this.minute = (byte) second.getMinute().getMinute(); 117: this.hour = (byte) second.getMinute().getHourValue(); 118: this.day = second.getMinute().getDay(); 119: peg(Calendar.getInstance()); 120: } 121: 122: /** 123: * Creates a new millisecond. 124: * 125: * @param millisecond the millisecond (0-999). 126: * @param second the second (0-59). 127: * @param minute the minute (0-59). 128: * @param hour the hour (0-23). 129: * @param day the day (1-31). 130: * @param month the month (1-12). 131: * @param year the year (1900-9999). 132: */ 133: public Millisecond(int millisecond, int second, int minute, int hour, 134: int day, int month, int year) { 135: 136: this(millisecond, new Second(second, minute, hour, day, month, year)); 137: 138: } 139: 140: /** 141: * Constructs a millisecond. 142: * 143: * @param time the time. 144: */ 145: public Millisecond(Date time) { 146: this(time, RegularTimePeriod.DEFAULT_TIME_ZONE); 147: } 148: 149: /** 150: * Creates a millisecond. 151: * 152: * @param time the instant in time. 153: * @param zone the time zone. 154: */ 155: public Millisecond(Date time, TimeZone zone) { 156: Calendar calendar = Calendar.getInstance(zone); 157: calendar.setTime(time); 158: this.millisecond = calendar.get(Calendar.MILLISECOND); 159: this.second = (byte) calendar.get(Calendar.SECOND); 160: this.minute = (byte) calendar.get(Calendar.MINUTE); 161: this.hour = (byte) calendar.get(Calendar.HOUR_OF_DAY); 162: this.day = new Day(time, zone); 163: peg(calendar); 164: } 165: 166: /** 167: * Returns the second. 168: * 169: * @return The second. 170: */ 171: public Second getSecond() { 172: return new Second(this.second, this.minute, this.hour, 173: this.day.getDayOfMonth(), this.day.getMonth(), 174: this.day.getYear()); 175: } 176: 177: /** 178: * Returns the millisecond. 179: * 180: * @return The millisecond. 181: */ 182: public long getMillisecond() { 183: return this.millisecond; 184: } 185: 186: /** 187: * Returns the first millisecond of the second. This will be determined 188: * relative to the time zone specified in the constructor, or in the 189: * calendar instance passed in the most recent call to the 190: * {@link #peg(Calendar)} method. 191: * 192: * @return The first millisecond of the second. 193: * 194: * @see #getLastMillisecond() 195: */ 196: public long getFirstMillisecond() { 197: return this.firstMillisecond; 198: } 199: 200: /** 201: * Returns the last millisecond of the second. This will be 202: * determined relative to the time zone specified in the constructor, or 203: * in the calendar instance passed in the most recent call to the 204: * {@link #peg(Calendar)} method. 205: * 206: * @return The last millisecond of the second. 207: * 208: * @see #getFirstMillisecond() 209: */ 210: public long getLastMillisecond() { 211: return this.firstMillisecond; 212: } 213: 214: /** 215: * Recalculates the start date/time and end date/time for this time period 216: * relative to the supplied calendar (which incorporates a time zone). 217: * 218: * @param calendar the calendar (<code>null</code> not permitted). 219: * 220: * @since 1.0.3 221: */ 222: public void peg(Calendar calendar) { 223: this.firstMillisecond = getFirstMillisecond(calendar); 224: } 225: 226: /** 227: * Returns the millisecond preceding this one. 228: * 229: * @return The millisecond preceding this one. 230: */ 231: public RegularTimePeriod previous() { 232: 233: RegularTimePeriod result = null; 234: 235: if (this.millisecond != FIRST_MILLISECOND_IN_SECOND) { 236: result = new Millisecond(this.millisecond - 1, getSecond()); 237: } 238: else { 239: Second previous = (Second) getSecond().previous(); 240: if (previous != null) { 241: result = new Millisecond(LAST_MILLISECOND_IN_SECOND, previous); 242: } 243: } 244: return result; 245: 246: } 247: 248: /** 249: * Returns the millisecond following this one. 250: * 251: * @return The millisecond following this one. 252: */ 253: public RegularTimePeriod next() { 254: 255: RegularTimePeriod result = null; 256: if (this.millisecond != LAST_MILLISECOND_IN_SECOND) { 257: result = new Millisecond(this.millisecond + 1, getSecond()); 258: } 259: else { 260: Second next = (Second) getSecond().next(); 261: if (next != null) { 262: result = new Millisecond(FIRST_MILLISECOND_IN_SECOND, next); 263: } 264: } 265: return result; 266: 267: } 268: 269: /** 270: * Returns a serial index number for the millisecond. 271: * 272: * @return The serial index number. 273: */ 274: public long getSerialIndex() { 275: long hourIndex = this.day.getSerialIndex() * 24L + this.hour; 276: long minuteIndex = hourIndex * 60L + this.minute; 277: long secondIndex = minuteIndex * 60L + this.second; 278: return secondIndex * 1000L + this.millisecond; 279: } 280: 281: /** 282: * Tests the equality of this object against an arbitrary Object. 283: * <P> 284: * This method will return true ONLY if the object is a Millisecond object 285: * representing the same millisecond as this instance. 286: * 287: * @param obj the object to compare 288: * 289: * @return <code>true</code> if milliseconds and seconds of this and object 290: * are the same. 291: */ 292: public boolean equals(Object obj) { 293: if (obj == this) { 294: return true; 295: } 296: if (!(obj instanceof Millisecond)) { 297: return false; 298: } 299: Millisecond that = (Millisecond) obj; 300: if (this.millisecond != that.millisecond) { 301: return false; 302: } 303: if (this.second != that.second) { 304: return false; 305: } 306: if (this.minute != that.minute) { 307: return false; 308: } 309: if (this.hour != that.hour) { 310: return false; 311: } 312: if (!this.day.equals(that.day)) { 313: return false; 314: } 315: return true; 316: } 317: 318: /** 319: * Returns a hash code for this object instance. The approach described by 320: * Joshua Bloch in "Effective Java" has been used here: 321: * <p> 322: * <code>http://developer.java.sun.com/developer/Books/effectivejava 323: * /Chapter3.pdf</code> 324: * 325: * @return A hashcode. 326: */ 327: public int hashCode() { 328: int result = 17; 329: result = 37 * result + this.millisecond; 330: result = 37 * result + getSecond().hashCode(); 331: return result; 332: } 333: 334: /** 335: * Returns an integer indicating the order of this Millisecond object 336: * relative to the specified object: 337: * 338: * negative == before, zero == same, positive == after. 339: * 340: * @param obj the object to compare 341: * 342: * @return negative == before, zero == same, positive == after. 343: */ 344: public int compareTo(Object obj) { 345: 346: int result; 347: long difference; 348: 349: // CASE 1 : Comparing to another Second object 350: // ------------------------------------------- 351: if (obj instanceof Millisecond) { 352: Millisecond ms = (Millisecond) obj; 353: difference = getFirstMillisecond() - ms.getFirstMillisecond(); 354: if (difference > 0) { 355: result = 1; 356: } 357: else { 358: if (difference < 0) { 359: result = -1; 360: } 361: else { 362: result = 0; 363: } 364: } 365: } 366: 367: // CASE 2 : Comparing to another TimePeriod object 368: // ----------------------------------------------- 369: else if (obj instanceof RegularTimePeriod) { 370: RegularTimePeriod rtp = (RegularTimePeriod) obj; 371: final long thisVal = this.getFirstMillisecond(); 372: final long anotherVal = rtp.getFirstMillisecond(); 373: result = (thisVal < anotherVal ? -1 374: : (thisVal == anotherVal ? 0 : 1)); 375: } 376: 377: // CASE 3 : Comparing to a non-TimePeriod object 378: // --------------------------------------------- 379: else { 380: // consider time periods to be ordered after general objects 381: result = 1; 382: } 383: 384: return result; 385: 386: } 387: 388: /** 389: * Returns the first millisecond of the time period. 390: * 391: * @param calendar the calendar (<code>null</code> not permitted). 392: * 393: * @return The first millisecond of the time period. 394: * 395: * @throws NullPointerException if <code>calendar</code> is 396: * <code>null</code>. 397: */ 398: public long getFirstMillisecond(Calendar calendar) { 399: int year = this.day.getYear(); 400: int month = this.day.getMonth() - 1; 401: int day = this.day.getDayOfMonth(); 402: calendar.clear(); 403: calendar.set(year, month, day, this.hour, this.minute, this.second); 404: calendar.set(Calendar.MILLISECOND, this.millisecond); 405: //return calendar.getTimeInMillis(); // this won't work for JDK 1.3 406: return calendar.getTime().getTime(); 407: } 408: 409: /** 410: * Returns the last millisecond of the time period. 411: * 412: * @param calendar the calendar (<code>null</code> not permitted). 413: * 414: * @return The last millisecond of the time period. 415: * 416: * @throws NullPointerException if <code>calendar</code> is 417: * <code>null</code>. 418: */ 419: public long getLastMillisecond(Calendar calendar) { 420: return getFirstMillisecond(calendar); 421: } 422: 423: }