Source for org.jfree.data.time.Minute

   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:  * Minute.java
  29:  * -----------
  30:  * (C) Copyright 2001-2004, by Object Refinery Limited.
  31:  *
  32:  * Original Author:  David Gilbert (for Object Refinery Limited);
  33:  * Contributor(s):   -;
  34:  *
  35:  * $Id: Minute.java,v 1.5.2.1 2005/10/25 21:35:24 mungady Exp $
  36:  *
  37:  * Changes
  38:  * -------
  39:  * 11-Oct-2001 : Version 1 (DG);
  40:  * 18-Dec-2001 : Changed order of parameters in constructor (DG);
  41:  * 19-Dec-2001 : Added a new constructor as suggested by Paul English (DG);
  42:  * 14-Feb-2002 : Fixed bug in Minute(Date) constructor, and changed the range 
  43:  *               to start from zero instead of one (DG);
  44:  * 26-Feb-2002 : Changed getStart(), getMiddle() and getEnd() methods to 
  45:  *               evaluate with reference to a particular time zone (DG);
  46:  * 13-Mar-2002 : Added parseMinute() method (DG);
  47:  * 19-Mar-2002 : Changed API, the minute is now defined in relation to an 
  48:  *               Hour (DG);
  49:  * 10-Sep-2002 : Added getSerialIndex() method (DG);
  50:  * 07-Oct-2002 : Fixed errors reported by Checkstyle (DG);
  51:  * 10-Jan-2003 : Changed base class and method names (DG);
  52:  * 13-Mar-2003 : Moved to com.jrefinery.data.time package and implemented 
  53:  *               Serializable (DG);
  54:  * 21-Oct-2003 : Added hashCode() method, and new constructor for 
  55:  *               convenience (DG);
  56:  * 30-Sep-2004 : Replaced getTime().getTime() with getTimeInMillis() (DG);
  57:  * 04-Nov-2004 : Reverted change of 30-Sep-2004, because it won't work for 
  58:  *               JDK 1.3 (DG);
  59:  *
  60:  */
  61: 
  62: package org.jfree.data.time;
  63: 
  64: import java.io.Serializable;
  65: import java.util.Calendar;
  66: import java.util.Date;
  67: import java.util.TimeZone;
  68: 
  69: /**
  70:  * Represents a minute.  This class is immutable, which is a requirement for 
  71:  * all {@link RegularTimePeriod} subclasses.
  72:  */
  73: public class Minute extends RegularTimePeriod implements Serializable {
  74: 
  75:     /** For serialization. */
  76:     private static final long serialVersionUID = 2144572840034842871L;
  77:     
  78:     /** Useful constant for the first minute in a day. */
  79:     public static final int FIRST_MINUTE_IN_HOUR = 0;
  80: 
  81:     /** Useful constant for the last minute in a day. */
  82:     public static final int LAST_MINUTE_IN_HOUR = 59;
  83: 
  84:     /** The hour in which the minute falls. */
  85:     private Hour hour;
  86: 
  87:     /** The minute. */
  88:     private int minute;
  89: 
  90:     /**
  91:      * Constructs a new Minute, based on the system date/time.
  92:      */
  93:     public Minute() {
  94:         this(new Date());
  95:     }
  96: 
  97:     /**
  98:      * Constructs a new Minute.
  99:      *
 100:      * @param minute  the minute (0 to 59).
 101:      * @param hour  the hour (<code>null</code> not permitted).
 102:      */
 103:     public Minute(int minute, Hour hour) {
 104:         if (hour == null) {
 105:             throw new IllegalArgumentException("Null 'hour' argument.");
 106:         }
 107:         this.minute = minute;
 108:         this.hour = hour;
 109:     }
 110: 
 111:     /**
 112:      * Constructs a new Minute, based on the supplied date/time.
 113:      *
 114:      * @param time  the time (<code>null</code> not permitted).
 115:      */
 116:     public Minute(Date time) {
 117:         // defer argument checking
 118:         this(time, RegularTimePeriod.DEFAULT_TIME_ZONE);
 119:     }
 120: 
 121:     /**
 122:      * Constructs a new Minute, based on the supplied date/time and timezone.
 123:      *
 124:      * @param time  the time (<code>null</code> not permitted).
 125:      * @param zone  the time zone (<code>null</code> not permitted).
 126:      */
 127:     public Minute(Date time, TimeZone zone) {
 128: 
 129:         if (time == null) {
 130:             throw new IllegalArgumentException("Null 'time' argument.");
 131:         }
 132:         if (zone == null) {
 133:             throw new IllegalArgumentException("Null 'zone' argument.");
 134:         }
 135:         Calendar calendar = Calendar.getInstance(zone);
 136:         calendar.setTime(time);
 137:         int min = calendar.get(Calendar.MINUTE);
 138:         this.minute = min;
 139:         this.hour = new Hour(time, zone);
 140: 
 141:     }
 142:     
 143:     /**
 144:      * Creates a new minute.
 145:      * 
 146:      * @param minute  the minute (0-59).
 147:      * @param hour  the hour (0-23).
 148:      * @param day  the day (1-31).
 149:      * @param month  the month (1-12).
 150:      * @param year  the year (1900-9999).
 151:      */
 152:     public Minute(int minute, 
 153:                   int hour, 
 154:                   int day, 
 155:                   int month, 
 156:                   int year) {
 157:         this(minute, new Hour(hour, new Day(day, month, year)));
 158:     }
 159: 
 160:     /**
 161:      * Returns the hour.
 162:      *
 163:      * @return The hour (never <code>null</code>).
 164:      */
 165:     public Hour getHour() {
 166:         return this.hour;
 167:     }
 168: 
 169:     /**
 170:      * Returns the minute.
 171:      *
 172:      * @return The minute.
 173:      */
 174:     public int getMinute() {
 175:         return this.minute;
 176:     }
 177: 
 178:     /**
 179:      * Returns the minute preceding this one.
 180:      *
 181:      * @return The minute preceding this one.
 182:      */
 183:     public RegularTimePeriod previous() {
 184: 
 185:         Minute result;
 186:         if (this.minute != FIRST_MINUTE_IN_HOUR) {
 187:             result = new Minute(this.minute - 1, this.hour);
 188:         }
 189:         else { // we are at the first minute in the hour...
 190:             Hour prevHour = (Hour) this.hour.previous();
 191:             if (prevHour != null) {
 192:                 result = new Minute(LAST_MINUTE_IN_HOUR, prevHour);
 193:             }
 194:             else {
 195:                 result = null;
 196:             }
 197:         }
 198:         return result;
 199: 
 200:     }
 201: 
 202:     /**
 203:      * Returns the minute following this one.
 204:      *
 205:      * @return The minute following this one.
 206:      */
 207:     public RegularTimePeriod next() {
 208: 
 209:         Minute result;
 210:         if (this.minute != LAST_MINUTE_IN_HOUR) {
 211:             result = new Minute(this.minute + 1, this.hour);
 212:         }
 213:         else { // we are at the last minute in the hour...
 214:             Hour nextHour = (Hour) this.hour.next();
 215:             if (nextHour != null) {
 216:                 result = new Minute(FIRST_MINUTE_IN_HOUR, nextHour);
 217:             }
 218:             else {
 219:                 result = null;
 220:             }
 221:         }
 222:         return result;
 223: 
 224:     }
 225: 
 226:     /**
 227:      * Returns a serial index number for the minute.
 228:      *
 229:      * @return The serial index number.
 230:      */
 231:     public long getSerialIndex() {
 232:         return this.hour.getSerialIndex() * 60L + this.minute;
 233:     }
 234: 
 235:     /**
 236:      * Returns the first millisecond of the minute.
 237:      *
 238:      * @param calendar  the calendar (which defines the timezone).
 239:      *
 240:      * @return The first millisecond.
 241:      */
 242:     public long getFirstMillisecond(Calendar calendar) {
 243: 
 244:         int year = this.hour.getDay().getYear();
 245:         int month = this.hour.getDay().getMonth() - 1;
 246:         int day = this.hour.getDay().getDayOfMonth();
 247: 
 248:         calendar.clear();
 249:         calendar.set(year, month, day, this.hour.getHour(), this.minute, 0);
 250:         calendar.set(Calendar.MILLISECOND, 0);
 251: 
 252:         //return calendar.getTimeInMillis();  // this won't work for JDK 1.3
 253:         return calendar.getTime().getTime();
 254: 
 255:     }
 256: 
 257:     /**
 258:      * Returns the last millisecond of the minute.
 259:      *
 260:      * @param calendar  the calendar and timezone.
 261:      *
 262:      * @return The last millisecond.
 263:      */
 264:     public long getLastMillisecond(Calendar calendar) {
 265: 
 266:         int year = this.hour.getDay().getYear();
 267:         int month = this.hour.getDay().getMonth() - 1;
 268:         int day = this.hour.getDay().getDayOfMonth();
 269: 
 270:         calendar.clear();
 271:         calendar.set(year, month, day, this.hour.getHour(), this.minute, 59);
 272:         calendar.set(Calendar.MILLISECOND, 999);
 273: 
 274:         //return calendar.getTimeInMillis();  // this won't work for JDK 1.3
 275:         return calendar.getTime().getTime();
 276: 
 277:     }
 278: 
 279:     /**
 280:      * Tests the equality of this object against an arbitrary Object.
 281:      * <P>
 282:      * This method will return true ONLY if the object is a Minute object
 283:      * representing the same minute as this instance.
 284:      *
 285:      * @param obj  the object to compare (<code>null</code> permitted).
 286:      *
 287:      * @return <code>true</code> if the minute and hour value of this and the
 288:      *      object are the same.
 289:      */
 290:     public boolean equals(Object obj) {
 291:         if (obj == this) {
 292:             return true;
 293:         }
 294:         if (!(obj instanceof Minute)) {
 295:             return false;
 296:         }
 297:         Minute that = (Minute) obj;
 298:         if (this.minute != that.minute) {
 299:             return false;
 300:         }
 301:         if (!this.hour.equals(that.hour)) {
 302:             return false;
 303:         }
 304:         return true;
 305:     }
 306: 
 307:     /**
 308:      * Returns a hash code for this object instance.  The approach described 
 309:      * by Joshua Bloch in "Effective Java" has been used here:
 310:      * <p>
 311:      * <code>http://developer.java.sun.com/developer/Books/effectivejava
 312:      * /Chapter3.pdf</code>
 313:      * 
 314:      * @return A hash code.
 315:      */
 316:     public int hashCode() {
 317:         int result = 17;
 318:         result = 37 * result + this.minute;
 319:         result = 37 * result + this.hour.hashCode();
 320:         return result;
 321:     }
 322: 
 323:     /**
 324:      * Returns an integer indicating the order of this Minute object relative
 325:      * to the specified object:
 326:      *
 327:      * negative == before, zero == same, positive == after.
 328:      *
 329:      * @param o1  object to compare.
 330:      *
 331:      * @return negative == before, zero == same, positive == after.
 332:      */
 333:     public int compareTo(Object o1) {
 334: 
 335:         int result;
 336: 
 337:         // CASE 1 : Comparing to another Minute object
 338:         // -------------------------------------------
 339:         if (o1 instanceof Minute) {
 340:             Minute m = (Minute) o1;
 341:             result = getHour().compareTo(m.getHour());
 342:             if (result == 0) {
 343:                 result = this.minute - m.getMinute();
 344:             }
 345:         }
 346: 
 347:         // CASE 2 : Comparing to another TimePeriod object
 348:         // -----------------------------------------------
 349:         else if (o1 instanceof RegularTimePeriod) {
 350:             // more difficult case - evaluate later...
 351:             result = 0;
 352:         }
 353: 
 354:         // CASE 3 : Comparing to a non-TimePeriod object
 355:         // ---------------------------------------------
 356:         else {
 357:             // consider time periods to be ordered after general objects
 358:             result = 1;
 359:         }
 360: 
 361:         return result;
 362: 
 363:     }
 364: 
 365:     /**
 366:      * Creates a Minute instance by parsing a string.  The string is assumed to
 367:      * be in the format "YYYY-MM-DD HH:MM", perhaps with leading or trailing
 368:      * whitespace.
 369:      *
 370:      * @param s  the minute string to parse.
 371:      *
 372:      * @return <code>null</code>, if the string is not parseable, the minute
 373:      *      otherwise.
 374:      */
 375:     public static Minute parseMinute(String s) {
 376: 
 377:         Minute result = null;
 378:         s = s.trim();
 379: 
 380:         String daystr = s.substring(0, Math.min(10, s.length()));
 381:         Day day = Day.parseDay(daystr);
 382:         if (day != null) {
 383:             String hmstr = s.substring(
 384:                 Math.min(daystr.length() + 1, s.length()), s.length()
 385:             );
 386:             hmstr = hmstr.trim();
 387: 
 388:             String hourstr = hmstr.substring(0, Math.min(2, hmstr.length()));
 389:             int hour = Integer.parseInt(hourstr);
 390: 
 391:             if ((hour >= 0) && (hour <= 23)) {
 392:                 String minstr = hmstr.substring(
 393:                     Math.min(hourstr.length() + 1, hmstr.length()), 
 394:                     hmstr.length()
 395:                 );
 396:                 int minute = Integer.parseInt(minstr);
 397:                 if ((minute >= 0) && (minute <= 59)) {
 398:                     result = new Minute(minute, new Hour(hour, day));
 399:                 }
 400:             }
 401:         }
 402: 
 403:         return result;
 404: 
 405:     }
 406: 
 407: }