org.openadaptor.util
Class DateHolder

java.lang.Object
  extended by org.openadaptor.util.DateHolder
All Implemented Interfaces:
java.io.Serializable, java.lang.Comparable
Direct Known Subclasses:
DateTimeHolder

public class DateHolder
extends java.lang.Object
implements java.io.Serializable, java.lang.Comparable

DateHolder represents a straightforward date, with no time. It is used for holding dates in DataObjects, and converting from a string representation to numeric values for day, month, year and vice versa. It is immutable - once the DateHolder is created, the date in it cannot be changed.

It checks the validity of the date with which it is created, but it not encyclopaedic in its knowledge so does not handle the calendar changes which took place in the eighteenth century in England and earlier for Johnny Foreigner.

Some notes about the date values:

A note on TimeZones
In earlier versions of the DateHolder the timezone string was an optional String appended to a date string, but otherwise unused within DateHolders. Now that DateHolders can be constructed from Dates, and can return Date objects with equivalent values (see asDate()), the timezone is essential for performing the conversion, so the default timezone form is a java.util.TimeZone, and all the standard DateHolder constructors now require an TimeZone parameter, or are deprecated. These deprecated constructors default to the local timezone, but can be made to default to the GMT/UTC timezone by setting a system property oa.date.defaultTZ=GMT. A null TimeZone parameter in a constructor implies the system local TimeZone, but for backwards compatibility reasons, calls to toString() on instances given null timezones will not output timezone strings.

DateHolder has a standard text form (yyyy-mm-dd tz) which is used for serialising DateHolder values into DataObject XML and back again into DateHolders. The methods used to read and generate this form are DateHolder.parseDate() and toString(). If you wish to convert to and from arbitrary date strings, you should use java.text.SimpleDateFormat which uses Java Dates and Calendars, and convert the Dates to/from DateHolders. For an example of how to do this, look at the source code of DateFormatTransformer.

Version:
2.0
Author:
Tim Bissell
See Also:
DateTimeHolder, SimpleDateFormat, Date, TimeZone, DateFormatTransformer, Serialized Form

Field Summary
protected  byte _date
          Day of month 1..{28-31}
protected  byte _month
          Month 0..11
protected  java.lang.String _stringValue
          cached string representation of the date
protected  java.lang.String _timezone
          Deprecated. - Please start using _tz
protected  java.util.TimeZone _tz
          TimeZone of the date
protected static boolean _warnThisUse
          Used to print a warning the first time that a deprecated constructor is used.
protected  short _year
          Year YEAR_MIN..YEAR_MAX
static java.util.TimeZone DEFAULT_TZ
          The TimeZone used in DateHolder creation where no TimeZone is provided.
static java.util.TimeZone GMT
          Convenience GMT TimeZone reference
static java.lang.String GMT_STR
          Default (GMT) timezone string
static short INVALID_DATE
          Useful invalid date value
static short INVALID_MONTH
          Useful invalid month value
static short INVALID_YEAR
          Useful invalid year value
static java.util.TimeZone LOCAL
          Convenience Local (system) TimeZone reference
(package private) static org.apache.log4j.Logger log
           
protected static int[] monthSizes
          An array of twelve byte values representing the number of days in each month in a non-leap year
protected  boolean noTimezone
          No timezone set, so do not output a timezone in toString() forms
(package private) static long serialVersionUID
           
static short YEAR_MAX
          Last handled year
static short YEAR_MIN
          First handled year
 
Constructor Summary
DateHolder()
          Initialises a new DateHolder to the current date in the default timezone.
DateHolder(java.util.Calendar cal)
          Initialises a new DateHolder to the date specified.
DateHolder(java.util.Date date)
          Deprecated. Please use the constructors taking (Date, TimeZone) or (Calendar) parameters instead.
DateHolder(java.util.Date date, java.util.TimeZone tz)
          Initialises a new DateHolder to the date specified.
DateHolder(int year, int month, int date)
          Deprecated. Please use the constructor taking (year,month,day,tz) parameters with an explicit TimeZone.
DateHolder(int year, int month, int date, java.lang.String timezone)
          Deprecated. Please use the constructor taking (year,month,day,tz) parameters with an explicit TimeZone.
DateHolder(int year, int month, int date, java.util.TimeZone tz)
          Initialises a new DateHolder to the date specified.
DateHolder(java.lang.String str)
          Constructs a DateHolder from a DOXML standard string definition.
 
Method Summary
 java.util.Calendar asCalendar()
          Returns the date/time value as a new java.util.Calendar object.
 java.util.Date asDate()
          Returns the date value as a new java.util.Date object.
 int compareTo(java.lang.Object o)
          Compares this date with the specified DateHolder for order.
