    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        super();
    205    }
    206
    207    /**
    208     * <p>Formats a date/time into a specific pattern using the UTC time zone.</p>
    209     *
    210     * @param millis  the date to format expressed in milliseconds
    211     * @param pattern  the pattern to use to format the date, not null
    212     * @return the formatted date
    213     */
    214    public static String formatUTC(final long millis, final String pattern) {
    215        return format(new Date(millis), pattern, UTC_TIME_ZONE, null);
    216    }
    217
    218    /**
    219     * <p>Formats a date/time into a specific pattern using the UTC time zone.</p>
    220     *
    221     * @param date  the date to format, not null
    222     * @param pattern  the pattern to use to format the date, not null
    223     * @return the formatted date
    224     */
    225    public static String formatUTC(final Date date, final String pattern) {
    226        return format(date, pattern, UTC_TIME_ZONE, null);
    227    }
    228
    229    /**
    230     * <p>Formats a date/time into a specific pattern using the UTC time zone.</p>
    231     *
    232     * @param millis  the date to format expressed in milliseconds
    233     * @param pattern  the pattern to use to format the date, not null
    234     * @param locale  the locale to use, may be <code>null</code>
    235     * @return the formatted date
    236     */
    237    public static String formatUTC(final long millis, final String pattern, final Locale locale) {
    238        return format(new Date(millis), pattern, UTC_TIME_ZONE, locale);
    239    }
    240
    241    /**
    242     * <p>Formats a date/time into a specific pattern using the UTC time zone.</p>
    243     *
    244     * @param date  the date to format, not null
    245     * @param pattern  the pattern to use to format the date, not null
    246     * @param locale  the locale to use, may be <code>null</code>
    247     * @return the formatted date
    248     */
    249    public static String formatUTC(final Date date, final String pattern, final Locale locale) {
    250        return format(date, pattern, UTC_TIME_ZONE, locale);
    251    }
    252
    253    /**
    254     * <p>Formats a date/time into a specific pattern.</p>
    255     *
    256     * @param millis  the date to format expressed in milliseconds
    257     * @param pattern  the pattern to use to format the date, not null
    258     * @return the formatted date
    259     */
    260    public static String format(final long millis, final String pattern) {
    261        return format(new Date(millis), pattern, null, null);
    262    }
    263
    264    /**
    265     * <p>Formats a date/time into a specific pattern.</p>
    266     *
    267     * @param date  the date to format, not null
    268     * @param pattern  the pattern to use to format the date, not null
    269     * @return the formatted date
    270     */
    271    public static String format(final Date date, final String pattern) {
    272        return format(date, pattern, null, null);
    273    }
    274
    275    /**
    276     * <p>Formats a calendar into a specific pattern.</p>
    277     *
    278     * @param calendar  the calendar to format, not null
    279     * @param pattern  the pattern to use to format the calendar, not null
    280     * @return the formatted calendar
    281     * @see FastDateFormat#format(Calendar)
    282     * @since 2.4
    283     */
    284    public static String format(final Calendar calendar, final String pattern) {
    285        return format(calendar, pattern, null, null);
    286    }
    287
    288    /**
    289     * <p>Formats a date/time into a specific pattern in a time zone.</p>
    290     *
    291     * @param millis  the time expressed in milliseconds
    292     * @param pattern  the pattern to use to format the date, not null
    293     * @param timeZone  the time zone  to use, may be <code>null</code>
    294     * @return the formatted date
    295     */
    296    public static String format(final long millis, final String pattern, final TimeZone timeZone) {
    297        return format(new Date(millis), pattern, timeZone, null);
    298    }
    299
    300    /**
    301     * <p>Formats a date/time into a specific pattern in a time zone.</p>
    302     *
    303     * @param date  the date to format, not null
    304     * @param pattern  the pattern to use to format the date, not null
    305     * @param timeZone  the time zone  to use, may be <code>null</code>
    306     * @return the formatted date
    307     */
    308    public static String format(final Date date, final String pattern, final TimeZone timeZone) {
    309        return format(date, pattern, timeZone, null);
    310    }
    311
    312    /**
    313     * <p>Formats a calendar into a specific pattern in a time zone.</p>
    314     *
    315     * @param calendar  the calendar to format, not null
    316     * @param pattern  the pattern to use to format the calendar, not null
    317     * @param timeZone  the time zone  to use, may be <code>null</code>
    318     * @return the formatted calendar
    319     * @see FastDateFormat#format(Calendar)
    320     * @since 2.4
    321     */
    322    public static String format(final Calendar calendar, final String pattern, final TimeZone timeZone) {
    323        return format(calendar, pattern, timeZone, null);
    324    }
    325
    326    /**
    327     * <p>Formats a date/time into a specific pattern in a locale.</p>
    328     *
    329     * @param millis  the date to format expressed in milliseconds
    330     * @param pattern  the pattern to use to format the date, not null
    331     * @param locale  the locale to use, may be <code>null</code>
    332     * @return the formatted date
    333     */
    334    public static String format(final long millis, final String pattern, final Locale locale) {
    335        return format(new Date(millis), pattern, null, locale);
    336    }
    337
    338    /**
    339     * <p>Formats a date/time into a specific pattern in a locale.</p>
    340     *
    341     * @param date  the date to format, not null
    342     * @param pattern  the pattern to use to format the date, not null
    343     * @param locale  the locale to use, may be <code>null</code>
    344     * @return the formatted date
    345     */
    346    public static String format(final Date date, final String pattern, final Locale locale) {
    347        return format(date, pattern, null, locale);
    348    }
    349
    350    /**
    351     * <p>Formats a calendar into a specific pattern in a locale.</p>
    352     *
    353     * @param calendar  the calendar to format, not null
    354     * @param pattern  the pattern to use to format the calendar, not null
    355     * @param locale  the locale to use, may be <code>null</code>
    356     * @return the formatted calendar
    357     * @see FastDateFormat#format(Calendar)
    358     * @since 2.4
    359     */
    360    public static String format(final Calendar calendar, final String pattern, final Locale locale) {
    361        return format(calendar, pattern, null, locale);
    362    }
    363
    364    /**
    365     * <p>Formats a date/time into a specific pattern in a time zone  and locale.</p>
    366     *
    367     * @param millis  the date to format expressed in milliseconds
    368     * @param pattern  the pattern to use to format the date, not null
    369     * @param timeZone  the time zone  to use, may be <code>null</code>
    370     * @param locale  the locale to use, may be <code>null</code>
    371     * @return the formatted date
    372     */
    373    public static String format(final long millis, final String pattern, final TimeZone timeZone, final Locale locale) {
    374        return format(new Date(millis), pattern, timeZone, locale);
    375    }
    376
    377    /**
    378     * <p>Formats a date/time into a specific pattern in a time zone  and locale.</p>
    379     *
    380     * @param date  the date to format, not null
    381     * @param pattern  the pattern to use to format the date, not null, not null
    382     * @param timeZone  the time zone  to use, may be <code>null</code>
    383     * @param locale  the locale to use, may be <code>null</code>
    384     * @return the formatted date
    385     */
    386    public static String format(final Date date, final String pattern, final TimeZone timeZone, final Locale locale) {
    387        final FastDateFormat df = FastDateFormat.getInstance(pattern, timeZone, locale);
    388        return df.format(date);
    389    }
    390
    391    /**
    392     * <p>Formats a calendar into a specific pattern in a time zone  and locale.</p>
    393     *
    394     * @param calendar  the calendar to format, not null
    395     * @param pattern  the pattern to use to format the calendar, not null
    396     * @param timeZone  the time zone  to use, may be <code>null</code>
    397     * @param locale  the locale to use, may be <code>null</code>
    398     * @return the formatted calendar
    399     * @see FastDateFormat#format(Calendar)
    400     * @since 2.4
    401     */
    402    public static String format(final Calendar calendar, final String pattern, final TimeZone timeZone, final Locale locale) {
    403        final FastDateFormat df = FastDateFormat.getInstance(pattern, timeZone, locale);
    404        return df.format(calendar);
    405    }
    406
    407}