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