/*******************************************************************************
* Copyright © 2011, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*
*******************************************************************************/
package org.eclipse.edt.runtime.java.eglx.lang;
import java.util.Calendar;
import java.util.GregorianCalendar;
import org.eclipse.edt.javart.AnyBoxedObject;
import org.eclipse.edt.javart.Constants;
import org.eclipse.edt.javart.messages.Message;
import org.eclipse.edt.javart.util.DateTimeUtil;
import org.eclipse.edt.javart.util.TimestampIntervalMask;
import eglx.lang.AnyException;
import eglx.lang.TypeCastException;
/**
* A class for Dates. The value is a Calendar.
* @author mheitz
*/
public class EDate extends AnyBoxedObject<Calendar> {
private static final long serialVersionUID = Constants.SERIAL_VERSION_UID;
public EDate() {
this(DateTimeUtil.getNewCalendar());
}
public EDate(Calendar value) {
super(value);
}
public static EDate ezeBox(Calendar value) {
Calendar clone = null;
if (value != null) {
clone = (Calendar) value.clone();
}
return new EDate(clone);
}
public static Calendar ezeCast(Object value) throws AnyException {
return (Calendar) EAny.ezeCast(value, "asDate", EDate.class, null, null);
}
public static boolean ezeIsa(Object value) {
return (value instanceof EDate && ((EDate) value).ezeUnbox() != null) || value instanceof Calendar;
}
public String toString() {
return EString.asString(EString.asStringDate(object));
}
public static Calendar defaultValue() {
long now = java.lang.System.currentTimeMillis();
Calendar cal = DateTimeUtil.getBaseCalendar();
cal.setTimeInMillis(now);
return cal;
}
public static Calendar asDate(EString date) throws TypeCastException {
if (date == null)
return null;
return asDate(date.ezeUnbox());
}
/**
* {@Operation narrow} Converts a string to a date. The string is parsed
* by searching for the month, then the day, then the year. One or two digits
* can be specified for the month and day. The year requires a minimum of one
* digit and a maximum of at least four digits (in other words, some implementations
* can support years beyond 9999). One separator character is required between
* the month and day, and another between the day and year. The separator
* character can be anything, even a digit (though that's probably a bad idea)
* and the two separator characters don't have to be identical.
*
* @throws TypeCastException if the string can't be parsed into a date.
*/
public static Calendar asDate(String date) throws TypeCastException {
if (date == null)
return null;
// Quick check for strings that are too long or too short.
int length = date.length();
if (length < 5 || length > 10) {
// Minimum is 5 characters: 1/1/1
// Maximum is 10 characters: 11/11/1111
TypeCastException tcx = new TypeCastException();
tcx.actualTypeName = "string";
tcx.castToName = "date";
throw tcx.fillInMessage( Message.CONVERSION_ERROR, date, tcx.actualTypeName, tcx.castToName );
}
int months = -1;
int days = -1;
int years = -1;
PARSE: {
// ch is the character we're currently looking at. i is the index of
// the next character after ch.
char ch;
int i;
// Read in the number of months.
ch = date.charAt(0);
if (ch < '0' || ch > '9') {
break PARSE;
}
months = ch - '0';
ch = date.charAt(1);
i = 2;
if ('0' <= ch && ch <= '9') {
months = months * 10 + ch - '0';
i++;
}
// Read in the number of days.
ch = date.charAt(i++);
if (ch < '0' || ch > '9') {
break PARSE;
}
days = ch - '0';
ch = date.charAt(i++);
if ('0' <= ch && ch <= '9') {
days = days * 10 + ch - '0';
i++;
}
// Read in the number of years.
if (i < length) {
int tempYears = 0;
ch = date.charAt(i++);
if ('0' <= ch && ch <= '9') {
tempYears = ch - '0';
if (i < length) {
ch = date.charAt(i++);
if ('0' <= ch && ch <= '9') {
tempYears = tempYears * 10 + ch - '0';
if (i < length) {
ch = date.charAt(i++);
if ('0' <= ch && ch <= '9') {
tempYears = tempYears * 10 + ch - '0';
if (i < length) {
ch = date.charAt(i++);
tempYears = tempYears * 10 + ch - '0';
}
}
}
}
}
}
if ( i == length && '0' <= ch && ch <= '9' )
{
years = tempYears;
}
}
}
// Make sure all required fields were found.
if (months == -1 || days == -1 || years == -1) {
TypeCastException tcx = new TypeCastException();
tcx.actualTypeName = "string";
tcx.castToName = "date";
throw tcx.fillInMessage( Message.CONVERSION_ERROR, date, tcx.actualTypeName, tcx.castToName );
}
// The last thing to do is put the values into a Calendar.
Calendar cal = DateTimeUtil.getBaseCalendar();
cal.set(Calendar.YEAR, years);
cal.set(Calendar.MONTH, months - 1);
cal.set(Calendar.DATE, days);
// Verify that the values are valid.
try {
cal.setTimeInMillis(cal.getTimeInMillis());
}
catch (Exception ex) {
TypeCastException tcx = new TypeCastException();
tcx.actualTypeName = "string";
tcx.castToName = "date";
tcx.initCause( ex );
throw tcx.fillInMessage( Message.CONVERSION_ERROR, date, tcx.actualTypeName, tcx.castToName );
}
return cal;
}
public static Calendar asDate(EDate date) throws AnyException {
if (date == null)
return null;
return asDate(date.ezeUnbox());
}
public static Calendar asDate(ETimestamp date) throws AnyException {
if (date == null)
return null;
return asDate(date.ezeUnbox(), date.getStartCode(), date.getEndCode());
}
public static Calendar asDate(GregorianCalendar date) throws AnyException {
if (date == null)
return null;
return asDate((Calendar) date);
}
public static Calendar asDate(Calendar date) throws AnyException {
if (date == null)
return null;
return asDate(date, ETimestamp.YEAR_CODE, ETimestamp.DAY_CODE);
}
public static Calendar asDate(Calendar original, int startCode, int endCode) {
if (original == null)
return null;
// Make sure all required fields were found.
if (startCode > ETimestamp.YEAR_CODE || endCode < ETimestamp.DAY_CODE) {
TypeCastException tcx = new TypeCastException();
tcx.actualTypeName = "timestamp(\"" + ETimestamp.createMask( startCode, endCode ) + "\")";
tcx.castToName = "date";
throw tcx.fillInMessage( Message.CONVERSION_ERROR, original, tcx.actualTypeName, tcx.castToName );
}
Calendar cal = (Calendar) original.clone();
Calendar result = DateTimeUtil.getBaseCalendar();
// Get values for the full set of fields. Fields that we need will be
// set from the calendar. The others will be set to reasonable defaults.
result.set(Calendar.YEAR, cal.get(Calendar.YEAR));
result.set(Calendar.MONTH, cal.get(Calendar.MONTH));
result.set(Calendar.DATE, cal.get(Calendar.DATE));
try {
result.setTimeInMillis(result.getTimeInMillis());
}
catch (Exception ex) {
TypeCastException tcx = new TypeCastException();
tcx.actualTypeName = "timestamp(\"" + ETimestamp.createMask( startCode, endCode ) + "\")";
tcx.castToName = "date";
tcx.initCause( ex );
throw tcx.fillInMessage( Message.CONVERSION_ERROR, original, tcx.actualTypeName, tcx.castToName );
}
return result;
}
public static int compareTo(Calendar op1, Calendar op2) {
return op1.compareTo(op2);
}
public static boolean equals(Calendar op1, Calendar op2) {
if (op1 == op2)
return true;
if (op1 == null || op2 == null)
return false;
return op1.get(Calendar.YEAR) == op2.get(Calendar.YEAR) && op1.get(Calendar.MONTH) == op2.get(Calendar.MONTH)
&& op1.get(Calendar.DATE) == op2.get(Calendar.DATE);
}
public static boolean notEquals(Calendar op1, Calendar op2) {
return !equals(op1, op2);
}
/**
* Returns the difference between 2 dates
*/
public static int daysDifferent(EDate aDate, EDate bDate) throws AnyException {
aDate.ezeUnbox().setTimeInMillis(aDate.ezeUnbox().getTimeInMillis());
bDate.ezeUnbox().setTimeInMillis(bDate.ezeUnbox().getTimeInMillis());
return (int) ((aDate.ezeUnbox().getTimeInMillis() - bDate.ezeUnbox().getTimeInMillis()) / (1000 * DateTimeUtil.SECONDS_PER_DAY));
}
/**
* Returns the adds days to a date
*/
public static Calendar addDays(EDate original, int amount) throws AnyException {
Calendar aDate = (Calendar) original.ezeUnbox().clone();
aDate.setLenient(true);
aDate.add(Calendar.DATE, amount);
try {
aDate.setTimeInMillis(aDate.getTimeInMillis());
}
catch (Exception ex) {
}
return new EDate(aDate).ezeUnbox();
}
/**
* Returns the extension of a date
*/
public static Calendar extend(EDate aDate, String timeSpanPattern) throws AnyException {
// Default values in case the pattern doesn't specify things.
int startCode = ETimestamp.YEAR_CODE;
int endCode = ETimestamp.SECOND_CODE;
TimestampIntervalMask mask = new TimestampIntervalMask(timeSpanPattern);
if (mask.getStartCode() != -1 && mask.getStartCode() <= mask.getEndCode()) {
startCode = mask.getStartCode();
endCode = mask.getEndCode();
}
return ETimestamp.asTimestamp(aDate, startCode, endCode);
}
/**
* Returns the day portion of this date field.
*
* @return the day portion of this date field.
*/
public static int dayOf( EDate date )
{
return date.ezeUnbox().get( Calendar.DAY_OF_MONTH );
}
/**
* Returns the month portion of this date field.
*
* @return the month portion of this date field.
*/
public static int monthOf( EDate date )
{
return date.ezeUnbox().get( Calendar.MONTH ) + 1;
}
/**
* Returns the year portion of this date field.
*
* @return the year portion of this date field.
*/
public static int yearOf( EDate date )
{
return date.ezeUnbox().get( Calendar.YEAR );
}
}