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: * DateTickUnit.java 29: * ----------------- 30: * (C) Copyright 2000-2007, by Object Refinery Limited. 31: * 32: * Original Author: David Gilbert (for Object Refinery Limited); 33: * Contributor(s): Chris Boek; 34: * 35: * Changes 36: * ------- 37: * 08-Nov-2002 : Moved to new package com.jrefinery.chart.axis (DG); 38: * 27-Nov-2002 : Added IllegalArgumentException to getMillisecondCount() 39: * method (DG); 40: * 26-Mar-2003 : Implemented Serializable (DG); 41: * 12-Nov-2003 : Added roll fields that can improve the labelling on segmented 42: * date axes (DG); 43: * 03-Dec-2003 : DateFormat constructor argument is now filled with an default 44: * if null (TM); 45: * 07-Dec-2003 : Fixed bug (null pointer exception) in constructor (DG); 46: * ------------- JFREECHART 1.0.x --------------------------------------------- 47: * 21-Mar-2007 : Added toString() for debugging (DG); 48: * 04-Apr-2007 : Added new methods addToDate(Date, TimeZone) and rollDate(Date, 49: * TimeZone) (CB); 50: * 51: */ 52: 53: package org.jfree.chart.axis; 54: 55: import java.io.Serializable; 56: import java.text.DateFormat; 57: import java.util.Calendar; 58: import java.util.Date; 59: import java.util.TimeZone; 60: 61: import org.jfree.util.ObjectUtilities; 62: 63: /** 64: * A tick unit for use by subclasses of {@link DateAxis}. Instances of this 65: * class are immutable. 66: */ 67: public class DateTickUnit extends TickUnit implements Serializable { 68: 69: /** For serialization. */ 70: private static final long serialVersionUID = -7289292157229621901L; 71: 72: /** A constant for years. */ 73: public static final int YEAR = 0; 74: 75: /** A constant for months. */ 76: public static final int MONTH = 1; 77: 78: /** A constant for days. */ 79: public static final int DAY = 2; 80: 81: /** A constant for hours. */ 82: public static final int HOUR = 3; 83: 84: /** A constant for minutes. */ 85: public static final int MINUTE = 4; 86: 87: /** A constant for seconds. */ 88: public static final int SECOND = 5; 89: 90: /** A constant for milliseconds. */ 91: public static final int MILLISECOND = 6; 92: 93: /** The unit. */ 94: private int unit; 95: 96: /** The unit count. */ 97: private int count; 98: 99: /** The roll unit. */ 100: private int rollUnit; 101: 102: /** The roll count. */ 103: private int rollCount; 104: 105: /** The date formatter. */ 106: private DateFormat formatter; 107: 108: /** 109: * Creates a new date tick unit. The dates will be formatted using a 110: * SHORT format for the default locale. 111: * 112: * @param unit the unit. 113: * @param count the unit count. 114: */ 115: public DateTickUnit(int unit, int count) { 116: this(unit, count, null); 117: } 118: 119: /** 120: * Creates a new date tick unit. You can specify the units using one of 121: * the constants YEAR, MONTH, DAY, HOUR, MINUTE, SECOND or MILLISECOND. 122: * In addition, you can specify a unit count, and a date format. 123: * 124: * @param unit the unit. 125: * @param count the unit count. 126: * @param formatter the date formatter (defaults to DateFormat.SHORT). 127: */ 128: public DateTickUnit(int unit, int count, DateFormat formatter) { 129: 130: this(unit, count, unit, count, formatter); 131: 132: } 133: 134: /** 135: * Creates a new unit. 136: * 137: * @param unit the unit. 138: * @param count the count. 139: * @param rollUnit the roll unit. 140: * @param rollCount the roll count. 141: * @param formatter the date formatter (defaults to DateFormat.SHORT). 142: */ 143: public DateTickUnit(int unit, int count, int rollUnit, int rollCount, 144: DateFormat formatter) { 145: super(DateTickUnit.getMillisecondCount(unit, count)); 146: this.unit = unit; 147: this.count = count; 148: this.rollUnit = rollUnit; 149: this.rollCount = rollCount; 150: this.formatter = formatter; 151: if (formatter == null) { 152: this.formatter = DateFormat.getDateInstance(DateFormat.SHORT); 153: } 154: } 155: 156: /** 157: * Returns the date unit. This will be one of the constants 158: * <code>YEAR</code>, <code>MONTH</code>, <code>DAY</code>, 159: * <code>HOUR</code>, <code>MINUTE</code>, <code>SECOND</code> or 160: * <code>MILLISECOND</code>, defined by this class. Note that these 161: * constants do NOT correspond to those defined in Java's 162: * <code>Calendar</code> class. 163: * 164: * @return The date unit. 165: */ 166: public int getUnit() { 167: return this.unit; 168: } 169: 170: /** 171: * Returns the unit count. 172: * 173: * @return The unit count. 174: */ 175: public int getCount() { 176: return this.count; 177: } 178: 179: /** 180: * Returns the roll unit. This is the amount by which the tick advances if 181: * it is "hidden" when displayed on a segmented date axis. Typically the 182: * roll will be smaller than the regular tick unit (for example, a 7 day 183: * tick unit might use a 1 day roll). 184: * 185: * @return The roll unit. 186: */ 187: public int getRollUnit() { 188: return this.rollUnit; 189: } 190: 191: /** 192: * Returns the roll count. 193: * 194: * @return The roll count. 195: */ 196: public int getRollCount() { 197: return this.rollCount; 198: } 199: 200: /** 201: * Formats a value. 202: * 203: * @param milliseconds date in milliseconds since 01-01-1970. 204: * 205: * @return The formatted date. 206: */ 207: public String valueToString(double milliseconds) { 208: return this.formatter.format(new Date((long) milliseconds)); 209: } 210: 211: /** 212: * Formats a date using the tick unit's formatter. 213: * 214: * @param date the date. 215: * 216: * @return The formatted date. 217: */ 218: public String dateToString(Date date) { 219: return this.formatter.format(date); 220: } 221: 222: /** 223: * Calculates a new date by adding this unit to the base date. 224: * 225: * @param base the base date. 226: * 227: * @return A new date one unit after the base date. 228: * 229: * @see #addToDate(Date, TimeZone) 230: */ 231: public Date addToDate(Date base) { 232: Calendar calendar = Calendar.getInstance(); 233: calendar.setTime(base); 234: calendar.add(getCalendarField(this.unit), this.count); 235: return calendar.getTime(); 236: } 237: 238: /** 239: * Calculates a new date by adding this unit to the base date. 240: * 241: * @param base the base date. 242: * @param zone the time zone for the date calculation. 243: * 244: * @return A new date one unit after the base date. 245: * 246: * @since 1.0.6 247: * @see #addToDate(Date) 248: */ 249: public Date addToDate(Date base, TimeZone zone) { 250: Calendar calendar = Calendar.getInstance(zone); 251: calendar.setTime(base); 252: calendar.add(getCalendarField(this.unit), this.count); 253: return calendar.getTime(); 254: } 255: 256: /** 257: * Rolls the date forward by the amount specified by the roll unit and 258: * count. 259: * 260: * @param base the base date. 261: 262: * @return The rolled date. 263: * 264: * @see #rollDate(Date, TimeZone) 265: */ 266: public Date rollDate(Date base) { 267: Calendar calendar = Calendar.getInstance(); 268: calendar.setTime(base); 269: calendar.add(getCalendarField(this.rollUnit), this.rollCount); 270: return calendar.getTime(); 271: } 272: 273: /** 274: * Rolls the date forward by the amount specified by the roll unit and 275: * count. 276: * 277: * @param base the base date. 278: * @param zone the time zone. 279: * 280: * @return The rolled date. 281: * 282: * @since 1.0.6 283: * @see #rollDate(Date) 284: */ 285: public Date rollDate(Date base, TimeZone zone) { 286: Calendar calendar = Calendar.getInstance(zone); 287: calendar.setTime(base); 288: calendar.add(getCalendarField(this.rollUnit), this.rollCount); 289: return calendar.getTime(); 290: } 291: 292: /** 293: * Returns a field code that can be used with the <code>Calendar</code> 294: * class. 295: * 296: * @return The field code. 297: */ 298: public int getCalendarField() { 299: return getCalendarField(this.unit); 300: } 301: 302: /** 303: * Returns a field code (that can be used with the Calendar class) for a 304: * given 'unit' code. The 'unit' is one of: {@link #YEAR}, {@link #MONTH}, 305: * {@link #DAY}, {@link #HOUR}, {@link #MINUTE}, {@link #SECOND} and 306: * {@link #MILLISECOND}. 307: * 308: * @param tickUnit the unit. 309: * 310: * @return The field code. 311: */ 312: private int getCalendarField(int tickUnit) { 313: 314: switch (tickUnit) { 315: case (YEAR): 316: return Calendar.YEAR; 317: case (MONTH): 318: return Calendar.MONTH; 319: case (DAY): 320: return Calendar.DATE; 321: case (HOUR): 322: return Calendar.HOUR_OF_DAY; 323: case (MINUTE): 324: return Calendar.MINUTE; 325: case (SECOND): 326: return Calendar.SECOND; 327: case (MILLISECOND): 328: return Calendar.MILLISECOND; 329: default: 330: return Calendar.MILLISECOND; 331: } 332: 333: } 334: 335: /** 336: * Returns the (approximate) number of milliseconds for the given unit and 337: * unit count. 338: * <P> 339: * This value is an approximation some of the time (e.g. months are 340: * assumed to have 31 days) but this shouldn't matter. 341: * 342: * @param unit the unit. 343: * @param count the unit count. 344: * 345: * @return The number of milliseconds. 346: */ 347: private static long getMillisecondCount(int unit, int count) { 348: 349: switch (unit) { 350: case (YEAR): 351: return (365L * 24L * 60L * 60L * 1000L) * count; 352: case (MONTH): 353: return (31L * 24L * 60L * 60L * 1000L) * count; 354: case (DAY): 355: return (24L * 60L * 60L * 1000L) * count; 356: case (HOUR): 357: return (60L * 60L * 1000L) * count; 358: case (MINUTE): 359: return (60L * 1000L) * count; 360: case (SECOND): 361: return 1000L * count; 362: case (MILLISECOND): 363: return count; 364: default: 365: throw new IllegalArgumentException( 366: "DateTickUnit.getMillisecondCount() : unit must " 367: + "be one of the constants YEAR, MONTH, DAY, HOUR, MINUTE, " 368: + "SECOND or MILLISECOND defined in the DateTickUnit " 369: + "class. Do *not* use the constants defined in " 370: + "java.util.Calendar." 371: ); 372: } 373: 374: } 375: 376: /** 377: * Tests this unit for equality with another object. 378: * 379: * @param obj the object (<code>null</code> permitted). 380: * 381: * @return <code>true</code> or <code>false</code>. 382: */ 383: public boolean equals(Object obj) { 384: if (obj == this) { 385: return true; 386: } 387: if (!(obj instanceof DateTickUnit)) { 388: return false; 389: } 390: if (!super.equals(obj)) { 391: return false; 392: } 393: DateTickUnit that = (DateTickUnit) obj; 394: if (this.unit != that.unit) { 395: return false; 396: } 397: if (this.count != that.count) { 398: return false; 399: } 400: if (!ObjectUtilities.equal(this.formatter, that.formatter)) { 401: return false; 402: } 403: return true; 404: } 405: 406: /** 407: * Returns a hash code for this object. 408: * 409: * @return A hash code. 410: */ 411: public int hashCode() { 412: int result = 19; 413: result = 37 * result + this.unit; 414: result = 37 * result + this.count; 415: result = 37 * result + this.formatter.hashCode(); 416: return result; 417: } 418: 419: /** 420: * Strings for use by the toString() method. 421: */ 422: private static final String[] units = {"YEAR", "MONTH", "DAY", "HOUR", 423: "MINUTE", "SECOND", "MILLISECOND"}; 424: 425: /** 426: * Returns a string representation of this instance, primarily used for 427: * debugging purposes. 428: * 429: * @return A string representation of this instance. 430: */ 431: public String toString() { 432: return "DateTickUnit[" + DateTickUnit.units[this.unit] + ", " 433: + this.count + "]"; 434: } 435: 436: }