Source for org.jfree.data.time.Second

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