static int daysInMonth(int month, int year)
          Returns the number of days in the given month, allowing for leap years if year is a leap year.
 boolean equals(java.lang.Object o)
          Returns true if the argument is a DateHolder containing the same date.
 int getDate()
          Returns the day of the month, in the range 1..31.
 int getMonth()
          Returns the month number, in the range 0..11.
 java.lang.String getTimezone()
          Deprecated. Use TimeZones and getTimeZoneString() instead.
 java.util.TimeZone getTimeZone()
          Returns the TimeZone.
protected  java.lang.String getTimezoneString()
          Returns a string representing the timezone.
 int getTrueYear()
          Returns the year value, an integer in the range YEAR_MIN..YEAR_MAX.
 int getYear()
          Returns a java.util.Date compatible year value - year minus 1900.
 int hashCode()
          Returns the hashcode for this date.
static boolean isLeapYear(int year)
          Returns true if year is a leap year
static void main(java.lang.String[] args)
          A thorough check of the date parsing and formatting routines, and a simple test of some illegal values
static DateHolder parseDate(java.lang.String dateStr)
          Reads a date string and attempts to create a DateHolder object for it.
protected  void set(java.util.Calendar cal)
          For use in constructors only.
 java.lang.String toISOString()
          Returns an ISO-8601 standard date of the form YYYY-MM-DD.
 java.lang.String toString()
          Returns a standard format string representation of the date.
static DateHolder valueOfDate(java.lang.String s)
          Parses s as a Date string, and returns the DateHolder result.
protected  java.lang.String ymdToString()
          Returns the year, month and day in YYYY-MM-DD format.
 
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
 

Field Detail

serialVersionUID

static final long serialVersionUID
See Also:
Constant Field Values

log

static org.apache.log4j.Logger log

YEAR_MIN

public static final short YEAR_MIN
First handled year

See Also:
Constant Field Values

YEAR_MAX

public static final short YEAR_MAX
Last handled year

See Also:
Constant Field Values

INVALID_YEAR

public static final short INVALID_YEAR
Useful invalid year value

See Also:
Constant Field Values

INVALID_MONTH

public static final short INVALID_MONTH
Useful invalid month value

See Also:
Constant Field Values

INVALID_DATE

public static final short INVALID_DATE
Useful invalid date value

See Also:
Constant Field Values

GMT_STR

public static final java.lang.String GMT_STR
Default (GMT) timezone string

See Also:
Constant Field Values

GMT

public static final java.util.TimeZone GMT
Convenience GMT TimeZone reference


LOCAL

public static final java.util.TimeZone LOCAL
Convenience Local (system) TimeZone reference


DEFAULT_TZ

public static java.util.TimeZone DEFAULT_TZ
The TimeZone used in DateHolder creation where no TimeZone is provided. Defaults to the system local timezone, but can be set to GMT for backwards compatibility. (set the system oa.date.defaultTZ=GMT property).


monthSizes

protected static final int[] monthSizes
An array of twelve byte values representing the number of days in each month in a non-leap year


_warnThisUse

protected static boolean _warnThisUse
Used to print a warning the first time that a deprecated constructor is used.


noTimezone

protected final boolean noTimezone
No timezone set, so do not output a timezone in toString() forms


_date

protected byte _date
Day of month 1..{28-31}


_month

protected byte _month
Month 0..11


_year

protected short _year
Year YEAR_MIN..YEAR_MAX

See Also:
YEAR_MIN, YEAR_MAX

_tz

protected java.util.TimeZone _tz
TimeZone of the date


_timezone

protected java.lang.String _timezone
Deprecated. - Please start using _tz
Timezone string - user defined.
ROADMAP
This constructor will be deleted after openadaptor 1.5.1.


_stringValue

protected java.lang.String _stringValue
cached string representation of the date

Constructor Detail

DateHolder

public DateHolder(java.lang.String str)
           throws java.lang.Exception
Constructs a DateHolder from a DOXML standard string definition.

Parameters:
str - DOXML standard string.
Throws:
java.lang.Exception
See Also:
toString()

DateHolder

public DateHolder()
Initialises a new DateHolder to the current date in the default timezone.


DateHolder

public DateHolder(java.util.Date date)
           throws java.lang.Exception
Deprecated. Please use the constructors taking (Date, TimeZone) or (Calendar) parameters instead.

Initialises a new DateHolder to the date specified in the GMT timezone.
ROADMAP
This constructor will be deleted some time after openadaptor 1.5.1.

Parameters:
date - Date value. Note that default constructor timezone (currently GMT) is used.
Throws:
java.lang.Exception - If any of the year, month, date values are invalid (e.g. month=12) or inconsistent (e.g. month=1(feb), date=30)

