    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017package org.apache.commons.lang3.time;
    018
    019import java.util.Calendar;
    020import java.util.Date;
    021import java.util.Locale;
    022import java.util.TimeZone;
    023
    024/**
    025 * <p>Date and time formatting utilities and constants.</p>
    026 *
    027 * <p>Formatting is performed using the thread-safe
    028 * {@link org.apache.commons.lang3.time.FastDateFormat} class.</p>
    029 *
    030 * <p>Note that the JDK has a bug wherein calling Calendar.get(int) will
    031 * override any previously called Calendar.clear() calls. See LANG-755.</p>
    032 *
    033 * @since 2.0
    034 */
    035public class DateFormatUtils {
    036
    037    /**
    038     * The UTC time zone (often referred to as GMT).
    039     * This is private as it is mutable.
    040     */
    041    private static final TimeZone UTC_TIME_ZONE = FastTimeZone.getGmtTimeZone();
    042
    043    /**
    044     * ISO 8601 formatter for date-time without time zone.
    045     *
    046     * <p>
    047     * The format used is {@code yyyy-MM-dd'T'HH:mm:ss}. This format uses the
    048     * default TimeZone in effect at the time of loading DateFormatUtils class.
    049     * </p>
    050     *
    051     * @since 3.5
    052     */
    053    public static final FastDateFormat ISO_8601_EXTENDED_DATETIME_FORMAT
    054            = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss");
    055
    056    /**
    057     * @deprecated - as of 4.0, ISO_DATETIME_FORMAT will be replaced by ISO_8601_EXTENDED_DATETIME_FORMAT.
    058     */
    059    @Deprecated
    060    public static final FastDateFormat ISO_DATETIME_FORMAT = ISO_8601_EXTENDED_DATETIME_FORMAT;
    061
    062    /**
    063     * ISO 8601 formatter for date-time with time zone.
    064     *
    065     * <p>
    066     * The format used is {@code yyyy-MM-dd'T'HH:mm:ssZZ}. This format uses the
    067     * default TimeZone in effect at the time of loading DateFormatUtils class.
    068     * </p>
    069     *
    070     * @since 3.5
    071     */
    072    public static final FastDateFormat ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT
    073            = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ssZZ");
    074
    075    /**
    076     * @deprecated - as of 4.0, ISO_DATETIME_TIME_ZONE_FORMAT will be replaced by ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.
    077     */
    078    @Deprecated
    079    public static final FastDateFormat ISO_DATETIME_TIME_ZONE_FORMAT = ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT;
    080
    081    /**
    082     * ISO 8601 formatter for date without time zone.
    083     *
    084     * <p>
    085     * The format used is {@code yyyy-MM-dd}. This format uses the
    086     * default TimeZone in effect at the time of loading DateFormatUtils class.
    087     * </p>
    088     *
    089     * @since 3.5
    090     */
    091    public static final FastDateFormat ISO_8601_EXTENDED_DATE_FORMAT
    092            = FastDateFormat.getInstance("yyyy-MM-dd");
    093
    094    /**
    095     * @deprecated - as of 4.0, ISO_DATE_FORMAT will be replaced by ISO_8601_EXTENDED_DATE_FORMAT.
    096     */
    097    @Deprecated
    098    public static final FastDateFormat ISO_DATE_FORMAT = ISO_8601_EXTENDED_DATE_FORMAT;
    099
    100    /**
    101     * ISO 8601-like formatter for date with time zone.
    102     *
    103     * <p>
    104     * The format used is {@code yyyy-MM-ddZZ}. This pattern does not comply
    105     * with the formal ISO 8601 specification as the standard does not allow
    106     * a time zone  without a time. This format uses the default TimeZone in
    107     * effect at the time of loading DateFormatUtils class.
    108     * </p>
    109     *
    110     * @deprecated - as of 4.0, ISO_DATE_TIME_ZONE_FORMAT will be removed.
    111     */
    112    @Deprecated
    113    public static final FastDateFormat ISO_DATE_TIME_ZONE_FORMAT
    114            = FastDateFormat.getInstance("yyyy-MM-ddZZ");
    115
    116    /**
    117     * Non-compliant formatter for time without time zone (ISO 8601 does not
    118     * prefix 'T' for standalone time value).
    119     *
    120     * <p>
    121     * The format used is {@code 'T'HH:mm:ss}. This format uses the default
    122     * TimeZone in effect at the time of loading DateFormatUtils class.
    123     * </p>
    124     *
    125     * @deprecated - as of 4.0, ISO_TIME_FORMAT will be removed.
    126     */
    127    @Deprecated
    128    public static final FastDateFormat ISO_TIME_FORMAT
    129            = FastDateFormat.getInstance("'T'HH:mm:ss");
    130
    131    /**
    132     * Non-compliant formatter for time with time zone (ISO 8601 does not
    133     * prefix 'T' for standalone time value).
    134     *
    135     * <p>
    136     * The format used is {@code 'T'HH:mm:ssZZ}. This format uses the default
    137     * TimeZone in effect at the time of loading DateFormatUtils class.
    138     * </p>
    139     *
    140     * @deprecated - as of 4.0, ISO_TIME_TIME_ZONE_FORMAT will be removed.
    141     */
    142    @Deprecated
    143    public static final FastDateFormat ISO_TIME_TIME_ZONE_FORMAT
    144            = FastDateFormat.getInstance("'T'HH:mm:ssZZ");
    145
    146    /**
    147     * ISO 8601 formatter for time without time zone.
    148     *
    149     * <p>
    150     * The format used is {@code HH:mm:ss}. This format uses the default
    151     * TimeZone in effect at the time of loading DateFormatUtils class.
    152     * </p>
    153     *
    154     * @since 3.5
    155     */
    156    public static final FastDateFormat ISO_8601_EXTENDED_TIME_FORMAT
    157            = FastDateFormat.getInstance("HH:mm:ss");
    158
    159    /**
    160     * @deprecated - as of 4.0, ISO_TIME_NO_T_FORMAT will be replaced by ISO_8601_EXTENDED_TIME_FORMAT.
    161     */
    162    @Deprecated
    163    public static final FastDateFormat ISO_TIME_NO_T_FORMAT = ISO_8601_EXTENDED_TIME_FORMAT;
    164
    165    /**
    166     * ISO 8601 formatter for time with time zone.
    167     *
    168     * <p>
    169     * The format used is {@code HH:mm:ssZZ}. This format uses the default
    170     * TimeZone in effect at the time of loading DateFormatUtils class.
    171     * </p>
    172     *
    173     * @since 3.5
    174     */
    175    public static final FastDateFormat ISO_8601_EXTENDED_TIME_TIME_ZONE_FORMAT
    176            = FastDateFormat.getInstance("HH:mm:ssZZ");
    177
    178    /**
    179     * @deprecated - as of 4.0, ISO_TIME_NO_T_TIME_ZONE_FORMAT will be replaced by ISO_8601_EXTENDED_TIME_TIME_ZONE_FORMAT.
    180     */
    181    @Deprecated
    182    public static final FastDateFormat ISO_TIME_NO_T_TIME_ZONE_FORMAT = ISO_8601_EXTENDED_TIME_TIME_ZONE_FORMAT;
    183
    184    /**
    185     * SMTP (and probably other) date headers.
    186     *
    187     * <p>
    188     * The format used is {@code EEE, dd MMM yyyy HH:mm:ss Z} in US locale.
    189     * This format uses the default TimeZone in effect at the time of loading
    190     * DateFormatUtils class.
    191     * </p>
    192     */
    193    public static final FastDateFormat SMTP_DATETIME_FORMAT
    194            = FastDateFormat.getInstance("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
    195
    196    //-----------------------------------------------------------------------
    197    /**
    198     * <p>DateFormatUtils instances should NOT be constructed in standard programming.</p>
    199     *
    200     * <p>This constructor is public to permit tools that require a JavaBean instance
    201     * to operate.</p>
    202     */
    203    public DateFormatUtils() {
    204    }
    205
    206    /**
    207     * <p>Formats a date/time into a specific pattern using the UTC time zone.</p>
    208     *
    209     * @param millis  the date to format expressed in milliseconds
    210     * @param pattern  the pattern to use to format the date, not null
    211     * @return the formatted date
    212     */
    213    public static String formatUTC(final long millis, final String pattern) {
    214        return format(new Date(millis), pattern, UTC_TIME_ZONE, null);
    215    }
    216
    217    /**
    218     * <p>Formats a date/time into a specific pattern using the UTC time zone.</p>
    219     *
    220     * @param date  the date to format, not null
    221     * @param pattern  the pattern to use to format the date, not null
    222     * @return the formatted date
    223     */
    224    public static String formatUTC(final Date date, final String pattern) {
    225        return format(date, pattern, UTC_TIME_ZONE, null);
    226    }
    227
    228    /**
    229     * <p>Formats a date/time into a specific pattern using the UTC time zone.</p>
    230     *
    231     * @param millis  the date to format expressed in milliseconds
    232     * @param pattern  the pattern to use to format the date, not null
    233     * @param locale  the locale to use, may be {@code null}
    234     * @return the formatted date
    235     */
    236    public static String formatUTC(final long millis, final String pattern, final Locale locale) {
    237        return format(new Date(millis), pattern, UTC_TIME_ZONE, locale);
    238    }
    239
    240    /**
    241     * <p>Formats a date/time into a specific pattern using the UTC time zone.</p>
    242     *
    243     * @param date  the date to format, not null
    244     * @param pattern  the pattern to use to format the date, not null
    245     * @param locale  the locale to use, may be {@code null}
    246     * @return the formatted date
    247     */
    248    public static String formatUTC(final Date date, final String pattern, final Locale locale) {
    249        return format(date, pattern, UTC_TIME_ZONE, locale);
    250    }
    251
    252    /**
    253     * <p>Formats a date/time into a specific pattern.</p>
    254     *
    255     * @param millis  the date to format expressed in milliseconds
    256     * @param pattern  the pattern to use to format the date, not null
    257     * @return the formatted date
    258     */
    259    public static String format(final long millis, final String pattern) {
    260        return format(new Date(millis), pattern, null, null);
    261    }
    262
    263    /**
    264     * <p>Formats a date/time into a specific pattern.</p>
    265     *
    266     * @param date  the date to format, not null
    267     * @param pattern  the pattern to use to format the date, not null
    268     * @return the formatted date
    269     */
    270    public static String format(final Date date, final String pattern) {
    271        return format(date, pattern, null, null);
    272    }
    273
    274    /**
    275     * <p>Formats a calendar into a specific pattern.</p>
    276     *
    277     * @param calendar  the calendar to format, not null
    278     * @param pattern  the pattern to use to format the calendar, not null
    279     * @return the formatted calendar
    280     * @see FastDateFormat#format(Calendar)
    281     * @since 2.4
    282     */
    283    public static String format(final Calendar calendar, final String pattern) {
    284        return format(calendar, pattern, null, null);
    285    }
    286
    287    /**
    288     * <p>Formats a date/time into a specific pattern in a time zone.</p>
    289     *
    290     * @param millis  the time expressed in milliseconds
    291     * @param pattern  the pattern to use to format the date, not null
    292     * @param timeZone  the time zone  to use, may be {@code null}
    293     * @return the formatted date
    294     */
    295    public static String format(final long millis, final String pattern, final TimeZone timeZone) {
    296        return format(new Date(millis), pattern, timeZone, null);
    297    }
    298
    299    /**
    300     * <p>Formats a date/time into a specific pattern in a time zone.</p>
    301     *
    302     * @param date  the date to format, not null
    303     * @param pattern  the pattern to use to format the date, not null
    304     * @param timeZone  the time zone  to use, may be {@code null}
    305     * @return the formatted date
    306     */
    307    public static String format(final Date date, final String pattern, final TimeZone timeZone) {
    308        return format(date, pattern, timeZone, null);
    309    }
    310
    311    /**
    312     * <p>Formats a calendar into a specific pattern in a time zone.</p>
    313     *
    314     * @param calendar  the calendar to format, not null
    315     * @param pattern  the pattern to use to format the calendar, not null
    316     * @param timeZone  the time zone  to use, may be {@code null}
    317     * @return the formatted calendar
    318     * @see FastDateFormat#format(Calendar)
    319     * @since 2.4
    320     */
    321    public static String format(final Calendar calendar, final String pattern, final TimeZone timeZone) {
    322        return format(calendar, pattern, timeZone, null);
    323    }
    324
    325    /**
    326     * <p>Formats a date/time into a specific pattern in a locale.</p>
    327     *
    328     * @param millis  the date to format expressed in milliseconds
    329     * @param pattern  the pattern to use to format the date, not null
    330     * @param locale  the locale to use, may be {@code null}
    331     * @return the formatted date
    332     */
    333    public static String format(final long millis, final String pattern, final Locale locale) {
    334        return format(new Date(millis), pattern, null, locale);
    335    }
    336
    337    /**
    338     * <p>Formats a date/time into a specific pattern in a locale.</p>
    339     *
    340     * @param date  the date to format, not null
    341     * @param pattern  the pattern to use to format the date, not null
    342     * @param locale  the locale to use, may be {@code null}
    343     * @return the formatted date
    344     */
    345    public static String format(final Date date, final String pattern, final Locale locale) {
    346        return format(date, pattern, null, locale);
    347    }
    348
    349    /**
    350     * <p>Formats a calendar into a specific pattern in a locale.</p>
    351     *
    352     * @param calendar  the calendar to format, not null
    353     * @param pattern  the pattern to use to format the calendar, not null
    354     * @param locale  the locale to use, may be {@code null}
    355     * @return the formatted calendar
    356     * @see FastDateFormat#format(Calendar)
    357     * @since 2.4
    358     */
    359    public static String format(final Calendar calendar, final String pattern, final Locale locale) {
    360        return format(calendar, pattern, null, locale);
    361    }
    362
    363    /**
    364     * <p>Formats a date/time into a specific pattern in a time zone  and locale.</p>
    365     *
    366     * @param millis  the date to format expressed in milliseconds
    367     * @param pattern  the pattern to use to format the date, not null
    368     * @param timeZone  the time zone  to use, may be {@code null}
    369     * @param locale  the locale to use, may be {@code null}
    370     * @return the formatted date
    371     */
    372    public static String format(final long millis, final String pattern, final TimeZone timeZone, final Locale locale) {
    373        return format(new Date(millis), pattern, timeZone, locale);
    374    }
    375
    376    /**
    377     * <p>Formats a date/time into a specific pattern in a time zone  and locale.</p>
    378     *
    379     * @param date  the date to format, not null
    380     * @param pattern  the pattern to use to format the date, not null, not null
    381     * @param timeZone  the time zone  to use, may be {@code null}
    382     * @param locale  the locale to use, may be {@code null}
    383     * @return the formatted date
    384     */
    385    public static String format(final Date date, final String pattern, final TimeZone timeZone, final Locale locale) {
    386        final FastDateFormat df = FastDateFormat.getInstance(pattern, timeZone, locale);
    387        return df.format(date);
    388    }
    389
    390    /**
    391     * <p>Formats a calendar into a specific pattern in a time zone  and locale.</p>
    392     *
    393     * @param calendar  the calendar to format, not null
    394     * @param pattern  the pattern to use to format the calendar, not null
    395     * @param timeZone  the time zone  to use, may be {@code null}
    396     * @param locale  the locale to use, may be {@code null}
    397     * @return the formatted calendar
    398     * @see FastDateFormat#format(Calendar)
    399     * @since 2.4
    400     */
    401    public static String format(final Calendar calendar, final String pattern, final TimeZone timeZone, final Locale locale) {
    402        final FastDateFormat df = FastDateFormat.getInstance(pattern, timeZone, locale);
    403        return df.format(calendar);
    404    }
    405
    406}