Mega Code Archive

 
Categories / Java / Development Class
 

A class representing a moment in time

/*  * This code is free software; you can redistribute it and/or  * modify it under the terms of the GNU Lesser General Public   * License as published by the Free Software Foundation; either   * version 2.1 of the License, or (at your option) any later version.  *  * This code is distributed in the hope that it will be useful,  * but WITHOUT ANY WARRANTY; without even the implied warranty of  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the  * GNU Lesser General Public License for more details.  *  * You should have received a copy of the GNU Lesser General Public   * License along with this program; if not, write to the Free   * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,   * MA  02111-1307, USA.  */ //package no.geosoft.cc.util; import java.io.Serializable; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.TimeZone; /**  * A class representing a moment in time. Extends Day which represents the day  * of the moment, and defines the time within the day to millisecond accuracy.  *   * @author Jacob Dreyer (<a  *         href="mailto:jacob.dreyer@geosoft.no">jacob.dreyer@geosoft.no</a>)  */ public class Time extends Day {   /**    * Instantiate a Time object. The time is lenient meaning that illegal day    * parameters can be specified and results in a recomputed day with legal    * month/day values.    *     * @param year    *          Year of this time    * @param month    *          Month of this time    * @param dayOfMonth    *          Day of month of this time.    * @param hours    *          Hours of this time [0-23]    * @param minutes    *          Minutes of this time [0-23]    * @param seconds    *          Seconds of this time [0-23]    */   public Time(int year, int month, int dayOfMonth, int hours, int minutes, int seconds) {     super(year, month, dayOfMonth);     setHours(hours);     setMinutes(minutes);     setSeconds(seconds);   }   public Time(Day day, int hours, int minutes, int seconds) {     this(day.getYear(), day.getMonth(), day.getDayOfMonth(), hours, minutes, seconds);   }   public Time(int hours, int minutes, int seconds) {     this(new Day(), hours, minutes, seconds);   }   public Time() {     calendar_ = new GregorianCalendar(); // Now   }   public void setDay(Day day) {     setYear(day.getYear());     setMonth(day.getMonth());     setDayOfMonth(day.getDayOfMonth());   }   public void setHours(int hours) {     calendar_.set(Calendar.HOUR_OF_DAY, hours);   }   public int getHours() {     return calendar_.get(Calendar.HOUR_OF_DAY);   }   public void setMinutes(int minutes) {     calendar_.set(Calendar.MINUTE, minutes);   }   public int getMinutes() {     return calendar_.get(Calendar.MINUTE);   }   public void setSeconds(int seconds) {     calendar_.set(Calendar.SECOND, seconds);   }   public int getSeconds() {     return calendar_.get(Calendar.SECOND);   }   public void setMilliSeconds(int milliSeconds) {     calendar_.set(Calendar.MILLISECOND, milliSeconds);   }   public int getMilliSeconds() {     return calendar_.get(Calendar.MILLISECOND);   }   public boolean isAfter(Time time) {     return calendar_.after(time.calendar_);   }   public boolean isBefore(Time time) {     return calendar_.before(time.calendar_);   }   public boolean equals(Time time) {     return calendar_.equals(time.calendar_);   }   public void addHours(int nHours) {     calendar_.add(Calendar.HOUR_OF_DAY, nHours);   }   public void addMinutes(int nMinutes) {     calendar_.add(Calendar.MINUTE, nMinutes);   }   public void addSeconds(int nSeconds) {     calendar_.add(Calendar.SECOND, nSeconds);   }   public void addMilliSeconds(int nMilliSeconds) {     calendar_.add(Calendar.MILLISECOND, nMilliSeconds);   }   public long milliSecondsBetween(Time time) {     long millisBetween = calendar_.getTime().getTime() - time.calendar_.getTime().getTime();     return millisBetween;   }   public double secondsBetween(Time time) {     long millisBetween = calendar_.getTime().getTime() - time.calendar_.getTime().getTime();     return millisBetween / 1000;   }   public double minutesBetween(Time time) {     long millisBetween = calendar_.getTime().getTime() - time.calendar_.getTime().getTime();     return millisBetween / (1000 * 60);   }   public double hoursBetween(Time time) {     long millisBetween = calendar_.getTime().getTime() - time.calendar_.getTime().getTime();     return millisBetween / (1000 * 60 * 60);   }   public String toString() {     StringBuffer string = new StringBuffer();     string.append(super.toString());     string.append(' ');     if (getHours() < 10)       string.append('0');     string.append(getHours());     string.append(':');     if (getMinutes() < 10)       string.append('0');     string.append(getMinutes());     string.append(':');     if (getSeconds() < 10)       string.append('0');     string.append(getSeconds());     string.append(',');     string.append(getMilliSeconds());     return string.toString();   }   public static void main(String args[]) {     Time time = new Time(12, 00, 00);     System.out.println(time);   } } class Day implements Comparable, Cloneable, Serializable {   protected Calendar calendar_;   /**    * Initialize the internal calendar instance.    *     * @param year    *          Year of new day.    * @param month    *          Month of new day.    * @param dayOfMonth    *          Day of month of new day.    */   private void initialize(int year, int month, int dayOfMonth) {     calendar_ = Calendar.getInstance();     calendar_.setLenient(true);     calendar_.setFirstDayOfWeek(Calendar.MONDAY);     calendar_.setTimeZone(TimeZone.getTimeZone("GMT"));     set(year, month, dayOfMonth);   }   /**    * Create a new day. The day is lenient meaning that illegal day parameters    * can be specified and results in a recomputed day with legal month/day    * values.    *     * @param year    *          Year of new day.    * @param month    *          Month of new day (0-11)    * @param dayOfMonth    *          Day of month of new day (1-31)    */   public Day(int year, int month, int dayOfMonth) {     initialize(year, month, dayOfMonth);   }   /**    * Create a new day, specifying the year and the day of year. The day is    * lenient meaning that illegal day parameters can be specified and results in    * a recomputed day with legal month/day values.    *     * @param year    *          Year of new day.    * @param dayOfYear    *          1=January 1, etc.    */   public Day(int year, int dayOfYear) {     initialize(year, Calendar.JANUARY, 1);     calendar_.set(Calendar.DAY_OF_YEAR, dayOfYear);   }   /**    * Create a new day representing the day of creation (according to the setting    * of the current machine).    */   public Day() {     // Now (in the currenct locale of the client machine)     Calendar calendar = Calendar.getInstance();     // Prune time part     initialize(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar         .get(Calendar.DAY_OF_MONTH));   }   /**    * Create a new day based on a java.util.Calendar instance. NOTE: The time    * component from calendar will be pruned.    *     * @param calendar    *          Calendar instance to copy.    */   public Day(Calendar calendar) {     this(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar         .get(Calendar.DAY_OF_MONTH));   }   /**    * Create a new day based on a java.util.Date instance. NOTE: The time    * component from date will be pruned.    *     * @param date    *          Date instance to copy.    */   public Day(Date date) {     // Create a calendar based on given date     Calendar calendar = Calendar.getInstance();     calendar.setTime(date);     // Extract date values and use these only     initialize(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar         .get(Calendar.DAY_OF_MONTH));   }   /**    * Create a new day based on a time value. Time is milliseconds since "the    * Epoch" (1.1.1970). NOTE: The time component from time will be pruned.    *     * @param time    *          Milliseconds since "the Epoch".    */   public Day(long time) {     this(new Date(time));   }   /**    * Create a new day as a copy of the specified day.    *     * @param day    *          Day to clone.    */   public Day(Day day) {     this(day.getYear(), day.getMonth(), day.getDayOfMonth());   }   /**    * Create a clone of this day.    *     * @return This day cloned.    */   public Object clone() {     return new Day(this);   }   /**    * A more explicit front-end to the Day() constructor which return a day    * object representing the day of creation.    *     * @return A day instance representing today.    */   public static Day today() {     return new Day();   }   /**    * Return a Calendar instance representing the same day as this instance. For    * use by secondary methods requiring java.util.Calendar as input.    *     * @return Calendar equivalent representing this day.    */   public Calendar getCalendar() {     return (Calendar) calendar_.clone();   }   /**    * Return a Date instance representing the same date as this instance. For use    * by secondary methods requiring java.util.Date as input.    *     * @return Date equivalent representing this day.    */   public Date getDate() {     return getCalendar().getTime();   }   /**    * Compare this day to the specified day. If object is not of type Day a    * ClassCastException is thrown.    *     * @param object    *          Day object to compare to.    * @return    * @see Comparable#compareTo(Object)    * @throws ClassCastException    *           If object is not of type Day.    */   public int compareTo(Object object) {     Day day = (Day) object;     return calendar_.getTime().compareTo(day.calendar_.getTime());   }   /**    * Return true if this day is after the specified day.    *     * @param date    *          Day to compare to.    * @return True if this is after day, false otherwise.    */   public boolean isAfter(Day day) {     return calendar_.after(day.calendar_);   }   /**    * Return true if this day is before the specified day.    *     * @param date    *          Day to compare to.    * @return True if this is before day, false otherwise.    */   public boolean isBefore(Day day) {     return calendar_.before(day.calendar_);   }   /**    * Return true if this day equals (represent the same date) as the specified    * day.    *     * @param date    *          Day to compare to.    * @return True if this equals day, false otherwise.    */   public boolean equals(Day day) {     return calendar_.equals(day.calendar_);   }   /**    * Overload required as default definition of equals() has changed.    *     * @return A hash code value for this object.    */   public int hashCode() {     return calendar_.hashCode();   }   /**    * Set date of this day. The day is lenient meaning that illegal day    * parameters can be specified and results in a recomputed day with legal    * month/day values.    *     * @param year    *          Year of this day.    * @param month    *          Month of this day (0-11).    * @param dayOfMonth    *          Day of month of this day (1-31).    */   public void set(int year, int month, int dayOfMonth) {     setYear(year);     setMonth(month);     setDayOfMonth(dayOfMonth);   }   /**    * Return year of this day.    *     * @return Year of this day.    */   public int getYear() {     return calendar_.get(Calendar.YEAR);   }   /**    * Set year of this day.    *     * @param year    *          New year of this day.    */   public void setYear(int year) {     calendar_.set(Calendar.YEAR, year);   }   /**    * Return month of this day. The result must be compared to Calendar.JANUARY,    * Calendar.FEBRUARY, etc.    *     * @return Month of this day.    */   public int getMonth() {     return calendar_.get(Calendar.MONTH);   }   /**    * Return the 1-based month number of the month of this day. 1 = January, 2 =    * February and so on.    *     * @return Month number of this month    */   public int getMonthNo() {     // It is tempting to return getMonth() + 1 but this is conceptually     // wrong, as Calendar month is an enumeration and the values are tags     // only and can be anything.     switch (getMonth()) {     case Calendar.JANUARY:       return 1;     case Calendar.FEBRUARY:       return 2;     case Calendar.MARCH:       return 3;     case Calendar.APRIL:       return 4;     case Calendar.MAY:       return 5;     case Calendar.JUNE:       return 6;     case Calendar.JULY:       return 7;     case Calendar.AUGUST:       return 8;     case Calendar.SEPTEMBER:       return 9;     case Calendar.OCTOBER:       return 10;     case Calendar.NOVEMBER:       return 11;     case Calendar.DECEMBER:       return 12;     }     // This will never happen     return 0;   }   /**    * Set month of this day. January = 0, February = 1, etc. Illegal month values    * will result in a recomputation of year and a resetting of month to a valid    * value. I.e. setMonth(20), will add 1 year to day and set month to 8.    *     * @param month    *          New month of this day.    */   public void setMonth(int month) {     calendar_.set(Calendar.MONTH, month);   }   /**    * Return day of month of this day. NOTE: First day of month is 1 (not 0).    *     * @return Day of month of this day.    */   public int getDayOfMonth() {     return calendar_.get(Calendar.DAY_OF_MONTH);   }   /**    * Set day of month of this date. 1=1st 2=2nd, etc. Illegal day values will    * result in a recomputation of month/year and a resetting of day to a valid    * value. I.e. setDayOfMonth(33), will add 1 month to date and set day to 5,    * 4, 3 or 2 depending on month/year.    *     * @param dayOfMonth    *          New day of month of this day.    */   public void setDayOfMonth(int dayOfMonth) {     calendar_.set(Calendar.DAY_OF_MONTH, dayOfMonth);   }   /**    * Return the day number of year this day represents. January 1 = 1 and so on.    *     * @return day number of year.    */   public int getDayOfYear() {     return calendar_.get(Calendar.DAY_OF_YEAR);   }   /**    * Return the day of week of this day. NOTE: Must be compared to    * Calendar.MONDAY, TUSEDAY etc.    *     * @return Day of week of this day.    */   public int getDayOfWeek() {     return calendar_.get(Calendar.DAY_OF_WEEK);   }   /**    * Return the day number of week of this day, where Monday=1, Tuesday=2, ...    * Sunday=7.    *     * @return Day number of week of this day.    */   public int getDayNumberOfWeek() {     return getDayOfWeek() == Calendar.SUNDAY ? 7 : getDayOfWeek() - Calendar.SUNDAY;   }   /**    * Return the week number of year, this day belongs to. 1st=1 and so on.    *     * @return Week number of year of this day.    */   public int getWeekOfYear() {     return calendar_.get(Calendar.WEEK_OF_YEAR);   }   /**    * Add a number of days to this day. Subtracting a number of days can be done    * by a negative argument to addDays() or calling subtractDays() explicitly.    *     * @param nDays    *          Number of days to add.    */   public void addDays(int nDays) {     calendar_.add(Calendar.DAY_OF_MONTH, nDays);   }   /**    * Subtract a number of days from this day    *     * @param nDays    *          Number of days to subtract.    */   public void subtractDays(int nDays) {     addDays(-nDays);   }   /**    * Add a number of months to this day. The actual number of days added depends    * on the staring day. Subtracting a number of months can be done by a    * negative argument to addMonths() or calling subtactMonths() explicitly.    * NOTE: addMonth(n) m times will in general give a different result than    * addMonth(m*n). Add 1 month to January 31, 2005 will give February 28, 2005.    *     * @param nMonths    *          Number of months to add.    */   public void addMonths(int nMonths) {     calendar_.add(Calendar.MONTH, nMonths);   }   /**    * Subtract a number of months from this day    *     * @see #addMonths(int).    *     * @param nDays    *          Number of days to subtract.    */   public void subtractMonths(int nMonths) {     addMonths(-nMonths);   }   /**    * Add a number of years to this day. The actual number of days added depends    * on the starting day. Subtracting a number of years can be done by a    * negative argument to addYears() or calling subtractYears explicitly.    *     * @param nYears    *          Number of years to add.    */   public void addYears(int nYears) {     calendar_.add(Calendar.YEAR, nYears);   }   /**    * Subtract a number of years from this day    *     * @see #addYears(int).    *     * @param nYears    *          Number of years to subtract.    */   public void subtractYears(int nYears) {     addYears(-nYears);   }   /**    * Return the number of days in the year of this day.    *     * @return Number of days in this year.    */   public int getDaysInYear() {     return calendar_.getActualMaximum(Calendar.DAY_OF_YEAR);   }   /**    * Return true if the year of this day is a leap year.    *     * @return True if this year is a leap year, false otherwise.    */   public boolean isLeapYear() {     return getDaysInYear() == calendar_.getMaximum(Calendar.DAY_OF_YEAR);   }   /**    * Return true if the specified year is a leap year.    *     * @param year    *          Year to check.    * @return True if specified year is leap year, false otherwise.    */   public static boolean isLeapYear(int year) {     return (new Day(year, Calendar.JANUARY, 1)).isLeapYear();   }   /**    * Return the number of days in the month of this day.    *     * @return Number of days in this month.    */   public int getDaysInMonth() {     return calendar_.getActualMaximum(Calendar.DAY_OF_MONTH);   }   /**    * Get default locale name of this day ("Monday", "Tuesday", etc.    *     * @return Name of day.    */   public String getDayName() {     switch (getDayOfWeek()) {     case Calendar.MONDAY:       return "Monday";     case Calendar.TUESDAY:       return "Tuesday";     case Calendar.WEDNESDAY:       return "Wednesday";     case Calendar.THURSDAY:       return "Thursday";     case Calendar.FRIDAY:       return "Friday";     case Calendar.SATURDAY:       return "Saturday";     case Calendar.SUNDAY:       return "Sunday";     }     // This will never happen     return null;   }   /**    * Return number of days between two days. The method always returns a    * positive number of days.    *     * @param date    *          The day to compare to.    * @return Number of days between this and day.    */   public int daysBetween(Day day) {     long millisBetween = Math         .abs(calendar_.getTime().getTime() - day.calendar_.getTime().getTime());     return (int) Math.round(millisBetween / (1000 * 60 * 60 * 24));   }   /**    * Find the n'th xxxxday of s specified month (for instance find 1st sunday of    * May 2006; findNthOfMonth (1, Calendar.SUNDAY, Calendar.MAY, 2006); Return    * null if the specified day doesn't exists.    *     * @param n    *          Nth day to look for.    * @param dayOfWeek    *          Day to look for (Calendar.XXXDAY).    * @param month    *          Month to check (Calendar.XXX).    * @param year    *          Year to check.    * @return Required Day (or null if non-existent)    * @throws ArrayIndexOutOfBoundsException    *           if dyaOfWeek parameter doesn't represent a valid day.    */   public static Day getNthOfMonth(int n, int dayOfWeek, int month, int year)       throws ArrayIndexOutOfBoundsException {     // Validate the dayOfWeek argument     if (dayOfWeek < 0 || dayOfWeek > 6)       throw new ArrayIndexOutOfBoundsException(dayOfWeek);     Day first = new Day(year, month, 1);     int offset = dayOfWeek - first.getDayOfWeek();     if (offset < 0)       offset = 7 + offset;     int dayNo = (n - 1) * 7 + offset + 1;     return dayNo > first.getDaysInMonth() ? null : new Day(year, month, dayNo);   }   /**    * Find the first of a specific day in a given month, for instance first    * Tuesday of May: getFirstOfMonth (Calendar.TUESDAY, Calendar.MAY, 2005);    *     * @param dayOfWeek    *          Weekday to get.    * @param month    *          Month of day to get.    * @param year    *          Year of day to get.    * @return The requested day.    */   public static Day getFirstOfMonth(int dayOfWeek, int month, int year) {     return Day.getNthOfMonth(1, dayOfWeek, month, year);   }   /**    * Find the last of a specific day in a given month, for instance last Tuesday    * of May: getLastOfMonth (Calendar.TUESDAY, Calendar.MAY, 2005);    *     * @param dayOfWeek    *          Weekday to get.    * @param month    *          Month of day to get.    * @param year    *          Year of day to get.    * @return The requested day.    */   public static Day getLastOfMonth(int dayOfWeek, int month, int year) {     Day day = Day.getNthOfMonth(5, dayOfWeek, month, year);     return day != null ? day : Day.getNthOfMonth(4, dayOfWeek, month, year);   }   /**    * Return a scratch string representation of this day. Used for debugging    * only. The format of the day is dd/mm-yyyy    *     * @return A string representation of this day.    */   public String toString() {     StringBuffer string = new StringBuffer();     if (getDayOfMonth() < 10)       string.append('0');     string.append(getDayOfMonth());     string.append('/');     if (getMonth() < 9)       string.append('0');     string.append(getMonth() + 1);     string.append('-');     string.append(getYear());     string.append(" ");     string.append(getDayName());     return string.toString();   }   /**    * Testing this class.    *     * @param args    *          Not used.    */   public static void main(String[] args) {     // This proves that there are 912 days between the two major     // terrorist attacks, not 911 as is common knowledge.     Day september11 = new Day(2001, Calendar.SEPTEMBER, 11);     Day march11 = new Day(2004, Calendar.MARCH, 11);     System.out.println(september11.daysBetween(march11));     // This proves that Kennedy was president for 1037 days,     // not 1000 as is the popular belief nor 1036 which is the     // bluffers reply. Nerds knows when to add one...     Day precidency = new Day(1961, Calendar.JANUARY, 20);     Day assasination = new Day(1963, Calendar.NOVEMBER, 22);     System.out.println(precidency.daysBetween(assasination) + 1);     // Niel Armstrong walked the moon on a Sunday     Day nielOnMoon = new Day(1969, Calendar.JULY, 20);     System.out.println(nielOnMoon.getDayNumberOfWeek());     // Find last tuesdays for 2005     for (int i = 0; i < 12; i++) {       Day tuesday = Day.getLastOfMonth(Calendar.TUESDAY, i, 2005);       System.out.println(tuesday);     }   } }