DateHolder

public DateHolder(java.util.Date date,
                  java.util.TimeZone tz)
           throws java.lang.Exception
Initialises a new DateHolder to the date specified.

Parameters:
date - Date value
tz - TimeZone of date value; the system default is used if tz is null.
Throws:
java.lang.Exception - If any of the year, month, date values are invalid (e.g. month=13) or inconsistent (e.g. month=1(feb), date=30)

DateHolder

public DateHolder(java.util.Calendar cal)
           throws java.lang.Exception
Initialises a new DateHolder to the date specified.

Parameters:
cal - Calendar defining date and timezone.
Throws:
java.lang.Exception - If any of the year, month, date values are invalid (e.g. month=12) or inconsistent (e.g. month=1(feb), date=30)

DateHolder

public DateHolder(int year,
                  int month,
                  int date)
           throws java.lang.Exception
Deprecated. Please use the constructor taking (year,month,day,tz) parameters with an explicit TimeZone.

Initialises a new DateHolder to the date specified. Note: the default timezone is GMT, not the system local timezone. For behaviour consistent with java.util.Date, use a non-deprecated constructor which takes a TimeZone parameter and defaults to the system local timezone when called with a null TimeZone.
ROADMAP
This constructor will be deleted after openadaptor 1.5.1.

Parameters:
year - The year value, if less than 500 treated as year - 1900; this is for java.util.Date compatibility.
month - The month value, 0..11.
date - The day value, 1..31
Throws:
java.lang.Exception - If any of the year, month, date values are invalid (e.g. month=12) or inconsistent (e.g. month=1(feb), date=30)

DateHolder

public DateHolder(int year,
                  int month,
                  int date,
                  java.lang.String timezone)
           throws java.lang.Exception
Deprecated. Please use the constructor taking (year,month,day,tz) parameters with an explicit TimeZone.

Initialises a new DateHolder to the date specified. Note: the default timezone is GMT, not the system local timezone. For behaviour consistent with java.util.Date, use a non-deprecated constructor which takes a TimeZone parameter and defaults to the system local timezone when called with a null TimeZone.
ROADMAP
This constructor will be deleted after openadaptor 1.5.1.

Parameters:
year - The year value, if less than 500 treated as year - 1900 this is for java.util.Date compatibility.
month - The month value, 0..11
date - The day value, 1..31
timezone - Timezone string, or null (implies the default timezone).
Throws:
java.lang.Exception - If any of the year, month, date values are invalid (e.g. month=12) or inconsistent (e.g. month=1(feb), date=30)

DateHolder

public DateHolder(int year,
                  int month,
                  int date,
                  java.util.TimeZone tz)
           throws java.lang.Exception
Initialises a new DateHolder to the date specified.

Parameters:
year - The year value, if less than 500 treated as year - 1900 this is for java.util.Date compatibility.
month - The month value, 0..11
date - The day value, 1..31
tz - Timezone string, or null.
Throws:
java.lang.Exception - If any of the year, month, date values are invalid (e.g. month=12) or inconsistent (e.g. month=1(feb), date=30)
Method Detail

valueOfDate

public static DateHolder valueOfDate(java.lang.String s)
                              throws java.lang.IllegalArgumentException
Parses s as a Date string, and returns the DateHolder result. Expected date format is ISO8601: yyyy-MM-dd

Parameters:
s - Date string.
Returns:
new DateHolder instance.
Throws:
java.lang.IllegalArgumentException - If s cannot be parsed as a valid date.

isLeapYear

public static boolean isLeapYear(int year)
                          throws java.lang.Exception
Returns true if year is a leap year

Returns:
true is year is a leap year.
Throws:
java.lang.Exception - If year is outside the range YEAR_MIN..YEAR_MAX

daysInMonth

public static int daysInMonth(int month,
                              int year)
Returns the number of days in the given month, allowing for leap years if year is a leap year.


parseDate

public static DateHolder parseDate(java.lang.String dateStr)
                            throws java.lang.Exception
Reads a date string and attempts to create a DateHolder object for it. This method is used to de-serialise a DateHolder written out in the standard serialised format produced by toString(). See toString() for details of this format.

Parameters:
dateStr - String containing text representation of date.
Returns:
New DateHolder representing the date in the date string.
Throws:
java.lang.Exception - If the string cannot be parsed as a valid date.
See Also:
toString()

set

protected void set(java.util.Calendar cal)
            throws java.lang.Exception
For use in constructors only. Finishes construction by setting receiver properties from calendar. Is protected, so should only be called by set() methods in subclasses.

