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