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}