/**
* Copyright 2005-2014 Restlet
*
* The contents of this file are subject to the terms of one of the following
* open source licenses: Apache 2.0 or or EPL 1.0 (the "Licenses"). You can
* select the license that you prefer but you may not use this file except in
* compliance with one of these Licenses.
*
* You can obtain a copy of the Apache 2.0 license at
* http://www.opensource.org/licenses/apache-2.0
*
* You can obtain a copy of the EPL 1.0 license at
* http://www.opensource.org/licenses/eclipse-1.0
*
* See the Licenses for the specific language governing permissions and
* limitations under the Licenses.
*
* Alternatively, you can obtain a royalty free commercial license with less
* limitations, transferable or non-transferable, directly at
* http://restlet.com/products/restlet-framework
*
* Restlet is a registered trademark of Restlet S.A.S.
*/
package org.restlet.engine.util;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
/**
* Date manipulation utilities.
*
* @author Jerome Louvel
*/
public final class DateUtils {
/**
* Obsoleted HTTP date format (ANSI C asctime() format). Pattern:
* "EEE MMM dd HH:mm:ss yyyy".
*/
public static final List<String> FORMAT_ASC_TIME = unmodifiableList("EEE MMM dd HH:mm:ss yyyy");
/**
* Obsoleted HTTP date format (RFC 1036). Pattern:
* "EEEE, dd-MMM-yy HH:mm:ss zzz".
*/
public static final List<String> FORMAT_RFC_1036 = unmodifiableList("EEEE, dd-MMM-yy HH:mm:ss zzz");
/**
* Preferred HTTP date format (RFC 1123). Pattern:
* "EEE, dd MMM yyyy HH:mm:ss zzz".
*/
public static final List<String> FORMAT_RFC_1123 = unmodifiableList("EEE, dd MMM yyyy HH:mm:ss zzz");
/** W3C date format (RFC 3339). Pattern: "yyyy-MM-dd'T'HH:mm:ssz". */
public static final List<String> FORMAT_RFC_3339 = unmodifiableList("yyyy-MM-dd'T'HH:mm:ssz");
/** AWS date format (ISO 8601). Pattern: "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'". */
public static final List<String> FORMAT_ISO_8601 = unmodifiableList("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
/**
* Common date format (RFC 822). Patterns: "EEE, dd MMM yy HH:mm:ss z" or
* "EEE, dd MMM yy HH:mm z", "dd MMM yy HH:mm:ss z" or "dd MMM yy HH:mm z".
*/
public static final List<String> FORMAT_RFC_822 = unmodifiableList(
"EEE, dd MMM yy HH:mm:ss z", "EEE, dd MMM yy HH:mm z",
"dd MMM yy HH:mm:ss z", "dd MMM yy HH:mm z");
// [ifndef gwt] member
/** Remember the often used GMT time zone. */
private static final java.util.TimeZone TIMEZONE_GMT = java.util.TimeZone
.getTimeZone("GMT");
// [ifdef gwt] member uncomment
// private static final com.google.gwt.i18n.client.TimeZone TIMEZONE_GMT =
// com.google.gwt.i18n.client.TimeZone.createTimeZone(0);
/**
* Compares two date with a precision of one second.
*
* @param baseDate
* The base date
* @param afterDate
* The date supposed to be after.
* @return True if the afterDate is indeed after the baseDate.
*/
public static boolean after(final Date baseDate, final Date afterDate) {
if ((baseDate == null) || (afterDate == null)) {
throw new IllegalArgumentException(
"Can't compare the dates, at least one of them is null");
}
long baseTime = baseDate.getTime() / 1000;
long afterTime = afterDate.getTime() / 1000;
return baseTime < afterTime;
}
/**
* Compares two date with a precision of one second.
*
* @param baseDate
* The base date
* @param beforeDate
* The date supposed to be before.
* @return True if the beforeDate is indeed before the baseDate.
*/
public static boolean before(final Date baseDate, final Date beforeDate) {
if ((baseDate == null) || (beforeDate == null)) {
throw new IllegalArgumentException(
"Can't compare the dates, at least one of them is null");
}
long baseTime = baseDate.getTime() / 1000;
long beforeTime = beforeDate.getTime() / 1000;
return beforeTime < baseTime;
}
/**
* Compares two date with a precision of one second.
*
* @param baseDate
* The base date
* @param otherDate
* The other date supposed to be equals.
* @return True if both dates are equals.
*/
public static boolean equals(final Date baseDate, final Date otherDate) {
if ((baseDate == null) || (otherDate == null)) {
throw new IllegalArgumentException(
"Can't compare the dates, at least one of them is null");
}
long baseTime = baseDate.getTime() / 1000;
long otherTime = otherDate.getTime() / 1000;
return otherTime == baseTime;
}
/**
* Formats a Date in the default HTTP format (RFC 1123).
*
* @param date
* The date to format.
* @return The formatted date.
*/
public static String format(final Date date) {
return format(date, DateUtils.FORMAT_RFC_1123.get(0));
}
/**
* Formats a Date according to the first format in the array.
*
* @param date
* The date to format.
* @param formats
* The array of date formats to use.
* @return The formatted date.
*/
public static String format(final Date date, final List<String> formats) {
return format(date, formats != null ? formats.get(0) : null);
}
/**
* Formats a Date according to the given format.
*
* @param date
* The date to format.
* @param format
* The date format to use.
* @return The formatted date.
*/
public static String format(final Date date, final String format) {
if (date == null) {
throw new IllegalArgumentException("Date is null");
}
// [ifndef gwt]
java.text.DateFormat formatter = null;
if (FORMAT_RFC_3339.get(0).equals(format)) {
formatter = new InternetDateFormat(TIMEZONE_GMT);
} else {
formatter = new java.text.SimpleDateFormat(format,
java.util.Locale.US);
formatter.setTimeZone(TIMEZONE_GMT);
}
return formatter.format(date);
// [enddef]
// [ifdef gwt]
/*
* GWT difference: DateTimeFormat parser is not passed a Locale in the
* same way as SimpleDateFormat. It derives locale information from the
* GWT application's locale.
*
* Default timezone is GMT unless specified via a GMT:hhmm, GMT:+hhmm,
* or GMT:-hhmm string.
*/
// [enddef]
// [ifdef gwt] uncomment
// final com.google.gwt.i18n.client.DateTimeFormat formatter =
// com.google.gwt.i18n.client.DateTimeFormat.getFormat(format);
// return formatter.format(date, TIMEZONE_GMT);
// [enddef]
}
/**
* Parses a formatted date into a Date object using the default HTTP format
* (RFC 1123).
*
* @param date
* The date to parse.
* @return The parsed date.
*/
public static Date parse(String date) {
return parse(date, FORMAT_RFC_1123);
}
/**
* Parses a formatted date into a Date object.
*
* @param date
* The date to parse.
* @param formats
* The date formats to use sorted by completeness.
* @return The parsed date.
*/
public static Date parse(String date, List<String> formats) {
Date result = null;
if (date == null) {
throw new IllegalArgumentException("Date is null");
}
String format = null;
int formatsSize = formats.size();
for (int i = 0; (result == null) && (i < formatsSize); i++) {
format = formats.get(i);
// [ifndef gwt]
java.text.DateFormat parser = null;
if (FORMAT_RFC_3339.get(0).equals(format)) {
parser = new InternetDateFormat(TIMEZONE_GMT);
} else {
parser = new java.text.SimpleDateFormat(format,
java.util.Locale.US);
parser.setTimeZone(TIMEZONE_GMT);
}
// [enddef]
// [ifdef gwt]
/*
* GWT difference: DateTimeFormat parser is not passed a Locale in
* the same way as SimpleDateFormat. It derives locale information
* from the GWT application's locale.
*
* Default timezone is GMT unless specified via a GMT:hhmm,
* GMT:+hhmm, or GMT:-hhmm string.
*/
// [enddef]
// [ifdef gwt] uncomment
// final com.google.gwt.i18n.client.DateTimeFormat parser =
// com.google.gwt.i18n.client.DateTimeFormat.getFormat(format);
// [enddef]
try {
result = parser.parse(date);
} catch (Exception e) {
// Ignores error as the next format may work better
}
}
return result;
}
/**
* Returns an immutable version of a given date.
*
* @param date
* The modifiable date.
* @return An immutable version of a given date.
*/
public static Date unmodifiable(Date date) {
return (date == null) ? null : new ImmutableDate(date);
}
/**
* Helper method to help initialize this class by providing unmodifiable
* lists based on arrays.
*
* @param <T>
* Any valid java object
* @param array
* to be converted into an unmodifiable list
* @return unmodifiable list based on the provided array
*/
@SafeVarargs
private static <T> List<T> unmodifiableList(final T... array) {
return Collections.unmodifiableList(Arrays.asList(array));
}
/**
* Private constructor to ensure that the class acts as a true utility class
* i.e. it isn't instantiable and extensible.
*/
private DateUtils() {
}
}