Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.apache.juneau.utils.CalendarUtils Maven / Gradle / Ivy
// ***************************************************************************************************************************
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
// * distributed with this work for additional information regarding copyright ownership. 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. *
// ***************************************************************************************************************************
package org.apache.juneau.utils;
import static org.apache.juneau.internal.DateUtils.*;
import java.text.*;
import java.util.*;
import java.util.concurrent.*;
import javax.xml.bind.*;
import org.apache.juneau.internal.*;
/**
* Utility class for converting {@link Calendar} and {@link Date} objects to common serialized forms.
*/
public class CalendarUtils {
private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
/**
* Valid conversion formats.
*/
public static enum Format {
/**
* Transform to ISO8601 date-time-local strings.
*
* Example output:
*
* "2001-07-04T15:30:45"
*
*
* Example input:
*
* "2001-07-04T15:30:45"
* "2001-07-04T15:30:45.1"
* "2001-07-04T15:30"
* "2001-07-04"
* "2001-07"
* "2001"
*
*/
ISO8601_DTL,
/**
* Transform to ISO8601 date-time strings.
*
* Example output:
*
* "2001-07-04T15:30:45-05:00"
* "2001-07-04T15:30:45Z"
*
*
* Example input:
*
* "2001-07-04T15:30:45-05:00"
* "2001-07-04T15:30:45Z"
* "2001-07-04T15:30:45.1Z"
* "2001-07-04T15:30Z"
* "2001-07-04"
* "2001-07"
* "2001"
*
*/
ISO8601_DT,
/**
* Same as {@link CalendarUtils.Format#ISO8601_DT}, except always serializes in GMT.
*
* Example output:
* "2001-07-04T15:30:45Z"
*/
ISO8601_DTZ,
/**
* Same as {@link CalendarUtils.Format#ISO8601_DT} except serializes to millisecond precision.
*
* Example output:
* "2001-07-04T15:30:45.123Z"
*/
ISO8601_DTP,
/**
* Same as {@link CalendarUtils.Format#ISO8601_DTZ} except serializes to millisecond precision.
*
* Example output:
* "2001-07-04T15:30:45.123"
*/
ISO8601_DTPZ,
/**
* ISO8601 date only.
*
* Example output:
* "2001-07-04"
*/
ISO8601_D,
/**
* Transform to {@link String Strings} using the {@code Date.toString()} method.
*
* Example output:
*
* "Wed Jul 04 15:30:45 EST 2001"
*
*/
TO_STRING,
/**
* Transform to RFC2822 date-time strings.
*
* Example output:
*
* "Sat, 03 Mar 2001 10:11:12 +0000" // en_US
* "土, 03 3 2001 10:11:12 +0000" // ja_JP
* "토, 03 3월 2001 10:11:12 +0000" // ko_KR
*
*/
RFC2822_DT,
/**
* Same as {@link CalendarUtils.Format#RFC2822_DT}, except always serializes in GMT.
*
* Example output:
*
* "Sat, 03 Mar 2001 10:11:12 GMT" // en_US
* "土, 03 3 2001 10:11:12 GMT" // ja_JP
* "토, 03 3월 2001 10:11:12 GMT" // ko_KR
*
*/
RFC2822_DTZ,
/**
* Transform to RFC2822 date strings.
*
* Example output:
*
* "03 Mar 2001" // en_US
* "03 3 2001" // ja_JP
* "03 3월 2001" // ko_KR
*
*/
RFC2822_D,
/**
* Transform to simple "yyyy/MM/dd HH:mm:ss" date-time strings.
*
* Example output:
*
* "2001/03/03 10:11:12"
*
*/
SIMPLE_DT,
/**
* Transform to simple "yyyy/MM/dd" date strings.
*
* Example output:
*
*/
SIMPLE_D,
/**
* Transform to simple "HH:mm:ss" time strings.
*
* Example output:
*
*/
SIMPLE_T,
/**
* Transform to {@link DateFormat#FULL} date strings.
*
* Example output:
*
* "Saturday, March 3, 2001" // en_US
* "2001年3月3日" // ja_JP
* "2001년 3월 3일 토요일" // ko_KR
*
*/
FULL_D,
/**
* Transform to {@link DateFormat#LONG} date strings.
*
* Example output:
*
* "March 3, 2001" // en_US
* "2001/03/03" // ja_JP
* "2001년 3월 3일 (토)" // ko_KR
*
*/
LONG_D,
/**
* Transform to {@link DateFormat#MEDIUM} date strings.
*
* Example output:
*
* "Mar 3, 2001" // en_US
* "2001/03/03" // ja_JP
* "2001. 3. 3" // ko_KR
*
*/
MEDIUM_D,
/**
* Transform to {@link DateFormat#SHORT} date strings.
*
* Example output:
*
* "3/3/01" // en_US
* "01/03/03" // ja_JP
* "01. 3. 3" // ko_KR
*
*/
SHORT_D,
/**
* Transform to {@link DateFormat#FULL} time strings.
*
* Example output:
*
* "10:11:12 AM GMT" // en_US
* "10時11分12秒 GMT" // ja_JP
* "오전 10시 11분 12초 GMT" // ko_KR
*
*/
FULL_T,
/**
* Transform to {@link DateFormat#LONG} time strings.
*
* Example output:
*
* "10:11:12 AM GMT" // en_US
* "10:11:12 GMT" // ja_JP
* "오전 10시 11분 12초" // ko_KR
*
*/
LONG_T,
/**
* Transform to {@link DateFormat#MEDIUM} time strings.
*
* Example output:
*
* "10:11:12 AM" // en_US
* "10:11:12" // ja_JP
* "오전 10:11:12" // ko_KR
*
*/
MEDIUM_T,
/**
* Transform to {@link DateFormat#SHORT} time strings.
*
* Example output:
*
* "10:11 AM" // en_US
* "10:11 AM" // ja_JP
* "오전 10:11" // ko_KR
*
*/
SHORT_T,
/**
* Transform to {@link DateFormat#FULL} date-time strings.
*
* Example output:
*
* "Saturday, March 3, 2001 10:11:12 AM GMT" // en_US
* "2001年3月3日 10時11分12秒 GMT" // ja_JP
* "2001년 3월 3일 토요일 오전 10시 11분 12초 GMT" // ko_KR
*
*/
FULL_DT,
/**
* Transform to {@link DateFormat#LONG} date-time strings.
*
* Example output:
*
* "March 3, 2001 10:11:12 AM GMT" // en_US
* "2001/03/03 10:11:12 GMT" // ja_JP
* "2001년 3월 3일 (토) 오전 10시 11분 12초" // ko_KR
*
*/
LONG_DT,
/**
* Transform to {@link DateFormat#MEDIUM} date-time strings.
*
* Example output:
*
* "Mar 3, 2001 10:11:12 AM" // en_US
* "2001/03/03 10:11:12" // ja_JP
* "2001. 3. 3 오전 10:11:12" // ko_KR
*
*/
MEDIUM_DT,
/**
* Transform to {@link DateFormat#SHORT} date-time strings.
*
* Example output:
*
* "3/3/01 10:11 AM" // en_US
* "01/03/03 10:11" // ja_JP
* "01. 3. 3 오전 10:11" // ko_KR
*
*/
SHORT_DT
}
private static ThreadLocal> patternCache = new ThreadLocal>();
static class DateFormatKey {
final CalendarUtils.Format format;
final Locale locale;
final TimeZone timeZone;
final int hashCode;
DateFormatKey(CalendarUtils.Format format, Locale locale, TimeZone timeZone) {
this.format = format;
this.locale = locale;
this.timeZone = timeZone;
this.hashCode = format.hashCode() + locale.hashCode() + timeZone.hashCode();
}
@Override
public int hashCode() {
return hashCode;
}
@Override
public boolean equals(Object o) {
if (o == null)
return false;
DateFormatKey key = (DateFormatKey)o;
return format.equals(key.format) && locale.equals(key.locale) && timeZone.equals(key.timeZone);
}
}
private static DateFormat getFormat(CalendarUtils.Format format, Locale locale, TimeZone timeZone) {
if (locale == null)
locale = Locale.getDefault();
if (timeZone == null)
timeZone = TimeZone.getDefault();
DateFormatKey key = new DateFormatKey(format, locale, timeZone);
Map m1 = patternCache.get();
if (m1 == null) {
m1 = new ConcurrentHashMap();
patternCache.set(m1);
}
DateFormat df = m1.get(key);
if (df == null) {
String p = null;
switch (format) {
case ISO8601_DTL: p = "yyyy-MM-dd'T'HH:mm:ss"; break;
case ISO8601_D: p = "yyyy-MM-dd"; break;
case TO_STRING: p = "EEE MMM dd HH:mm:ss zzz yyyy"; break;
case RFC2822_DT: p = "EEE, dd MMM yyyy HH:mm:ss Z"; break;
case RFC2822_DTZ: p = "EEE, dd MMM yyyy HH:mm:ss 'GMT'"; break;
case RFC2822_D: p = "dd MMM yyyy"; break;
case SIMPLE_DT: p = "yyyy/MM/dd HH:mm:ss"; break;
case SIMPLE_D: p = "yyyy/MM/dd"; break;
case SIMPLE_T: p = "HH:mm:ss"; break;
case FULL_D: df = DateFormat.getDateInstance(DateFormat.FULL, locale); break;
case LONG_D: df = DateFormat.getDateInstance(DateFormat.LONG, locale); break;
case MEDIUM_D: df = DateFormat.getDateInstance(DateFormat.MEDIUM, locale); break;
case SHORT_D: df = DateFormat.getDateInstance(DateFormat.SHORT, locale); break;
case FULL_T: df = DateFormat.getTimeInstance(DateFormat.FULL, locale); break;
case LONG_T: df = DateFormat.getTimeInstance(DateFormat.LONG, locale); break;
case MEDIUM_T: df = DateFormat.getTimeInstance(DateFormat.MEDIUM, locale); break;
case SHORT_T: df = DateFormat.getTimeInstance(DateFormat.SHORT, locale); break;
case FULL_DT: df = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, locale); break;
case LONG_DT: df = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale); break;
case MEDIUM_DT: df = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, locale); break;
case SHORT_DT: df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale); break;
default: return null;
}
if (p != null) {
df = new SimpleDateFormat(p, locale);
}
if (df != null)
df.setTimeZone(timeZone);
m1.put(key, df);
}
return df;
}
/**
* Converts the specified calendar to a string of the specified format.
*
* @param c The calendar to serialize.
* @param format The date format.
* @param locale The locale to use. If null , uses {@link Locale#getDefault()}.
* @param timeZone The time zone to use. If null , uses {@link TimeZone#getDefault()}.
* @return The serialized date, or null if the calendar was null .
* @throws Exception
*/
public static final String serialize(Calendar c, CalendarUtils.Format format, Locale locale, TimeZone timeZone) throws Exception {
if (c == null)
return null;
if (timeZone == null)
timeZone = c.getTimeZone();
switch(format) {
case ISO8601_DTL:
case ISO8601_D:
case RFC2822_D:
case RFC2822_DT:
case TO_STRING:
case FULL_D:
case FULL_DT:
case FULL_T:
case LONG_D:
case LONG_DT:
case LONG_T:
case MEDIUM_D:
case MEDIUM_DT:
case MEDIUM_T:
case SHORT_D:
case SHORT_DT:
case SHORT_T:
case SIMPLE_D:
case SIMPLE_DT:
case SIMPLE_T:
return serializeFromDateFormat(c.getTime(), format, locale, timeZone);
case ISO8601_DT:
return DatatypeConverter.printDateTime(setTimeZone(c, timeZone));
case ISO8601_DTP:
String s = DatatypeConverter.printDateTime(setTimeZone(c, timeZone));
return String.format("%s.%03d%s", s.substring(0, 19), c.get(Calendar.MILLISECOND), s.substring(19));
case ISO8601_DTZ:
if (c.getTimeZone().getRawOffset() != 0) {
Calendar c2 = Calendar.getInstance(GMT);
c2.setTime(c.getTime());
c = c2;
}
return DatatypeConverter.printDateTime(c);
case ISO8601_DTPZ:
if (c.getTimeZone().getRawOffset() != 0) {
Calendar c2 = Calendar.getInstance(GMT);
c2.setTime(c.getTime());
c = c2;
}
s = DatatypeConverter.printDateTime(c);
return String.format("%s.%03d%s", s.substring(0, 19), c.get(Calendar.MILLISECOND), s.substring(19));
case RFC2822_DTZ:
return serializeFromDateFormat(c.getTime(), format, locale, GMT);
default:
break;
}
return null;
}
/**
* Converts the specified date to a string of the specified format.
*
* @param format The date format.
* @param d The date to serialize.
* @param locale The locale to use. If null , uses {@link Locale#getDefault()}.
* @param timeZone The time zone to use. If null , uses {@link TimeZone#getDefault()}.
* @return The serialized date, or null if the calendar was null .
* @throws Exception
*/
public static final String serialize(Date d, CalendarUtils.Format format, Locale locale, TimeZone timeZone) throws Exception {
if (d == null)
return null;
if (timeZone == null)
timeZone = TimeZone.getDefault();
switch(format) {
case ISO8601_DTL:
case ISO8601_D:
case RFC2822_D:
case RFC2822_DT:
case TO_STRING:
case FULL_D:
case FULL_DT:
case FULL_T:
case LONG_D:
case LONG_DT:
case LONG_T:
case MEDIUM_D:
case MEDIUM_DT:
case MEDIUM_T:
case SHORT_D:
case SHORT_DT:
case SHORT_T:
case SIMPLE_D:
case SIMPLE_DT:
case SIMPLE_T:
return serializeFromDateFormat(d, format, locale, timeZone);
case ISO8601_DT:
Calendar c = new GregorianCalendar();
c.setTime(d);
c.setTimeZone(timeZone);
return DatatypeConverter.printDateTime(c);
case ISO8601_DTP:
c = new GregorianCalendar();
c.setTime(d);
c.setTimeZone(timeZone);
String s = DatatypeConverter.printDateTime(setTimeZone(c, timeZone));
return String.format("%s.%03d%s", s.substring(0, 19), c.get(Calendar.MILLISECOND), s.substring(19));
case ISO8601_DTZ:
c = new GregorianCalendar();
c.setTime(d);
c.setTimeZone(GMT);
return DatatypeConverter.printDateTime(c);
case ISO8601_DTPZ:
c = new GregorianCalendar();
c.setTime(d);
c.setTimeZone(GMT);
s = DatatypeConverter.printDateTime(c);
return String.format("%s.%03d%s", s.substring(0, 19), c.get(Calendar.MILLISECOND), s.substring(19));
case RFC2822_DTZ:
return serializeFromDateFormat(d, format, locale, GMT);
}
return null;
}
/**
* Converts the specified serialized date back into a {@link Calendar} object.
*
* @param format The date format.
* @param in The serialized date.
* @param locale
* The locale to use.
* If null , uses {@link Locale#getDefault()}.
* @param timeZone
* The timezone to assume if input string doesn't contain timezone info.
* If null , uses {@link TimeZone#getDefault()}.
* @return The date as a {@link Calendar}, or null if the input was null or empty.
* @throws Exception
*/
public static final Calendar parseCalendar(String in, CalendarUtils.Format format, Locale locale, TimeZone timeZone) throws Exception {
if (StringUtils.isEmpty(in))
return null;
if (timeZone == null)
timeZone = TimeZone.getDefault();
Date d = null;
switch(format) {
// These use DatatypeConverter to parse the date.
case ISO8601_DTL:
case ISO8601_DT:
case ISO8601_DTZ:
case ISO8601_DTP:
case ISO8601_DTPZ:
case ISO8601_D:
return DatatypeConverter.parseDateTime(toValidISO8601DT(in));
// These don't specify timezones, so we have to assume the timezone is whatever is specified.
case RFC2822_D:
case SIMPLE_DT:
case SIMPLE_D:
case SIMPLE_T:
case FULL_D:
case LONG_D:
case MEDIUM_D:
case SHORT_D:
case MEDIUM_T:
case SHORT_T:
case MEDIUM_DT:
case SHORT_DT:
d = getFormat(format, locale, GMT).parse(in);
d.setTime(d.getTime() - timeZone.getRawOffset());
break;
// This is always in GMT.
case RFC2822_DTZ:
DateFormat f = getFormat(format, locale, GMT);
d = f.parse(in);
break;
// These specify timezones in the strings, so we don't use the specified timezone.
case TO_STRING:
case FULL_DT:
case FULL_T:
case LONG_DT:
case LONG_T:
case RFC2822_DT:
d = getFormat(format, locale, timeZone).parse(in);
break;
}
if (d == null)
return null;
Calendar c = new GregorianCalendar();
c.setTime(d);
c.setTimeZone(timeZone);
return c;
}
/**
* Converts the specified serialized date back into a {@link Date} object.
*
* @param format The date format.
* @param in The serialized date.
* @param locale
* The locale to use.
* If null , uses {@link Locale#getDefault()}.
* @param timeZone
* The timezone to assume if input string doesn't contain timezone info.
* If null , uses {@link TimeZone#getDefault()}.
* @return The date as a {@link Date}, or null if the input was null or empty.
* @throws Exception
*/
public static final Date parseDate(String in, CalendarUtils.Format format, Locale locale, TimeZone timeZone) throws Exception {
if (StringUtils.isEmpty(in))
return null;
if (timeZone == null)
timeZone = TimeZone.getDefault();
switch(format) {
// These use DatatypeConverter to parse the date.
case ISO8601_DTL:
case ISO8601_D:
case ISO8601_DT:
case ISO8601_DTZ:
case ISO8601_DTP:
case ISO8601_DTPZ:
return DatatypeConverter.parseDateTime(toValidISO8601DT(in)).getTime();
// These don't specify timezones, so we have to assume the timezone is whatever is specified.
case FULL_D:
case LONG_D:
case MEDIUM_D:
case MEDIUM_DT:
case MEDIUM_T:
case RFC2822_D:
case SHORT_D:
case SHORT_DT:
case SHORT_T:
case SIMPLE_D:
case SIMPLE_DT:
case SIMPLE_T:
return getFormat(format, locale, timeZone).parse(in);
// This is always in GMT.
case RFC2822_DTZ:
Date d = getFormat(format, locale, TimeZone.getDefault()).parse(in);
d.setTime(d.getTime() + TimeZone.getDefault().getRawOffset());
return d;
// These specify timezones in the strings, so we don't use the specified timezone.
case TO_STRING:
case FULL_DT:
case FULL_T:
case LONG_DT:
case LONG_T:
case RFC2822_DT:
return getFormat(format, locale, timeZone).parse(in);
}
return null;
}
private static String serializeFromDateFormat(Date date, CalendarUtils.Format format, Locale locale, TimeZone timeZone) {
DateFormat df = getFormat(format, locale, timeZone);
String s = df.format(date);
return s;
}
private static Calendar setTimeZone(Calendar c, TimeZone tz) {
if (tz != null && ! tz.equals(c.getTimeZone())) {
c = (Calendar)c.clone();
c.setTimeZone(tz);
}
return c;
}
}