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 = TimeZone.getTimeZone("GMT");
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}