1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.lang3.time; 18 19 import java.util.Calendar; 20 import java.util.Date; 21 import java.util.Locale; 22 import java.util.TimeZone; 23 24 /** 25 * Date and time formatting utilities and constants. 26 * 27 * <p>Formatting is performed using the thread-safe 28 * {@link org.apache.commons.lang3.time.FastDateFormat} class.</p> 29 * 30 * <p>Note that the JDK has a bug wherein calling Calendar.get(int) will 31 * override any previously called Calendar.clear() calls. See LANG-755.</p> 32 * 33 * <p>Note that when using capital YYYY instead of lowercase yyyy, the formatter 34 * will assume current year as week year is not supported. See {@link java.util.GregorianCalendar} 35 * Week Year section for an explanation on the difference between calendar and week years.</p> 36 * 37 * @since 2.0 38 */ 39 public class DateFormatUtils { 40 41 /** 42 * The UTC time zone (often referred to as GMT). 43 * This is private as it is mutable. 44 */ 45 private static final TimeZone UTC_TIME_ZONE = FastTimeZone.getGmtTimeZone(); 46 47 /** 48 * ISO 8601 formatter for date-time without time zone. 49 * 50 * <p> 51 * The format used is {@code yyyy-MM-dd'T'HH:mm:ss}. This format uses the 52 * default TimeZone in effect at the time of loading DateFormatUtils class. 53 * </p> 54 * 55 * @since 3.5 56 */ 57 public static final FastDateFormat ISO_8601_EXTENDED_DATETIME_FORMAT 58 = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss"); 59 60 /** 61 * @deprecated - as of 4.0, ISO_DATETIME_FORMAT will be replaced by ISO_8601_EXTENDED_DATETIME_FORMAT. 62 */ 63 @Deprecated 64 public static final FastDateFormat ISO_DATETIME_FORMAT = ISO_8601_EXTENDED_DATETIME_FORMAT; 65 66 /** 67 * ISO 8601 formatter for date-time with time zone. 68 * 69 * <p> 70 * The format used is {@code yyyy-MM-dd'T'HH:mm:ssZZ}. This format uses the 71 * default TimeZone in effect at the time of loading DateFormatUtils class. 72 * </p> 73 * 74 * @since 3.5 75 */ 76 public static final FastDateFormat ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT 77 = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ssZZ"); 78 79 /** 80 * @deprecated - as of 4.0, ISO_DATETIME_TIME_ZONE_FORMAT will be replaced by ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT. 81 */ 82 @Deprecated 83 public static final FastDateFormat ISO_DATETIME_TIME_ZONE_FORMAT = ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT; 84 85 /** 86 * ISO 8601 formatter for date without time zone. 87 * 88 * <p> 89 * The format used is {@code yyyy-MM-dd}. This format uses the 90 * default TimeZone in effect at the time of loading DateFormatUtils class. 91 * </p> 92 * 93 * @since 3.5 94 */ 95 public static final FastDateFormat ISO_8601_EXTENDED_DATE_FORMAT 96 = FastDateFormat.getInstance("yyyy-MM-dd"); 97 98 /** 99 * @deprecated - as of 4.0, ISO_DATE_FORMAT will be replaced by ISO_8601_EXTENDED_DATE_FORMAT. 100 */ 101 @Deprecated 102 public static final FastDateFormat ISO_DATE_FORMAT = ISO_8601_EXTENDED_DATE_FORMAT; 103 104 /** 105 * ISO 8601-like formatter for date with time zone. 106 * 107 * <p> 108 * The format used is {@code yyyy-MM-ddZZ}. This pattern does not comply 109 * with the formal ISO 8601 specification as the standard does not allow 110 * a time zone without a time. This format uses the default TimeZone in 111 * effect at the time of loading DateFormatUtils class. 112 * </p> 113 * 114 * @deprecated - as of 4.0, ISO_DATE_TIME_ZONE_FORMAT will be removed. 115 */ 116 @Deprecated 117 public static final FastDateFormat ISO_DATE_TIME_ZONE_FORMAT 118 = FastDateFormat.getInstance("yyyy-MM-ddZZ"); 119 120 /** 121 * Non-compliant formatter for time without time zone (ISO 8601 does not 122 * prefix 'T' for standalone time value). 123 * 124 * <p> 125 * The format used is {@code 'T'HH:mm:ss}. This format uses the default 126 * TimeZone in effect at the time of loading DateFormatUtils class. 127 * </p> 128 * 129 * @deprecated - as of 4.0, ISO_TIME_FORMAT will be removed. 130 */ 131 @Deprecated 132 public static final FastDateFormat ISO_TIME_FORMAT 133 = FastDateFormat.getInstance("'T'HH:mm:ss"); 134 135 /** 136 * Non-compliant formatter for time with time zone (ISO 8601 does not 137 * prefix 'T' for standalone time value). 138 * 139 * <p> 140 * The format used is {@code 'T'HH:mm:ssZZ}. This format uses the default 141 * TimeZone in effect at the time of loading DateFormatUtils class. 142 * </p> 143 * 144 * @deprecated - as of 4.0, ISO_TIME_TIME_ZONE_FORMAT will be removed. 145 */ 146 @Deprecated 147 public static final FastDateFormat ISO_TIME_TIME_ZONE_FORMAT 148 = FastDateFormat.getInstance("'T'HH:mm:ssZZ"); 149 150 /** 151 * ISO 8601 formatter for time without time zone. 152 * 153 * <p> 154 * The format used is {@code HH:mm:ss}. This format uses the default 155 * TimeZone in effect at the time of loading DateFormatUtils class. 156 * </p> 157 * 158 * @since 3.5 159 */ 160 public static final FastDateFormat ISO_8601_EXTENDED_TIME_FORMAT 161 = FastDateFormat.getInstance("HH:mm:ss"); 162 163 /** 164 * @deprecated - as of 4.0, ISO_TIME_NO_T_FORMAT will be replaced by ISO_8601_EXTENDED_TIME_FORMAT. 165 */ 166 @Deprecated 167 public static final FastDateFormat ISO_TIME_NO_T_FORMAT = ISO_8601_EXTENDED_TIME_FORMAT; 168 169 /** 170 * ISO 8601 formatter for time with time zone. 171 * 172 * <p> 173 * The format used is {@code HH:mm:ssZZ}. This format uses the default 174 * TimeZone in effect at the time of loading DateFormatUtils class. 175 * </p> 176 * 177 * @since 3.5 178 */ 179 public static final FastDateFormat ISO_8601_EXTENDED_TIME_TIME_ZONE_FORMAT 180 = FastDateFormat.getInstance("HH:mm:ssZZ"); 181 182 /** 183 * @deprecated - as of 4.0, ISO_TIME_NO_T_TIME_ZONE_FORMAT will be replaced by ISO_8601_EXTENDED_TIME_TIME_ZONE_FORMAT. 184 */ 185 @Deprecated 186 public static final FastDateFormat ISO_TIME_NO_T_TIME_ZONE_FORMAT = ISO_8601_EXTENDED_TIME_TIME_ZONE_FORMAT; 187 188 /** 189 * SMTP (and probably other) date headers. 190 * 191 * <p> 192 * The format used is {@code EEE, dd MMM yyyy HH:mm:ss Z} in US locale. 193 * This format uses the default TimeZone in effect at the time of loading 194 * DateFormatUtils class. 195 * </p> 196 */ 197 public static final FastDateFormat SMTP_DATETIME_FORMAT 198 = FastDateFormat.getInstance("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US); 199 200 /** 201 * DateFormatUtils instances should NOT be constructed in standard programming. 202 * 203 * <p>This constructor is public to permit tools that require a JavaBean instance 204 * to operate.</p> 205 */ DateFormatUtils()206 public DateFormatUtils() { 207 } 208 209 /** 210 * Formats a calendar into a specific pattern. The TimeZone from the calendar 211 * will be used for formatting. 212 * 213 * @param calendar the calendar to format, not null 214 * @param pattern the pattern to use to format the calendar, not null 215 * @return the formatted calendar 216 * @see FastDateFormat#format(Calendar) 217 * @since 2.4 218 */ format(final Calendar calendar, final String pattern)219 public static String format(final Calendar calendar, final String pattern) { 220 return format(calendar, pattern, getTimeZone(calendar), null); 221 } 222 223 /** 224 * Formats a calendar into a specific pattern in a locale. The TimeZone from the calendar 225 * will be used for formatting. 226 * 227 * @param calendar the calendar to format, not null 228 * @param pattern the pattern to use to format the calendar, not null 229 * @param locale the locale to use, may be {@code null} 230 * @return the formatted calendar 231 * @see FastDateFormat#format(Calendar) 232 * @since 2.4 233 */ format(final Calendar calendar, final String pattern, final Locale locale)234 public static String format(final Calendar calendar, final String pattern, final Locale locale) { 235 return format(calendar, pattern, getTimeZone(calendar), locale); 236 } 237 238 /** 239 * Formats a calendar into a specific pattern in a time zone. 240 * 241 * @param calendar the calendar to format, not null 242 * @param pattern the pattern to use to format the calendar, not null 243 * @param timeZone the time zone to use, may be {@code null} 244 * @return the formatted calendar 245 * @see FastDateFormat#format(Calendar) 246 * @since 2.4 247 */ format(final Calendar calendar, final String pattern, final TimeZone timeZone)248 public static String format(final Calendar calendar, final String pattern, final TimeZone timeZone) { 249 return format(calendar, pattern, timeZone, null); 250 } 251 252 /** 253 * Formats a calendar into a specific pattern in a time zone and locale. 254 * 255 * @param calendar the calendar to format, not null 256 * @param pattern the pattern to use to format the calendar, not null 257 * @param timeZone the time zone to use, may be {@code null} 258 * @param locale the locale to use, may be {@code null} 259 * @return the formatted calendar 260 * @see FastDateFormat#format(Calendar) 261 * @since 2.4 262 */ format(final Calendar calendar, final String pattern, final TimeZone timeZone, final Locale locale)263 public static String format(final Calendar calendar, final String pattern, final TimeZone timeZone, final Locale locale) { 264 final FastDateFormat df = FastDateFormat.getInstance(pattern, timeZone, locale); 265 return df.format(calendar); 266 } 267 268 /** 269 * Formats a date/time into a specific pattern. 270 * 271 * @param date the date to format, not null 272 * @param pattern the pattern to use to format the date, not null 273 * @return the formatted date 274 */ format(final Date date, final String pattern)275 public static String format(final Date date, final String pattern) { 276 return format(date, pattern, null, null); 277 } 278 279 /** 280 * Formats a date/time into a specific pattern in a locale. 281 * 282 * @param date the date to format, not null 283 * @param pattern the pattern to use to format the date, not null 284 * @param locale the locale to use, may be {@code null} 285 * @return the formatted date 286 */ format(final Date date, final String pattern, final Locale locale)287 public static String format(final Date date, final String pattern, final Locale locale) { 288 return format(date, pattern, null, locale); 289 } 290 291 /** 292 * Formats a date/time into a specific pattern in a time zone. 293 * 294 * @param date the date to format, not null 295 * @param pattern the pattern to use to format the date, not null 296 * @param timeZone the time zone to use, may be {@code null} 297 * @return the formatted date 298 */ format(final Date date, final String pattern, final TimeZone timeZone)299 public static String format(final Date date, final String pattern, final TimeZone timeZone) { 300 return format(date, pattern, timeZone, null); 301 } 302 303 /** 304 * Formats a date/time into a specific pattern in a time zone and locale. 305 * 306 * @param date the date to format, not null 307 * @param pattern the pattern to use to format the date, not null, not null 308 * @param timeZone the time zone to use, may be {@code null} 309 * @param locale the locale to use, may be {@code null} 310 * @return the formatted date 311 */ format(final Date date, final String pattern, final TimeZone timeZone, final Locale locale)312 public static String format(final Date date, final String pattern, final TimeZone timeZone, final Locale locale) { 313 final FastDateFormat df = FastDateFormat.getInstance(pattern, timeZone, locale); 314 return df.format(date); 315 } 316 317 /** 318 * Formats a date/time into a specific pattern. 319 * 320 * @param millis the date to format expressed in milliseconds 321 * @param pattern the pattern to use to format the date, not null 322 * @return the formatted date 323 */ format(final long millis, final String pattern)324 public static String format(final long millis, final String pattern) { 325 return format(new Date(millis), pattern, null, null); 326 } 327 328 /** 329 * Formats a date/time into a specific pattern in a locale. 330 * 331 * @param millis the date to format expressed in milliseconds 332 * @param pattern the pattern to use to format the date, not null 333 * @param locale the locale to use, may be {@code null} 334 * @return the formatted date 335 */ format(final long millis, final String pattern, final Locale locale)336 public static String format(final long millis, final String pattern, final Locale locale) { 337 return format(new Date(millis), pattern, null, locale); 338 } 339 340 /** 341 * Formats a date/time into a specific pattern in a time zone. 342 * 343 * @param millis the time expressed in milliseconds 344 * @param pattern the pattern to use to format the date, not null 345 * @param timeZone the time zone to use, may be {@code null} 346 * @return the formatted date 347 */ format(final long millis, final String pattern, final TimeZone timeZone)348 public static String format(final long millis, final String pattern, final TimeZone timeZone) { 349 return format(new Date(millis), pattern, timeZone, null); 350 } 351 352 /** 353 * Formats a date/time into a specific pattern in a time zone and locale. 354 * 355 * @param millis the date to format expressed in milliseconds 356 * @param pattern the pattern to use to format the date, not null 357 * @param timeZone the time zone to use, may be {@code null} 358 * @param locale the locale to use, may be {@code null} 359 * @return the formatted date 360 */ format(final long millis, final String pattern, final TimeZone timeZone, final Locale locale)361 public static String format(final long millis, final String pattern, final TimeZone timeZone, final Locale locale) { 362 return format(new Date(millis), pattern, timeZone, locale); 363 } 364 365 /** 366 * Formats a date/time into a specific pattern using the UTC time zone. 367 * 368 * @param date the date to format, not null 369 * @param pattern the pattern to use to format the date, not null 370 * @return the formatted date 371 */ formatUTC(final Date date, final String pattern)372 public static String formatUTC(final Date date, final String pattern) { 373 return format(date, pattern, UTC_TIME_ZONE, null); 374 } 375 376 /** 377 * Formats a date/time into a specific pattern using the UTC time zone. 378 * 379 * @param date the date to format, not null 380 * @param pattern the pattern to use to format the date, not null 381 * @param locale the locale to use, may be {@code null} 382 * @return the formatted date 383 */ formatUTC(final Date date, final String pattern, final Locale locale)384 public static String formatUTC(final Date date, final String pattern, final Locale locale) { 385 return format(date, pattern, UTC_TIME_ZONE, locale); 386 } 387 388 /** 389 * Formats a date/time into a specific pattern using the UTC time zone. 390 * 391 * @param millis the date to format expressed in milliseconds 392 * @param pattern the pattern to use to format the date, not null 393 * @return the formatted date 394 */ formatUTC(final long millis, final String pattern)395 public static String formatUTC(final long millis, final String pattern) { 396 return format(new Date(millis), pattern, UTC_TIME_ZONE, null); 397 } 398 399 /** 400 * Formats a date/time into a specific pattern using the UTC time zone. 401 * 402 * @param millis the date to format expressed in milliseconds 403 * @param pattern the pattern to use to format the date, not null 404 * @param locale the locale to use, may be {@code null} 405 * @return the formatted date 406 */ formatUTC(final long millis, final String pattern, final Locale locale)407 public static String formatUTC(final long millis, final String pattern, final Locale locale) { 408 return format(new Date(millis), pattern, UTC_TIME_ZONE, locale); 409 } 410 getTimeZone(final Calendar calendar)411 private static TimeZone getTimeZone(final Calendar calendar) { 412 return calendar == null ? null : calendar.getTimeZone(); 413 } 414 415 } 416