DateValue.java
/*
** Module :DateValue.java
** Abstract :Date value holder.
**
** Copyright (c) 2005-2017, Golden Code Development Corporation.
**
** -#- -I- --Date-- -T- --JPRM-- ----------------Description-----------------
** 001 SIY 20050218 ADD @20017 Created initial version
** 002 SIY 20050310 CHG @20356 Organized imports and reordered methods.
** Fixed format string.
** Fixed month calculation.
** Fixed equals();
** 003 SIY 20050323 CHG @20470 Fixed formatting.
** 004 SIY 20050325 CHG @20493 Fixed format string.
** 005 SIY 20050328 CHG @20576 Added "implements Comparable" and cleared
** milliseconds field.
** 006 NVS 20050426 CHG @20890 Class implements Serializable interface.
** 007 SIY 20050429 CHG @21009 Fixed formatting.
** 008 EVL 20160223 Javadoc fixes to make compatible with Oracle Java 8 for
** Solaris 10.
** 009 IAS 20160331 Moved non-threadsafe format field to ThreadLocal
*/
/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** This program 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 Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
**
** Additional terms under GNU Affero GPL version 3 section 7:
**
** Under Section 7 of the GNU Affero GPL version 3, the following additional
** terms apply to the works covered under the License. These additional terms
** are non-permissive additional terms allowed under Section 7 of the GNU
** Affero GPL version 3 and may not be removed by you.
**
** 0. Attribution Requirement.
**
** You must preserve all legal notices or author attributions in the covered
** work or Appropriate Legal Notices displayed by works containing the covered
** work. You may not remove from the covered work any author or developer
** credit already included within the covered work.
**
** 1. No License To Use Trademarks.
**
** This license does not grant any license or rights to use the trademarks
** Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
** of Golden Code Development Corporation. You are not authorized to use the
** name Golden Code, FWD, or the names of any author or contributor, for
** publicity purposes without written authorization.
**
** 2. No Misrepresentation of Affiliation.
**
** You may not represent yourself as Golden Code Development Corporation or FWD.
**
** You may not represent yourself for publicity purposes as associated with
** Golden Code Development Corporation, FWD, or any author or contributor to
** the covered work, without written authorization.
**
** 3. No Misrepresentation of Source or Origin.
**
** You may not represent the covered work as solely your work. All modified
** versions of the covered work must be marked in a reasonable way to make it
** clear that the modified work is not originating from Golden Code Development
** Corporation or FWD. All modified versions must contain the notices of
** attribution required in this license.
*/
package com.goldencode.p2j.directory;
import java.text.DateFormat;
import java.text.FieldPosition;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.io.Serializable;
/**
* The main purpose of this class is to hold date value for storing/saving it
* in the Directory. Also it allows to distinguish types during processing
* (this is not so simple for java.util.Date and derivatives). For the
* convenience it can be easily converted to/from java.util.Date class.
*
* @author SIY
* @version 1.0
*/
public class DateValue
implements Comparable, Serializable
{
/**
* Format used for <code>DateValue</code> <-> <code>String</code>
* conversion.
*/
private static final ThreadLocal<SimpleDateFormat> format =
new ThreadLocal<SimpleDateFormat>()
{
@Override
protected SimpleDateFormat initialValue()
{
return new SimpleDateFormat("yyyy-MM-dd");
}
};
/** Internal instance of the Calendar */
private Calendar calendar;
/**
* Construct an instance for the current date.
*/
public DateValue()
{
calendar = Calendar.getInstance();
enforceTime(calendar.getTime());
}
/**
* Construct new instance from the instance of the <code>Date</code>.
*
* @param other
* An instance which is used as a source of the information.
*/
public DateValue(Date other)
{
calendar = Calendar.getInstance();
enforceTime(other);
}
/**
* Construct new instance from the other instance of the
* <code>DateValue</code>.
*
* @param other
* An instance which is used as a source of the information.
*/
public DateValue(DateValue other)
{
calendar = Calendar.getInstance();
enforceTime(other.getDate());
}
/**
* Construct an instance for specified date.
*
* @param year
* Year value for the new instance.
* @param month
* Month value for the new instance.
* @param day
* Day of the month value for the new instance.
*/
public DateValue(int year, int month, int day)
{
calendar = Calendar.getInstance();
calendar.set(year, month - 1, day, 0, 0, 0);
enforceTime(calendar.getTime());
}
/**
* Parse <code>String</code> like YYYYMMDD and create an instance of
* <code>DateValue</code>.
*
* @param str
* Source string.
* @return new <code>DateValue</code> instance or <code>null</code> if
* source string does not contain properly formatted date.
*/
public static DateValue valueOf(String str)
{
try
{
return new DateValue(format.get().parse(str, new ParsePosition(0)));
}
catch (Exception e)
{
return null;
}
}
/**
* Compares this instance with instance of <code>Date</code> for
* ordering.
*
* @param other
* The instance of <code>Date</code> to be compared.
* @return <code>0</code> if dates are equal; a value less than
* <code>0</code> if this instance date is before date of the
* passed parameter; a value greater than <code>0</code> if this
* instance date is after date of the parameter.
*/
public int compareTo(Date other)
{
return calendar.getTime().compareTo(other);
}
/**
* Compares two instances for ordering.
*
* @param other
* The instance to be compared.
* @return <code>0</code> if instances are equal; a value less than
* <code>0</code> if this instance date is before date of the
* instance passed as a parameter; a value greater than
* <code>0</code> if this instance date is after date of the
* instance passed as a parameter.
*/
public int compareTo(DateValue other)
{
return calendar.getTime().compareTo(other.getDate());
}
/**
* Compare this instance with other object.
*
* @param other
* The instance of <code>Date</code> to be compared.
* @return <code>0</code> if dates are equal; a value less than
* <code>0</code> if this instance date is before date of the
* passed parameter; a value greater than <code>0</code> if this
* instance date is after date of the parameter.
* @throws ClassCastException
* if argument is not instance of <code>Date</code> or
* <code>DateValue</code>.
*/
public int compareTo(Object other)
{
if (other instanceof Date)
return calendar.getTime().compareTo((Date)other);
return compareTo((DateValue)other);
}
/**
* Compares two objects for equality. Calls <code>Calendar.equals()</code>
* or <code>Date.equals()</code> if possible. Otherwise return
* <code>false</code>.
*
* @param o
* Object to compare with.
* @return <code>true</code> if instances are equal and
* <code>false</code> otherwise.
*/
public boolean equals(Object o)
{
if (o instanceof DateValue || o instanceof Calendar)
{
Calendar other;
if (o instanceof DateValue)
other = ((DateValue)o).calendar;
else
other = (Calendar)o;
if (calendar.get(Calendar.YEAR) == other.get(Calendar.YEAR)
&& calendar.get(Calendar.MONTH) == other.get(Calendar.MONTH)
&& calendar.get(Calendar.DATE) == other.get(Calendar.DATE))
{
return true;
}
return false;
}
if (o instanceof Date)
return getDate().equals(o);
return false;
}
/**
* Return current value represented as an instance of <code>Date</code>.
*
* @return an instance of <code>java.util.Date</code>.
*/
public Date getDate()
{
return calendar.getTime();
}
/**
* Return a hash code for the instance. Use <code>Date.hashCode()</code>
* for real computation.
*
* @return hash code for the instance.
*/
public int hashCode()
{
return calendar.getTime().hashCode();
}
/**
* Set current value using instance of <code>Date</code> as a source.
*
* @param date
* Source instance of <code>Date</code> to get values from.
*/
public void setDate(Date date)
{
enforceTime(date);
}
/**
* Convert <code>DateValue</code> instance into <code>String</code>.
*
* @return string in format YYYYMMMDD.
*/
public String toString()
{
StringBuffer buf = new StringBuffer();
format.get().format(getDate(), buf, new FieldPosition(DateFormat.YEAR_FIELD));
return buf.toString();
}
/**
* This method performs all necessary steps to enforce DateValue instance
* to contain only date, without time part.
*
* @param input
* <code>Date</code> instance to set information from.
*/
private void enforceTime(Date input)
{
//Make sure that time part is set to 0
calendar.setTime(input);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
}
}