A time-less Date class for basic date arithmetics : Day « Development Class « Java

Home
Java
1.2D Graphics GUI
2.3D
3.Advanced Graphics
4.Ant
5.Apache Common
6.Chart
7.Class
8.Collections Data Structure
9.Data Type
10.Database SQL JDBC
11.Design Pattern
12.Development Class
13.EJB3
14.Email
15.Event
16.File Input Output
17.Game
18.Generics
19.GWT
20.Hibernate
21.I18N
22.J2EE
23.J2ME
24.JDK 6
25.JNDI LDAP
26.JPA
27.JSP
28.JSTL
29.Language Basics
30.Network Protocol
31.PDF RTF
32.Reflection
33.Regular Expressions
34.Scripting
35.Security
36.Servlets
37.Spring
38.Swing Components
39.Swing JFC
40.SWT JFace Eclipse
41.Threads
42.Tiny Application
43.Velocity
44.Web Services SOA
45.XML
Java » Development Class » DayScreenshots 
A time-less Date class for basic date arithmetics


/*
 * (C) 2004 - Geotechnical Software Services
 
 * 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.util.Date;
import java.util.Calendar;
import java.util.TimeZone;
import java.io.Serializable;



/**
 * A time-less Date class for basic date arithmetics.
 *
 * Thanks to Paul Hill @ xmission.com for valuable contribution.
 *
 @author  Jacob Dreyer (<a href="mailto:jacob.dreyer@geosoft.no">jacob.dreyer@geosoft.no</a>)
 */   
public 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 (Calendarcalendar_.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 = (Dayobject;
    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 ?
                           : 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 (intMath.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 < || dayOfWeek > 6)
      throw new ArrayIndexOutOfBoundsException (dayOfWeek);
    
    Day first = new Day (year, month, 1);
    
    int offset = dayOfWeek - first.getDayOfWeek();
    if (offset < 0offset = + offset;
    
    int dayNo = (n - 1+ 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() 10string.append ('0');
    string.append (getDayOfMonth());
    string.append ('/');
    if (getMonth() 9string.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 (assasination1);

    // 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);
    }
  }
}


           
       
Related examples in the same category
1.A class representing a moment in time
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.