blob: c3090985d05724fc0e7639793bf104dfe6fa9152 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. The ASF licenses this file to You
* under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package org.apache.abdera2.common.date;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
/**
* <p>
* Provides an implementation of the RFC 3339 date-time.
* </p>
* <p>
* Accessors on this class are not synchronized.
* </p>
*/
public final class DateTime implements Cloneable, Serializable {
private static final long serialVersionUID = 3491429176989953135L;
private final Date value;
/**
* Create an AtomDate using the current date and time
*/
public DateTime() {
this(new Date());
}
/**
* Create an AtomDate using the serialized string format (e.g. 2003-12-13T18:30:02Z).
*
* @param value The serialized RFC3339 date/time value
*/
public DateTime(String value) {
this(parse(value));
}
/**
* Create an AtomDate using a java.util.Date
*
* @param value The java.util.Date value
* @throws NullPointerException if {@code date} is {@code null}
*/
public DateTime(Date value) {
this.value = (Date)value.clone();
}
/**
* Create an AtomDate using a java.util.Calendar.
*
* @param value The java.util.Calendar value
* @throws NullPointerException if {@code value} is {@code null}
*/
public DateTime(Calendar value) {
this(value.getTime());
}
/**
* Create an AtomDate using the number of milliseconds since January 1, 1970, 00:00:00 GMT
*
* @param value The number of milliseconds since January 1, 1970, 00:00:00 GMT
*/
public DateTime(long value) {
this(new Date(value));
}
/**
* Return the serialized string form of the Atom date
*
* @return the serialized string form of the date as specified by RFC4287
*/
public String getValue() {
return format(value);
}
/**
* Returns the value of this Atom Date
*
* @return A java.util.Date representing this Atom Date
*/
public Date getDate() {
// copy it in case the user decides to change the value since
// date objects themselves are not immutable
return (Date)value.clone();
}
/**
* Returns the value of this Atom Date as a java.util.Calendar
*
* @return A java.util.Calendar representing this Atom Date
*/
public Calendar getCalendar() {
Calendar cal = Calendar.getInstance();
cal.setTime(value);
return cal;
}
/**
* Returns the value of this Atom Date as the number of milliseconds since January 1, 1970, 00:00:00 GMT
*
* @return The number of milliseconds since January 1, 1970, 00:00:00 GMT
*/
public long getTime() {
return value.getTime();
}
@Override
public String toString() {
return getValue();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + value.hashCode();
return result;
}
@Override
public boolean equals(Object obj) {
boolean answer = false;
if (obj instanceof Date) {
Date d = (Date)obj;
answer = (this.value.equals(d));
} else if (obj instanceof String) {
Date d = parse((String)obj);
answer = (this.value.equals(d));
} else if (obj instanceof Calendar) {
Calendar c = (Calendar)obj;
answer = (this.value.equals(c.getTime()));
} else if (obj instanceof DateTime) {
Date d = ((DateTime)obj).value;
answer = (this.value.equals(d));
}
return answer;
}
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError(e);
}
}
private static boolean sep(char c) {
return "-:.TtZz+".indexOf(c) > -1;
}
public static Date parse(String date) {
if (date == null || date.length() == 0)
throw new IllegalArgumentException();
int nexttoken = 1;
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
cal.set(Calendar.MILLISECOND, 0);
cal.set(Calendar.SECOND,0);
cal.set(Calendar.MINUTE,0);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.DATE,1);
cal.set(Calendar.MONTH,0);
cal.set(Calendar.YEAR,0);
for (int s = 0, r = 0; r < date.length(); r++) {
char c = date.charAt(r);
if (sep(c) || r+1==date.length()) {
if (nexttoken == -1) {
String sub = date.substring(s-1);
TimeZone tz = TimeZone.getTimeZone("GMT"+sub);
cal.setTimeZone(tz);
break;
} else {
String sub = date.substring(s,r);
s = r+1;
int val = Integer.parseInt(sub);
switch(nexttoken) {
case 1:
cal.set(Calendar.YEAR, val);
nexttoken = c == '-' ? 2 : c == 'T' ? 8 : c == '.' ? 64 : -1;
break;
case 2:
cal.set(Calendar.MONTH, val-1);
nexttoken = c == '-' ? 4 : c == 'T' ? 8 : c == '.' ? 64 : -1;
break;
case 4:
cal.set(Calendar.DATE, val);
nexttoken = c == 'T' || c == 't' ? 8 : -1;
break;
case 8:
cal.set(Calendar.HOUR_OF_DAY, val);
nexttoken = c == ':' ? 16 : c == '.' ? 64 : -1;
break;
case 16:
cal.set(Calendar.MINUTE, val);
nexttoken = c == ':' ? 32 : c == '.' ? 64 : -1;
break;
case 32:
cal.set(Calendar.SECOND, val);
nexttoken = c == '.' ? 64 : -1;
break;
case 64:
cal.set(Calendar.MILLISECOND, val);
nexttoken = -1;
break;
}
}
}
}
return cal.getTime();
}
/**
* Create the serialized string form from a java.util.Date
*
* @param d A java.util.Date
* @return The serialized string form of the date
*/
public static String format(Date date) {
Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
c.setTime(date);
return String.format("%04d-%02d-%02dT%02d:%02d:%02d.%03dZ",
c.get(Calendar.YEAR),
c.get(Calendar.MONTH)+1,
c.get(Calendar.DATE),
c.get(Calendar.HOUR_OF_DAY),
c.get(Calendar.MINUTE),
c.get(Calendar.SECOND),
c.get(Calendar.MILLISECOND));
}
public static String formatNow() {
return format(new Date());
}
/**
* Create a new Atom Date instance from the serialized string form
*
* @param value The serialized string form of the date
* @return The created AtomDate
*/
public static DateTime valueOf(String value) {
return new DateTime(value);
}
/**
* Create a new Atom Date instance from a java.util.Date
*
* @param value a java.util.Date
* @return The created AtomDate
*/
public static DateTime valueOf(Date value) {
return new DateTime(value);
}
/**
* Create a new Atom Date instance from a java.util.Calendar
*
* @param value A java.util.Calendar
* @return The created AtomDate
*/
public static DateTime valueOf(Calendar value) {
return new DateTime(value);
}
/**
* Create a new Atom Date instance using the number of milliseconds since January 1, 1970, 00:00:00 GMT
*
* @param value The number of milliseconds since January 1, 1970, 00:00:00 GMT
* @return The created AtomDate
*/
public static DateTime valueOf(long value) {
return new DateTime(value);
}
}