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