Parameters:
cal - Calendar containing date/timezone properties.
Throws:
java.lang.Exception - If any of the year, month, date values are invalid (e.g. month=13) or inconsistent (e.g. month=1(feb), date=30)

getTrueYear

public int getTrueYear()
Returns the year value, an integer in the range YEAR_MIN..YEAR_MAX.


getYear

public int getYear()
Returns a java.util.Date compatible year value - year minus 1900.


getMonth

public int getMonth()
Returns the month number, in the range 0..11. The 0..11 range is for java.util.Date compatibility.


getDate

public int getDate()
Returns the day of the month, in the range 1..31.


getTimezone

public java.lang.String getTimezone()
Deprecated. Use TimeZones and getTimeZoneString() instead.

Returns the timezone string. NOTE If the receiver has a TimeZone set, this method will return null.

Returns:
A String representing the timezone, or null.

getTimeZone

public java.util.TimeZone getTimeZone()
Returns the TimeZone. If the receiver was constructed with a TimeZone, then that TimeZone is returned.
If the receiver was constructed with a (deprecated) timezone string, then the string is parsed in an attempt to generate a TimeZone.
The timezone string should either be an offset (+/-hh:mm or GMT+/-hh:mm) or a valid TimeZone ID (e.g. Europe/London).

Returns:
TimeZone of DateHolder, or the default if timezone string not recognised or defined.

asDate

public java.util.Date asDate()
Returns the date value as a new java.util.Date object. If the DateHolder was not defined with a Java TimeZone or a valid timezone string (see getTimeZone()) then it assumes GMT.

Returns:
Date with same value as receiver.
See Also:
getTimeZone()

asCalendar

public java.util.Calendar asCalendar()
Returns the date/time value as a new java.util.Calendar object. If the DateTimeHolder was not defined with a Java TimeZone or a valid timezone string (see getTimeZone()) then it assumes the default timezone.

Returns:
Date with same value as receiver.
See Also:
getTimeZone()

toString

public java.lang.String toString()
Returns a standard format string representation of the date. This format is an ISO 8601 variant which is used as the standard serialised form of DateHolders in openadaptor.

The format used is: YYYY-MM-DD ZZ.

The timezone (ZZ) is optional, and if specified, will have an '@' prefix if it is a Java TimeZone ID, otherwise it will be an arbitrary string.
For example 1997-02-14 is February 14, 1997 and 1997-02-14 @Europe/London is February 14, 1997, in the Java 'Europe/London' timezone.
Spaces before the date and anything after the date (if there is no timezone) are ignored.

If you wish to generate Date strings for consumption by non-openadaptor systems, convert the DateHolder into a Date (asDate()), and use java.text.SimpleDateFormat to do so.

The value returned is cached, as the date value is immutable.

Overrides:
toString in class java.lang.Object
Returns:
Openadaptor standard-format date string.
See Also:
parseDate(java.lang.String)

getTimezoneString

protected java.lang.String getTimezoneString()
Returns a string representing the timezone.

Returns:
A string representing the timezone, or null if no timezone is specified.

toISOString

public java.lang.String toISOString()
Returns an ISO-8601 standard date of the form YYYY-MM-DD. Note, this differs from toString only in that it does not include the timezone and is not cached.

Returns:
Date string of the form YYYY-MM-DD.
See Also:
toString(), ymdToString()

ymdToString

protected java.lang.String ymdToString()
Returns the year, month and day in YYYY-MM-DD format. For use in subclasses. The value returned is not cached, as it is intended to be copied into other cached strings.


equals

public boolean equals(java.lang.Object o)
Returns true if the argument is a DateHolder containing the same date. We have tightened the definition of 'equal' such that a DateTimeHolder can only equal a DateHolder if the date and timezone are the same, and hours/minutes/seconds/milliseconds are all zero (in openadaptor 1.5.0 and earlier, any time was OK)

Overrides:
equals in class java.lang.Object
Parameters:
o - Jave object for comparison
Returns:
true if the objects are equal.

hashCode

public int hashCode()
Returns the hashcode for this date. Note that a DateHolder is immutable (unlike java.utilDate) so this hashCode will never change, and thus can be used as a key.

Overrides:
hashCode in class java.lang.Object

compareTo

public int compareTo(java.lang.Object o)
Compares this date with the specified DateHolder for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.

Date comparisons are transitive and commutative, but because of different timezone representations, Dates have a natural ordering that is inconsistent with equals.

Specified by:
compareTo in interface java.lang.Comparable
Parameters:
o - the Object to be compared.
Returns:
a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
Throws:
java.lang.ClassCastException - if the specified object's type prevents it from being compared to this Object.

main

public static void main(java.lang.String[] args)
A thorough check of the date parsing and formatting routines, and a simple test of some illegal values