/*
* The MIT License (MIT)
*
* Copyright (c) 2015 Lachlan Dowding
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package permafrost.tundra.time;
import permafrost.tundra.lang.ArrayHelper;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Map;
import java.util.SortedSet;
import java.util.TimeZone;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.bind.DatatypeConverter;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.Duration;
import javax.xml.datatype.XMLGregorianCalendar;
/**
* A collection of convenience methods for working with datetimes.
*/
public final class DateTimeHelper {
/**
* The default pattern used, when none is specified.
*/
public static final String DEFAULT_DATETIME_PATTERN = "datetime";
/**
* List of well-known named patterns.
*/
private static final Map<String, String> NAMED_PATTERNS = new TreeMap<String, String>();
/**
* DB2 specific datetime pattern.
*/
private static final Pattern DB2_DATETIME_PATTERN = Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})-(\\d{2})\\.(\\d{2})\\.(\\d{2})\\.(\\d{6})");
static {
// Initialize the list of well-known named patterns.
NAMED_PATTERNS.put("datetime.jdbc", "yyyy-MM-dd HH:mm:ss.SSS");
NAMED_PATTERNS.put("datetime.db2", "yyyy-MM-dd-HH.mm.ss.SSS'000'");
NAMED_PATTERNS.put("date", "yyyy-MM-dd");
NAMED_PATTERNS.put("date.jdbc", "yyyy-MM-dd");
NAMED_PATTERNS.put("date.xml", "yyyy-MM-dd");
NAMED_PATTERNS.put("time", "HH:mm:ss.SSS");
NAMED_PATTERNS.put("time.jdbc", "HH:mm:ss");
NAMED_PATTERNS.put("time.xml", "HH:mm:ss.SSS");
}
/**
* Disallow instantiation of this class.
*/
private DateTimeHelper() {}
/**
* Adds the given XML duration to the given datetime.
*
* @param date The Date to add the duration to.
* @param duration The duration to be added.
* @return A new Date representing the given date's time plus the given duration.
*/
public static Date add(Date date, Duration duration) {
return toDate(add(toCalendar(date), duration));
}
/**
* Adds the given XML duration to the given datetime.
*
* @param calendar The calendar to add the duration to.
* @param duration The duration to be added.
* @return A new calendar representing the given calendar's time plus the given duration.
*/
public static Calendar add(Calendar calendar, Duration duration) {
if (calendar == null || duration == null) return calendar;
try {
GregorianCalendar gcal = new GregorianCalendar();
gcal.setTime(calendar.getTime());
gcal.setTimeZone(calendar.getTimeZone());
XMLGregorianCalendar xcal = DatatypeFactory.newInstance().newXMLGregorianCalendar(gcal);
xcal.add(duration);
calendar = xcal.toGregorianCalendar();
} catch (DatatypeConfigurationException ex) {
throw new RuntimeException(ex);
}
return calendar;
}
/**
* Adds the given duration to the given datetime.
*
* @param datetime The datetime to add the duration to.
* @param datetimePattern The pattern the given datetime conforms to.
* @param duration The duration to be added.
* @param durationPattern The pattern the given duration conforms to.
* @return A new datetime representing the given datetime plus the given duration.
*/
public static String add(String datetime, String datetimePattern, String duration, String durationPattern) {
return emit(add(parse(datetime, datetimePattern), DurationHelper.parse(duration, durationPattern)), datetimePattern);
}
/**
* Subtracts the given XML duration from the given datetime.
*
* @param date The date to subtract the duration from.
* @param duration The duration to be subtracted.
* @return A new calendar representing the given date's time minus the given duration.
*/
public static Date subtract(Date date, Duration duration) {
return toDate(subtract(toCalendar(date), duration));
}
/**
* Subtracts the given XML duration from the given datetime.
*
* @param calendar The calendar to subtract the duration from.
* @param duration The duration to be subtracted.
* @return A new calendar representing the given calendar's time minus the given duration.
*/
public static Calendar subtract(Calendar calendar, Duration duration) {
if (duration != null) duration = duration.negate();
return add(calendar, duration);
}
/**
* Returns the current datetime minus the given duration.
*
* @param duration The duration to be subtracted from the current datetime.
* @return The current datetime minus the given duration.
*/
public static Calendar earlier(Duration duration) {
return subtract(Calendar.getInstance(), duration);
}
/**
* Returns the current datetime plus the given duration.
*
* @param duration The duration to be added from the current datetime.
* @return The current datetime plus the given duration.
*/
public static Calendar later(Duration duration) {
return add(Calendar.getInstance(), duration);
}
/**
* Compares two datetimes.
*
* @param firstCalendar The first calendar to compare.
* @param secondCalendar The second calendar to compare.
* @return Zero if both calendars represent that same instant in time, less than zero if the
* firstCalendar is an earlier instant in time than the secondCalendar, or greater than
* zero if the firstCalendar is greater than the secondCalendar.
*/
public static int compare(Calendar firstCalendar, Calendar secondCalendar) {
if (firstCalendar == null && secondCalendar == null) return 0;
if (firstCalendar == null) return -1;
if (secondCalendar == null) return 1;
return firstCalendar.compareTo(secondCalendar);
}
/**
* Compares two datetime strings.
*
* @param firstDate The first datetime string to compare.
* @param firstPattern The datetime pattern firstDate conforms to.
* @param secondDate The second datetime string to compare.
* @param secondPattern The datetime pattern secondDate conforms to.
* @return Zero if both calendars represent that same instant in time, less than zero if the
* firstCalendar is an earlier instant in time than the secondCalendar, or greater than
* zero if the firstCalendar is greater than the secondCalendar.
*/
public static int compare(String firstDate, String firstPattern, String secondDate, String secondPattern) {
return compare(parse(firstDate, firstPattern), parse(secondDate, secondPattern));
}
/**
* Returns the duration of time between two given Calendar objects.
*
* @param startCalendar The starting instant in time.
* @param endCalendar The ending instant in time.
* @return The duration of time from the start instant to the end instant.
*/
public static Duration duration(Calendar startCalendar, Calendar endCalendar) {
if (startCalendar == null || endCalendar == null) return null;
return DurationHelper.parse((endCalendar.getTimeInMillis() - startCalendar.getTimeInMillis()));
}
/**
* Returns the given datetime as an XML datetime string.
*
* @param input The datetime to be serialized to an XML string.
* @return The given datetime serialized as an XML string.
*/
public static String emit(Date input) {
return emit(input, null);
}
/**
* Serializes the given datetime to a string using the given pattern.
*
* @param input The datetime to be serialized to a string.
* @param pattern The serialization pattern to use.
* @return The given datetime serialized to a string using the given pattern.
*/
public static String emit(Date input, String pattern) {
return emit(input, pattern, (TimeZone)null);
}
/**
* Serializes the given datetime to a string using the given pattern.
*
* @param input The datetime to be serialized to a string.
* @param pattern The serialization pattern to use.
* @param timezone The timezone ID identifying the desired timezone the datetime string should use.
* @return The given datetime serialized to a string using the given pattern.
*/
public static String emit(Date input, String pattern, String timezone) {
return emit(input, pattern, TimeZoneHelper.get(timezone));
}
/**
* Serializes the given datetime to a string using the given pattern.
*
* @param input The datetime to be serialized to a string.
* @param pattern The serialization pattern to use.
* @param timezone The timezone the datetime string should use.
* @return The given datetime serialized to a string using the given pattern.
*/
public static String emit(Date input, String pattern, TimeZone timezone) {
if (input == null) return null;
return emit(toCalendar(input), pattern, timezone);
}
/**
* Returns the given datetime as an XML datetime string.
*
* @param input The datetime to be serialized to an XML string.
* @return The given datetime serialized as an XML string.
*/
public static String emit(Calendar input) {
return emit(input, null);
}
/**
* Serializes the given datetime to a string using the given pattern.
*
* @param input The datetime to be serialized to a string.
* @param pattern The serialization pattern to use.
* @return The given datetime serialized to a string using the given pattern.
*/
public static String emit(Calendar input, String pattern) {
return emit(input, pattern, (TimeZone)null);
}
/**
* Serializes the given datetime to a string using the given pattern.
*
* @param input The datetime to be serialized to a string.
* @param pattern The serialization pattern to use.
* @param timezone The timezone ID identifying the desired timezone the datetime string should use.
* @return The given datetime serialized to a string using the given pattern.
*/
public static String emit(Calendar input, String pattern, String timezone) {
return emit(input, pattern, TimeZoneHelper.get(timezone));
}
/**
* Serializes the given datetime to a string using the given pattern.
*
* @param input The datetime to be serialized to a string.
* @param pattern The serialization pattern to use.
* @param timezone The timezone the datetime string should use.
* @return The given datetime serialized to a string using the given pattern.
*/
public static String emit(Calendar input, String pattern, TimeZone timezone) {
if (input == null) return null;
if (pattern == null) pattern = DEFAULT_DATETIME_PATTERN;
String output = null;
if (timezone != null) input = TimeZoneHelper.convert(input, timezone);
if (pattern.equals("datetime") || pattern.equals("datetime.xml")) {
output = DatatypeConverter.printDateTime(input);
} else if (pattern.equals("milliseconds")) {
output = "" + input.getTimeInMillis();
} else {
if (NAMED_PATTERNS.containsKey(pattern)) pattern = NAMED_PATTERNS.get(pattern);
DateFormat formatter = new SimpleDateFormat(pattern);
formatter.setTimeZone(input.getTimeZone());
formatter.setLenient(false);
output = formatter.format(input.getTime());
}
return output;
}
/**
* Returns the given list of datetimes as a list of XML datetime strings.
*
* @param inputs The datetimes to be serialized to XML strings.
* @return The given datetimes serialized as XML strings.
*/
public static String[] emit(Date[] inputs) {
return emit(inputs, null);
}
/**
* Serializes the given datetimes to strings using the given pattern.
*
* @param inputs The datetimes to be serialized to strings.
* @param pattern The serialization pattern to use.
* @return The given datetimes serialized to strings using the given pattern.
*/
public static String[] emit(Date[] inputs, String pattern) {
return emit(inputs, pattern, (TimeZone)null);
}
/**
* Serializes the given datetimes to strings using the given pattern.
*
* @param inputs The datetimes to be serialized to strings.
* @param pattern The serialization pattern to use.
* @param timezone The timezone ID identifying the desired timezone the datetime strings should use.
* @return The given datetimes serialized to strings using the given pattern.
*/
public static String[] emit(Date[] inputs, String pattern, String timezone) {
return emit(inputs, pattern, TimeZoneHelper.get(timezone));
}
/**
* Serializes the given datetimes to strings using the given pattern.
*
* @param inputs The datetimes to be serialized to strings.
* @param pattern The serialization pattern to use.
* @param timezone The timezone the datetime strings should use.
* @return The given datetimes serialized to strings using the given pattern.
*/
public static String[] emit(Date[] inputs, String pattern, TimeZone timezone) {
String[] outputs = null;
if (inputs != null) {
outputs = new String[inputs.length];
for (int i = 0; i < inputs.length; i++) {
outputs[i] = emit(inputs[i], pattern, timezone);
}
}
return outputs;
}
/**
* Returns the given list of datetimes as a list of XML datetime strings.
*
* @param inputs The datetimes to be serialized to XML strings.
* @return The given datetimes serialized as XML strings.
*/
public static String[] emit(Calendar[] inputs) {
return emit(inputs, null);
}
/**
* Serializes the given datetimes to strings using the given pattern.
*
* @param inputs The datetimes to be serialized to strings.
* @param pattern The serialization pattern to use.
* @return The given datetimes serialized to strings using the given pattern.
*/
public static String[] emit(Calendar[] inputs, String pattern) {
return emit(inputs, pattern, (TimeZone)null);
}
/**
* Serializes the given datetimes to strings using the given pattern.
*
* @param inputs The datetimes to be serialized to strings.
* @param pattern The serialization pattern to use.
* @param timezone The timezone ID identifying the desired timezone the datetime strings should use.
* @return The given datetimes serialized to strings using the given pattern.
*/
public static String[] emit(Calendar[] inputs, String pattern, String timezone) {
return emit(inputs, pattern, TimeZoneHelper.get(timezone));
}
/**
* Serializes the given datetimes to strings using the given pattern.
*
* @param inputs The datetimes to be serialized to strings.
* @param pattern The serialization pattern to use.
* @param timezone The timezone the datetime strings should use.
* @return The given datetimes serialized to strings using the given pattern.
*/
public static String[] emit(Calendar[] inputs, String pattern, TimeZone timezone) {
String[] outputs = null;
if (inputs != null) {
outputs = new String[inputs.length];
for (int i = 0; i < inputs.length; i++) {
outputs[i] = emit(inputs[i], pattern, timezone);
}
}
return outputs;
}
/**
* Parses a milliseconds since epoch value into a Calendar object.
*
* @param milliseconds The milliseconds since epoch value.
* @return A Calendar object representing the parsed value.
*/
public static Calendar parse(long milliseconds) {
return parse(milliseconds, (TimeZone)null);
}
/**
* Parses a milliseconds since epoch value into a Calendar object.
*
* @param milliseconds The milliseconds since epoch value.
* @param timezone The time zone ID identifying the time zone into which the parsed string will be forced.
* @return A Calendar object representing the parsed value.
*/
public static Calendar parse(long milliseconds, String timezone) {
return parse(milliseconds, TimeZoneHelper.get(timezone));
}
/**
* Parses a milliseconds since epoch value into a Calendar object.
*
* @param milliseconds The milliseconds since epoch value.
* @param timezone The time zone into which the parsed string will be forced.
* @return A Calendar object representing the parsed value.
*/
public static Calendar parse(long milliseconds, TimeZone timezone) {
Calendar output = Calendar.getInstance();
output.setTimeInMillis(milliseconds);
return TimeZoneHelper.convert(output, timezone);
}
/**
* Parses an XML datetime string and returns a Calendar object.
*
* @param input The XML datetime string to be parsed.
* @return A Calendar object representing the parsed XML datetime string.
*/
public static Calendar parse(String input) {
return parse(input, (String)null);
}
/**
* Parses a datetime string that adheres to the given pattern and returns a Calendar object.
*
* @param input The datetime string to be parsed.
* @param pattern The datetime pattern the given string adheres to.
* @return A Calendar object representing the parsed datetime string.
*/
public static Calendar parse(String input, String pattern) {
return parse(input, pattern, (TimeZone)null);
}
/**
* Parses a datetime string that adheres to the given pattern and returns a Calendar object.
*
* @param input The datetime string to be parsed.
* @param pattern The datetime pattern the given string adheres to.
* @param timezone The time zone ID identifying the time zone into which the parsed string will be forced.
* @return A Calendar object representing the parsed datetime string.
*/
public static Calendar parse(String input, String pattern, String timezone) {
return parse(input, pattern, TimeZoneHelper.get(timezone));
}
/**
* Parses a datetime string that adheres to the given pattern and returns a Calendar object.
*
* @param input The datetime string to be parsed.
* @param pattern The datetime pattern the given string adheres to.
* @param timezone The time zone into which the parsed string will be forced.
* @return A Calendar object representing the parsed datetime string.
*/
public static Calendar parse(String input, String pattern, TimeZone timezone) {
if (input == null) return null;
if (pattern == null) pattern = DEFAULT_DATETIME_PATTERN;
Calendar output = null;
try {
if (pattern.equals("datetime") || pattern.equals("datetime.xml")) {
output = DatatypeConverter.parseDateTime(input);
} else if (pattern.equals("datetime.jdbc")) {
output = Calendar.getInstance();
output.setTime(Timestamp.valueOf(input));
} else if (pattern.equals("datetime.db2")) {
Matcher matcher = DB2_DATETIME_PATTERN.matcher(input);
if (matcher.matches()) {
output = Calendar.getInstance();
output.setLenient(false);
int year = Integer.parseInt(matcher.group(1));
int month = Integer.parseInt(matcher.group(2));
int day = Integer.parseInt(matcher.group(3));
int hour = Integer.parseInt(matcher.group(4));
int minute = Integer.parseInt(matcher.group(5));
int second = Integer.parseInt(matcher.group(6));
int microsecond = Integer.parseInt(matcher.group(7));
output.set(year, month - 1, day, hour, minute, second);
output.set(Calendar.MILLISECOND, microsecond / 1000);
} else {
throw new ParseException(MessageFormat.format("Unparseable date: \"{0}\"", input), 0);
}
} else if (pattern.equals("date") || pattern.equals("date.xml")) {
output = DatatypeConverter.parseDate(input);
} else if (pattern.equals("time") || pattern.equals("time.xml")) {
output = DatatypeConverter.parseTime(input);
} else if (pattern.equals("milliseconds")) {
output = Calendar.getInstance();
output.setTimeInMillis(Long.parseLong(input));
} else {
if (NAMED_PATTERNS.containsKey(pattern)) pattern = NAMED_PATTERNS.get(pattern);
DateFormat formatter = new SimpleDateFormat(pattern);
formatter.setLenient(false);
output = Calendar.getInstance();
output.setTime(formatter.parse(input));
}
if (timezone != null) output = TimeZoneHelper.replace(output, timezone);
} catch(Exception ex) {
throw new IllegalArgumentException(MessageFormat.format("Unparseable datetime: \"{0}\" does not conform to pattern \"{1}\"", input, pattern), ex);
}
return output;
}
/**
* Parses a datetime string that adheres to one of the given patterns and returns a Calendar object.
*
* @param input The datetime string to be parsed.
* @param patterns A list of datetime patterns the given string might adhere to.
* @return A Calendar object representing the parsed datetime string.
*/
public static Calendar parse(String input, String[] patterns) {
return parse(input, patterns, (String)null);
}
/**
* Parses a datetime string that adheres to one of the given patterns and returns a Calendar object.
*
* @param input The datetime string to be parsed.
* @param patterns A list of datetime patterns the given string might adhere to.
* @param timezone The time zone ID identifying the time zone into which the parsed string will be forced.
* @return A Calendar object representing the parsed datetime string.
*/
public static Calendar parse(String input, String[] patterns, String timezone) {
return parse(input, patterns, TimeZoneHelper.get(timezone));
}
/**
* Parses a datetime string that adheres to one of the given patterns and returns a Calendar object.
*
* @param input The datetime string to be parsed.
* @param patterns A list of datetime patterns the given string might adhere to.
* @param timezone The time zone into which the parsed string will be forced.
* @return A Calendar object representing the parsed datetime string.
*/
public static Calendar parse(String input, String[] patterns, TimeZone timezone) {
if (input == null) return null;
if (patterns == null) patterns = new String[1];
Calendar output = null;
boolean parsed = false;
for (String pattern : patterns) {
try {
output = parse(input, pattern, timezone);
parsed = true;
break;
} catch (IllegalArgumentException ex) {
// ignore and continue on to try the next pattern
}
}
if (!parsed) {
throw new IllegalArgumentException(MessageFormat.format("Unparseable datetime: \"{0}\" does not conform to pattern \"{1}\"", input, ArrayHelper.stringify(patterns)));
}
return output;
}
/**
* Parses a list of XML datetime strings and returns a list of Calendar objects.
*
* @param inputs The list of XML datetime strings to be parsed.
* @return A list of Calendar objects representing the parsed XML datetime strings.
*/
public static Calendar[] parse(String[] inputs) {
return parse(inputs, (String)null);
}
/**
* Parses a list of datetime strings that adhere to the given pattern and returns a list of Calendar objects.
*
* @param inputs The list of datetime strings to be parsed.
* @param pattern The datetime pattern the given string adheres to.
* @return A list of Calendar objects representing the parsed datetime strings.
*/
public static Calendar[] parse(String[] inputs, String pattern) {
return parse(inputs, pattern, (TimeZone)null);
}
/**
* Parses a list of datetime strings that adhere to the given pattern and returns a list of Calendar objects.
*
* @param inputs The list of datetime strings to be parsed.
* @param pattern The datetime pattern the given string adheres to.
* @param timezone The time zone ID identifying the time zone into which the parsed string will be forced.
* @return A list of Calendar objects representing the parsed datetime strings.
*/
public static Calendar[] parse(String[] inputs, String pattern, String timezone) {
return parse(inputs, pattern, TimeZoneHelper.get(timezone));
}
/**
* Parses a list of milliseconds since epoch values and returns a list of Calendar objects.
*
* @param inputs The list of milliseconds since epoch values to be parsed.
* @return A list of Calendar objects representing the parsed values.
*/
public static Calendar[] parse(long[] inputs) {
if (inputs == null) return null;
Calendar[] outputs = new Calendar[inputs.length];
for (int i = 0; i < inputs.length; i++) {
outputs[i] = parse(inputs[i]);
}
return outputs;
}
/**
* Parses a list of datetime strings that adhere to the given pattern and returns a list of Calendar objects.
*
* @param inputs The list of datetime strings to be parsed.
* @param pattern The datetime pattern the given string adheres to.
* @param timezone The time zone into which the parsed string will be forced.
* @return A list of Calendar objects representing the parsed datetime strings.
*/
public static Calendar[] parse(String[] inputs, String pattern, TimeZone timezone) {
if (inputs == null) return null;
Calendar[] outputs = new Calendar[inputs.length];
for (int i = 0; i < inputs.length; i++) {
outputs[i] = parse(inputs[i], pattern, timezone);
}
return outputs;
}
/**
* Parses a list of datetime strings that adhere to one of patterns in the given the list and returns a list of
* Calendar objects.
*
* @param inputs The list of datetime strings to be parsed.
* @param patterns The list of datetime patterns the given strings might adhere to.
* @return A list of Calendar objects representing the parsed datetime strings.
*/
public static Calendar[] parse(String[] inputs, String[] patterns) {
return parse(inputs, patterns, (TimeZone)null);
}
/**
* Parses a list of datetime strings that adhere to one of patterns in the given the list and returns a list of
* Calendar objects.
*
* @param inputs The list of datetime strings to be parsed.
* @param patterns The list of datetime patterns the given strings might adhere to.
* @param timezone The time zone ID identifying the time zone into which the parsed string will be forced.
* @return A list of Calendar objects representing the parsed datetime strings.
*/
public static Calendar[] parse(String[] inputs, String[] patterns, String timezone) {
return parse(inputs, patterns, TimeZoneHelper.get(timezone));
}
/**
* Parses a list of datetime strings that adhere to one of patterns in the given the list and returns a list of
* Calendar objects.
*
* @param inputs The list of datetime strings to be parsed.
* @param patterns The list of datetime patterns the given strings might adhere to.
* @param timezone The time zone into which the parsed string will be forced.
* @return A list of Calendar objects representing the parsed datetime strings.
*/
public static Calendar[] parse(String[] inputs, String[] patterns, TimeZone timezone) {
if (inputs == null) return null;
Calendar[] outputs = new Calendar[inputs.length];
for (int i = 0; i < inputs.length; i++) {
outputs[i] = parse(inputs[i], patterns, timezone);
}
return outputs;
}
/**
* Returns the current datetime as a java.util.Calendar.
*
* @return The current datetime as a java.util.Calendar.
*/
public static Calendar now() {
return Calendar.getInstance();
}
/**
* Returns the current datetime as a string formatted according to the given pattern.
*
* @param pattern The serialization pattern to use.
* @return The current datetime as a string formatted according to the given pattern.
*/
public static String now(String pattern) {
return now(pattern, (TimeZone)null);
}
/**
* Returns the current datetime as a string formatted according to the given pattern.
*
* @param pattern The serialization pattern to use.
* @param timezone The time zone ID identifying the time zone the datetime should be returned in.
* @return The current datetime as a string formatted according to the given pattern.
*/
public static String now(String pattern, String timezone) {
return now(pattern, TimeZoneHelper.get(timezone));
}
/**
* Returns the current datetime as a string formatted according to the given pattern.
*
* @param pattern The serialization pattern to use.
* @param timezone The time zone the datetime should be returned in.
* @return The current datetime as a string formatted according to the given pattern.
*/
public static String now(String pattern, TimeZone timezone) {
return emit(now(), pattern, timezone);
}
/**
* Returns the current date as a java.util.Calendar.
*
* @return The current date as a java.util.Calendar.
*/
public static Calendar today() {
Calendar today = now();
today.set(Calendar.HOUR_OF_DAY, 0);
today.set(Calendar.MINUTE, 0);
today.set(Calendar.SECOND, 0);
today.set(Calendar.MILLISECOND, 0);
return today;
}
/**
* Returns the current date as a string formatted according to the given pattern.
*
* @param pattern The serialization pattern to use.
* @return The current date as a string formatted according to the given pattern.
*/
public static String today(String pattern) {
return today(pattern, (TimeZone)null);
}
/**
* Returns the current date as a string formatted according to the given pattern.
*
* @param pattern The serialization pattern to use.
* @param timezone The time zone ID identifying the time zone the datetime should be returned in.
* @return The current date as a string formatted according to the given pattern.
*/
public static String today(String pattern, String timezone) {
return today(pattern, TimeZoneHelper.get(timezone));
}
/**
* Returns the current date as a string formatted according to the given pattern.
*
* @param pattern The serialization pattern to use.
* @param timezone The time zone the datetime should be returned in.
* @return The current date as a string formatted according to the given pattern.
*/
public static String today(String pattern, TimeZone timezone) {
return emit(TimeZoneHelper.replace(today(), timezone), pattern);
}
/**
* Returns the current date plus 1 day as a java.util.Calendar.
*
* @return The current date plus 1 day as a java.util.Calendar.
*/
public static Calendar tomorrow() {
return add(today(), DurationHelper.parse(DurationHelper.MILLISECONDS_PER_DAY));
}
/**
* Returns the current date plus 1 day as a string formatted according to the given pattern.
*
* @param pattern The serialization pattern to use.
* @return The current date plus 1 day as a string formatted according to the given pattern.
*/
public static String tomorrow(String pattern) {
return tomorrow(pattern, (TimeZone)null);
}
/**
* Returns the current date plus 1 day as a string formatted according to the given pattern.
*
* @param pattern The serialization pattern to use.
* @param timezone The time zone ID identifying the time zone the datetime should be returned in.
* @return The current date plus 1 day as a string formatted according to the given pattern.
*/
public static String tomorrow(String pattern, String timezone) {
return tomorrow(pattern, TimeZoneHelper.get(timezone));
}
/**
* Returns the current date plus 1 day as a string formatted according to the given pattern.
*
* @param pattern The serialization pattern to use.
* @param timezone The time zone the datetime should be returned in.
* @return The current date plus 1 day as a string formatted according to the given pattern.
*/
public static String tomorrow(String pattern, TimeZone timezone) {
return emit(TimeZoneHelper.replace(tomorrow(), timezone), pattern);
}
/**
* Returns the current date minus 1 day as a java.util.Calendar.
*
* @return The current date minus 1 day as a java.util.Calendar.
*/
public static Calendar yesterday() {
return subtract(today(), DurationHelper.parse(DurationHelper.MILLISECONDS_PER_DAY));
}
/**
* Returns the current date minus 1 day as a string formatted according to the given pattern.
*
* @param pattern The serialization pattern to use.
* @return The current date minus 1 day as a string formatted according to the given pattern.
*/
public static String yesterday(String pattern) {
return yesterday(pattern, (TimeZone)null);
}
/**
* Returns the current date minus 1 day as a string formatted according to the given pattern.
*
* @param pattern The serialization pattern to use.
* @param timezone The time zone ID identifying the time zone the datetime should be returned in.
* @return The current date minus 1 day as a string formatted according to the given pattern.
*/
public static String yesterday(String pattern, String timezone) {
return yesterday(pattern, TimeZoneHelper.get(timezone));
}
/**
* Returns the current date minus 1 day as a string formatted according to the given pattern.
*
* @param pattern The serialization pattern to use.
* @param timezone The time zone the datetime should be returned in.
* @return The current date minus 1 day as a string formatted according to the given pattern.
*/
public static String yesterday(String pattern, TimeZone timezone) {
return emit(TimeZoneHelper.replace(yesterday(), timezone), pattern);
}
/**
* Reformats the given milliseconds since epoch value as an XML datetime string.
*
* @param milliseconds The milliseconds since epoch value to be formatted.
* @return The given milliseconds since epoch value formatted as an XML datetime string.
*/
public static String format(long milliseconds) {
return format(milliseconds, null, (TimeZone)null);
}
/**
* Reformats the given milliseconds since epoch value according to the desired pattern.
*
* @param milliseconds The milliseconds since epoch value to be formatted.
* @param pattern The pattern the resulting datetime string should be formatted as.
* @return The given milliseconds since epoch value formatted according to the given pattern.
*/
public static String format(long milliseconds, String pattern) {
return format(milliseconds, pattern, (TimeZone)null);
}
/**
* Reformats the given milliseconds since epoch value according to the desired pattern.
*
* @param milliseconds The milliseconds since epoch value to be formatted.
* @param pattern The pattern the resulting datetime string should be formatted as.
* @param timezone The time zone ID identifying the time zone the returned datetime string should be in.
* @return The given milliseconds since epoch value formatted according to the given pattern.
*/
public static String format(long milliseconds, String pattern, String timezone) {
return format(milliseconds, pattern, TimeZoneHelper.get(timezone));
}
/**
* Reformats the given milliseconds since epoch value according to the desired pattern.
*
* @param milliseconds The milliseconds since epoch value to be formatted.
* @param pattern The pattern the resulting datetime string should be formatted as.
* @param timezone The time zone ID identifying the time zone the returned datetime string should be in.
* @return The given milliseconds since epoch value formatted according to the given pattern.
*/
public static String format(long milliseconds, String pattern, TimeZone timezone) {
return emit(parse(milliseconds), pattern, timezone);
}
/**
* Reformats the given datetime string according to the desired pattern.
*
* @param input The datetime string to be reformatted.
* @param inPattern The pattern the given input datetime string adheres to.
* @param outPattern The pattern the datetime string should be reformatted as.
* @return The given datetime string reformatted according to the given outPattern.
*/
public static String format(String input, String inPattern, String outPattern) {
return format(input, inPattern, (TimeZone)null, outPattern, (TimeZone)null);
}
/**
* Reformats the given datetime string according to the desired pattern.
*
* @param input The datetime string to be reformatted.
* @param inPattern The pattern the given input datetime string adheres to.
* @param inTimeZone The time zone ID identifying the time zone the given datetime string should be parsed in.
* @param outPattern The pattern the datetime string should be reformatted as.
* @param outTimeZone The time zone ID identifying the time zone the returned datetime string should be in.
* @return The given datetime string reformatted according to the given outPattern.
*/
public static String format(String input, String inPattern, String inTimeZone, String outPattern, String outTimeZone) {
return format(input, inPattern, TimeZoneHelper.get(inTimeZone), outPattern, TimeZoneHelper.get(outTimeZone));
}
/**
* Reformats the given datetime string according to the desired pattern.
*
* @param input The datetime string to be reformatted.
* @param inPattern The pattern the given input datetime string adheres to.
* @param inTimeZone The time zone the given datetime string should be parsed in.
* @param outPattern The pattern the datetime string should be reformatted as.
* @param outTimeZone The time zone the returned datetime string should be in.
* @return The given datetime string reformatted according to the given outPattern.
*/
public static String format(String input, String inPattern, TimeZone inTimeZone, String outPattern, TimeZone outTimeZone) {
return emit(parse(input, inPattern, inTimeZone), outPattern, outTimeZone);
}
/**
* Reformats the given datetime string according to the desired pattern.
*
* @param input The datetime string to be reformatted.
* @param inPatterns The list of patterns the given input datetime string might adhere to.
* @param outPattern The pattern the datetime string should be reformatted as.
* @return The given datetime string reformatted according to the given outPattern.
*/
public static String format(String input, String[] inPatterns, String outPattern) {
return format(input, inPatterns, (TimeZone)null, outPattern, (TimeZone)null);
}
/**
* Reformats the given datetime string according to the desired pattern.
*
* @param input The datetime string to be reformatted.
* @param inPatterns The list of patterns the given input datetime string might adhere to.
* @param inTimeZone The time zone ID identifying the time zone the given datetime string should be parsed in.
* @param outPattern The pattern the datetime string should be reformatted as.
* @param outTimeZone The time zone ID identifying the time zone the returned datetime string should be in.
* @return The given datetime string reformatted according to the given outPattern.
*/
public static String format(String input, String[] inPatterns, String inTimeZone, String outPattern, String outTimeZone) {
return format(input, inPatterns, TimeZoneHelper.get(inTimeZone), outPattern, TimeZoneHelper.get(outTimeZone));
}
/**
* Reformats the given datetime string according to the desired pattern.
*
* @param input The datetime string to be reformatted.
* @param inPatterns The list of patterns the given input datetime string might adhere to.
* @param inTimeZone The time zone the given datetime string should be parsed in.
* @param outPattern The pattern the datetime string should be reformatted as.
* @param outTimeZone The time zone the returned datetime string should be in.
* @return The given datetime string reformatted according to the given outPattern.
*/
public static String format(String input, String[] inPatterns, TimeZone inTimeZone, String outPattern, TimeZone outTimeZone) {
return emit(parse(input, inPatterns, inTimeZone), outPattern, outTimeZone);
}
/**
* Reformats the given list of milliseconds since epoch values to XML datetime strings.
*
* @param inputs The list of milliseconds since epoch value to be formatted.
* @return The given milliseconds since epoch value formatted to XML datetime strings.
*/
public static String[] format(long[] inputs) {
return format(inputs, null, (TimeZone)null);
}
/**
* Reformats the given list of milliseconds since epoch values according to the desired pattern.
*
* @param inputs The list of milliseconds since epoch value to be formatted.
* @param pattern The pattern the resulting datetime string should be formatted as.
* @return The given milliseconds since epoch value formatted according to the given pattern.
*/
public static String[] format(long[] inputs, String pattern) {
return format(inputs, pattern, (TimeZone)null);
}
/**
* Reformats the given list of milliseconds since epoch values according to the desired pattern.
*
* @param inputs The list of milliseconds since epoch values to be formatted.
* @param pattern The pattern the resulting datetime string should be formatted as.
* @param timezone The time zone ID identifying the time zone the returned datetime string should be in.
* @return The given milliseconds since epoch value formatted according to the given pattern.
*/
public static String[] format(long[] inputs, String pattern, String timezone) {
return format(inputs, pattern, TimeZoneHelper.get(timezone));
}
/**
* Reformats the given list of milliseconds since epoch values according to the desired pattern.
*
* @param inputs The list of milliseconds since epoch values to be formatted.
* @param pattern The pattern the resulting datetime string should be formatted as.
* @param timezone The time zone ID identifying the time zone the returned datetime string should be in.
* @return The given milliseconds since epoch value formatted according to the given pattern.
*/
public static String[] format(long[] inputs, String pattern, TimeZone timezone) {
if (inputs == null) return null;
String[] outputs = new String[inputs.length];
for (int i = 0; i < inputs.length; i++) {
outputs[i] = format(inputs[i], pattern, timezone);
}
return outputs;
}
/**
* Reformats the given list of datetime strings according to the desired pattern.
*
* @param inputs The list of datetime strings to be reformatted.
* @param inPattern The pattern the given input datetime strings adhere to.
* @param outPattern The pattern the datetime strings should be reformatted as.
* @return The given datetime strings reformatted according to the given outPattern.
*/
public static String[] format(String[] inputs, String inPattern, String outPattern) {
return format(inputs, inPattern, (TimeZone)null, outPattern, (TimeZone)null);
}
/**
* Reformats the given list of datetime strings according to the desired pattern.
*
* @param inputs The list of datetime strings to be reformatted.
* @param inPattern The pattern the given input datetime strings adhere to.
* @param inTimeZone The time zone ID identifying the time zone the given datetime string should be parsed in.
* @param outPattern The pattern the datetime strings should be reformatted as.
* @param outTimeZone The time zone ID identifying the time zone the returned datetime string should be in.
* @return The given datetime strings reformatted according to the given outPattern.
*/
public static String[] format(String[] inputs, String inPattern, String inTimeZone, String outPattern, String outTimeZone) {
return format(inputs, inPattern, TimeZoneHelper.get(inTimeZone), outPattern, TimeZoneHelper.get(outTimeZone));
}
/**
* Reformats the given list of datetime strings according to the desired pattern.
*
* @param inputs The list of datetime strings to be reformatted.
* @param inPattern The pattern the given input datetime strings adhere to.
* @param inTimeZone The time zone the given datetime string should be parsed in.
* @param outPattern The pattern the datetime strings should be reformatted as.
* @param outTimeZone The time zone the returned datetime string should be in.
* @return The given datetime strings reformatted according to the given outPattern.
*/
public static String[] format(String[] inputs, String inPattern, TimeZone inTimeZone, String outPattern, TimeZone outTimeZone) {
if (inputs == null) return null;
String[] outputs = new String[inputs.length];
for (int i = 0; i < inputs.length; i++) {
outputs[i] = format(inputs[i], inPattern, inTimeZone, outPattern, outTimeZone);
}
return outputs;
}
/**
* Reformats the given datetime string according to the desired pattern.
*
* @param inputs The list of datetime strings to be reformatted.
* @param inPatterns The list of patterns the given input datetime string might adhere to.
* @param outPattern The pattern the datetime string should be reformatted as.
* @return The given datetime string reformatted according to the given outPattern.
*/
public static String[] format(String[] inputs, String[] inPatterns, String outPattern) {
return format(inputs, inPatterns, (TimeZone)null, outPattern, (TimeZone)null);
}
/**
* Reformats the given datetime string according to the desired pattern.
*
* @param inputs The list of datetime strings to be reformatted.
* @param inPatterns The list of patterns the given input datetime string might adhere to.
* @param inTimeZone The time zone ID identifying the time zone the given datetime string should be parsed in.
* @param outPattern The pattern the datetime string should be reformatted as.
* @param outTimeZone The time zone ID identifying the time zone the returned datetime string should be in.
* @return The given datetime string reformatted according to the given outPattern.
*/
public static String[] format(String[] inputs, String[] inPatterns, String inTimeZone, String outPattern, String outTimeZone) {
return format(inputs, inPatterns, TimeZoneHelper.get(inTimeZone), outPattern, TimeZoneHelper.get(outTimeZone));
}
/**
* Reformats the given datetime string according to the desired pattern.
*
* @param inputs The list of datetime strings to be reformatted.
* @param inPatterns The list of patterns the given input datetime string might adhere to.
* @param inTimeZone The time zone the given datetime string should be parsed in.
* @param outPattern The pattern the datetime string should be reformatted as.
* @param outTimeZone The time zone the returned datetime string should be in.
* @return The given datetime string reformatted according to the given outPattern.
*/
public static String[] format(String[] inputs, String[] inPatterns, TimeZone inTimeZone, String outPattern, TimeZone outTimeZone) {
if (inputs == null) return null;
String[] outputs = new String[inputs.length];
for (int i = 0; i < inputs.length; i++) {
outputs[i] = format(inputs[i], inPatterns, inTimeZone, outPattern, outTimeZone);
}
return outputs;
}
/**
* Converts the given Date object to a Calendar object.
*
* @param input The Date object to be converted.
* @return The Calendar object representing the given Date object.
*/
public static Calendar toCalendar(Date input) {
if (input == null) return null;
Calendar calendar = Calendar.getInstance();
calendar.setTime(input);
return calendar;
}
/**
* Converts the given Calendar object to a Date object.
*
* @param input The Calendar object to be converted.
* @return The Date object representing the given Calendar object.
*/
public static Date toDate(Calendar input) {
if (input == null) return null;
return input.getTime();
}
/**
* Returns a new calendar that is constructed from the date part of the given date, and the time part from the given
* time.
*
* @param date The date part to be concatenated.
* @param time The time part to be concatenated.
* @return The resulting calendar with date and time parts from the given date and time calendars.
*/
public static Calendar concatenate(Calendar date, Calendar time) {
if (date == null || time == null) return null;
// set date part of given time to epoch date to ensure it is not included in resulting datetime
time.set(Calendar.DAY_OF_MONTH, 1);
time.set(Calendar.MONTH, 0);
time.set(Calendar.YEAR, 1970);
Calendar datetime = Calendar.getInstance(time.getTimeZone());
datetime.setTimeInMillis(time.getTimeInMillis());
datetime.set(Calendar.DAY_OF_MONTH, date.get(Calendar.DAY_OF_MONTH));
datetime.set(Calendar.MONTH, date.get(Calendar.MONTH));
datetime.set(Calendar.YEAR, date.get(Calendar.YEAR));
return datetime;
}
/**
* Returns the largest datetime from the given list.
*
* @param calendars The list of datetimes to find the maximum in.
* @return The maximum datetime in the given list.
*/
public static Calendar maximum(Calendar... calendars) {
if (calendars == null || calendars.length == 0) return null;
return maximum(Arrays.asList(calendars));
}
/**
* Returns the largest datetime from the given list.
*
* @param calendars The list of datetimes to find the maximum in.
* @return The maximum datetime in the given list.
*/
public static Calendar maximum(Collection<Calendar> calendars) {
if (calendars == null || calendars.size() == 0) return null;
SortedSet<Calendar> set = new TreeSet<Calendar>(calendars);
return set.last();
}
/**
* Returns the smallest datetime from the given list.
*
* @param calendars The list of datetimes to find the minimum in.
* @return The minimum datetime in the given list.
*/
public static Calendar minimum(Calendar... calendars) {
if (calendars == null || calendars.length == 0) return null;
return minimum(Arrays.asList(calendars));
}
/**
* Returns the smallest datetime from the given list.
*
* @param calendars The list of datetimes to find the minimum in.
* @return The minimum datetime in the given list.
*/
public static Calendar minimum(Collection<Calendar> calendars) {
if (calendars == null || calendars.size() == 0) return null;
SortedSet<Calendar> set = new TreeSet<Calendar>(calendars);
return set.first();
}
/**
* Normalizes the given Object to a Calendar: if it's already a Calendar, it is returned;
* if it's a Date, it is converted to a Calendar; if it's a Number, it is treated as
* a milliseconds since epoch value to create a new Calendar; otherwise it is parsed as
* a datetime string.
*
* @param object The Object to be normalized to a Calendar.
* @return A Calendar object representing the given Object.
*/
public static Calendar normalize(Object object) {
return normalize(object, null);
}
/**
* Normalizes the given Object to a Calendar: if it's already a Calendar, it is returned;
* if it's a Date, it is converted to a Calendar; if it's a Number, it is treated as
* a milliseconds since epoch value to create a new Calendar; otherwise it is parsed as
* a datetime string.
*
* @param object The Object to be normalized to a Calendar.
* @param pattern An optional datetime pattern the given Object adheres to, if it's a String.
* @return A Calendar object representing the given Object.
*/
public static Calendar normalize(Object object, String pattern) {
return normalize(object, pattern, (TimeZone)null);
}
/**
* Normalizes the given Object to a Calendar: if it's already a Calendar, it is returned;
* if it's a Date, it is converted to a Calendar; if it's a Number, it is treated as
* a milliseconds since epoch value to create a new Calendar; otherwise it is parsed as
* a datetime string.
*
* @param object The Object to be normalized to a Calendar.
* @param pattern An optional datetime pattern the given Object adheres to, if it's a String.
* @param timezone The time zone ID identifying the time zone which the parsed string will be forced.
* @return A Calendar object representing the given Object.
*/
public static Calendar normalize(Object object, String pattern, String timezone) {
return normalize(object, pattern, TimeZoneHelper.get(timezone));
}
/**
* Normalizes the given Object to a Calendar: if it's already a Calendar, it is returned;
* if it's a Date, it is converted to a Calendar; if it's a Number, it is treated as
* a milliseconds since epoch value to create a new Calendar; otherwise it is parsed as
* a datetime string.
*
* @param object The Object to be normalized to a Calendar.
* @param pattern An optional datetime pattern the given Object adheres to, if it's a String.
* @param timezone The time zone into which the parsed string will be forced.
* @return A Calendar object representing the given Object.
*/
public static Calendar normalize(Object object, String pattern, TimeZone timezone) {
if (object == null) return null;
Calendar calendar = null;
if (object instanceof Calendar) {
calendar = TimeZoneHelper.convert((Calendar)object, timezone);
} else if (object instanceof Date) {
calendar = TimeZoneHelper.convert(toCalendar((Date)object), timezone);
} else if (object instanceof Number) {
calendar = parse(((Number)object).longValue(), timezone);
} else {
calendar = parse(object.toString(), pattern, timezone);
}
return calendar;
}
}