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 * https://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 */ 017 018package org.apache.commons.lang3.time; 019 020import java.text.DateFormat; 021import java.text.FieldPosition; 022import java.text.Format; 023import java.text.ParseException; 024import java.text.ParsePosition; 025import java.text.SimpleDateFormat; 026import java.util.Calendar; 027import java.util.Date; 028import java.util.GregorianCalendar; 029import java.util.Locale; 030import java.util.TimeZone; 031 032/** 033 * FastDateFormat is a fast and thread-safe version of {@link java.text.SimpleDateFormat}. 034 * 035 * <p> 036 * To obtain an instance of FastDateFormat, use one of the static factory methods: {@link #getInstance(String, TimeZone, Locale)}, 037 * {@link #getDateInstance(int, TimeZone, Locale)}, {@link #getTimeInstance(int, TimeZone, Locale)}, or {@link #getDateTimeInstance(int, int, TimeZone, Locale)} 038 * </p> 039 * 040 * <p> 041 * Since FastDateFormat is thread safe, you can use a static member instance: 042 * </p> 043 * {@code 044 * private static final FastDateFormat DATE_FORMATTER = FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.SHORT); 045 * } 046 * 047 * <p> 048 * This class can be used as a direct replacement to {@link SimpleDateFormat} in most formatting and parsing situations. This class is especially useful in 049 * multi-threaded server environments. {@link SimpleDateFormat} is not thread-safe in any JDK version, nor will it be as Sun have closed the bug/RFE. 050 * </p> 051 * 052 * <p> 053 * Note on memory retention: unlike {@code new SimpleDateFormat(pattern)}, instances obtained from the static factory methods are held in a static cache keyed 054 * by (pattern, time zone, locale). The cache is bounded (it is flushed when it exceeds an internal limit) and can be flushed explicitly with 055 * {@link #clear()}, but each distinct key retains its instance for the lifetime of the JVM until then. Prefer fixed, application-defined patterns; do not 056 * pass unvalidated caller-supplied pattern, time zone, or locale values to the factory methods. 057 * </p> 058 * 059 * <p> 060 * All patterns are compatible with SimpleDateFormat (except time zones and some year patterns - see below). 061 * </p> 062 * 063 * <p> 064 * Since 3.2, FastDateFormat supports parsing as well as printing. 065 * </p> 066 * 067 * <p> 068 * Java 1.4 introduced a new pattern letter, {@code 'Z'}, to represent time zones in RFC822 format (for example, {@code +0800} or {@code -1100}). This pattern letter can 069 * be used here (on all JDK versions). 070 * </p> 071 * 072 * <p> 073 * The pattern {@code 'ZZ'} represents ISO 8601 extended format time zones (for example, {@code +08:00} or {@code -11:00}), printing {@code Z} for 074 * a zero offset. Three or more {@code 'Z'} letters also print colon-separated offsets, but print {@code +00:00} for a zero offset. These patterns differ 075 * from {@link SimpleDateFormat}. 076 * </p> 077 * 078 * <p> 079 * When parsing, {@code 'ZZ'} accepts {@code Z} or a colon-separated numeric offset. Three or more {@code 'Z'} letters accept colon-separated numeric 080 * offsets as well as the RFC822 offsets, GMT offsets, and localized time zone names accepted by a single {@code 'Z'}. 081 * </p> 082 * 083 * <p> 084 * Javadoc cites for the year pattern: <i>For formatting, if the number of pattern letters is 2, the year is truncated to 2 digits; otherwise it is interpreted 085 * as a number.</i> Starting with Java 1.7 a pattern of 'Y' or 'YYY' will be formatted as '2003', while it was '03' in former Java versions. FastDateFormat 086 * implements the behavior of Java 7. 087 * </p> 088 * 089 * @since 2.0 090 */ 091public class FastDateFormat extends Format implements DateParser, DatePrinter { 092 093 /** 094 * Required for serialization support. 095 * 096 * @see java.io.Serializable 097 */ 098 private static final long serialVersionUID = 2L; 099 100 /** 101 * FULL locale dependent date or time style. 102 */ 103 public static final int FULL = DateFormat.FULL; 104 105 /** 106 * LONG locale dependent date or time style. 107 */ 108 public static final int LONG = DateFormat.LONG; 109 110 /** 111 * MEDIUM locale dependent date or time style. 112 */ 113 public static final int MEDIUM = DateFormat.MEDIUM; 114 115 /** 116 * SHORT locale dependent date or time style. 117 */ 118 public static final int SHORT = DateFormat.SHORT; 119 120 private static final AbstractFormatCache<FastDateFormat> CACHE = new AbstractFormatCache<FastDateFormat>() { 121 122 @Override 123 protected FastDateFormat createInstance(final String pattern, final TimeZone timeZone, final Locale locale) { 124 return new FastDateFormat(pattern, timeZone, locale); 125 } 126 }; 127 128 /** 129 * Clears the caches. 130 * <p> 131 * Clears the static caches used by {@link FastDateFormat}: the (pattern, time zone, locale) to instance cache and the time zone display-name cache. 132 * Cached instances already obtained by callers remain valid; subsequent factory calls simply create and cache new instances. This can be used for 133 * operational relief if many distinct patterns, time zones, or locales have been used. 134 * </p> 135 */ 136 static void clear() { 137 AbstractFormatCache.clear(); 138 CACHE.clearInstance(); 139 FastDatePrinter.clear(); 140 } 141 142// /** 143// * Clears the static caches used by {@link FastDateFormat}: the (pattern, time zone, locale) to instance cache and the time zone display-name cache. 144// * Cached instances already obtained by callers remain valid; subsequent factory calls simply create and cache new instances. This can be used for 145// * operational relief if many distinct patterns, time zones, or locales have been used. 146// * 147// * @since 3.21.0 148// */ 149// public static void clearCache() { 150// clear(); 151// FastDatePrinter.clear(); 152// } 153 154 /** 155 * Gets a date formatter instance using the specified style in the default time zone and locale. 156 * 157 * @param style date style: {@link #FULL}, {@link #LONG}, {@link #MEDIUM}, or {@link #SHORT}. 158 * @return A localized standard date formatter. 159 * @throws IllegalArgumentException Thrown if the Locale has no date pattern defined. 160 * @since 2.1 161 */ 162 public static FastDateFormat getDateInstance(final int style) { 163 return CACHE.getDateInstance(style, null, null); 164 } 165 166 /** 167 * Gets a date formatter instance using the specified style and locale in the default time zone. 168 * 169 * @param style date style: {@link #FULL}, LO{@link #FULL},{@link #MEDIUM}, or {@link #SHORT}. 170 * @param locale optional locale, overrides system locale. 171 * @return A localized standard date formatter. 172 * @throws IllegalArgumentException Thrown if the Locale has no date pattern defined. 173 * @since 2.1 174 */ 175 public static FastDateFormat getDateInstance(final int style, final Locale locale) { 176 return CACHE.getDateInstance(style, null, locale); 177 } 178 179 /** 180 * Gets a date formatter instance using the specified style and time zone in the default locale. 181 * 182 * @param style date style: {@link #FULL}, {@link #LONG}, {@link #MEDIUM}, or {@link #SHORT}. 183 * @param timeZone optional time zone, overrides time zone of formatted date. 184 * @return A localized standard date formatter. 185 * @throws IllegalArgumentException Thrown if the Locale has no date pattern defined. 186 * @since 2.1 187 */ 188 public static FastDateFormat getDateInstance(final int style, final TimeZone timeZone) { 189 return CACHE.getDateInstance(style, timeZone, null); 190 } 191 192 /** 193 * Gets a date formatter instance using the specified style, time zone and locale. 194 * 195 * @param style date style: {@link #FULL}, {@link #LONG}, {@link #MEDIUM}, or {@link #SHORT}. 196 * @param timeZone optional time zone, overrides time zone of formatted date. 197 * @param locale optional locale, overrides system locale. 198 * @return A localized standard date formatter. 199 * @throws IllegalArgumentException Thrown if the Locale has no date pattern defined. 200 */ 201 public static FastDateFormat getDateInstance(final int style, final TimeZone timeZone, final Locale locale) { 202 return CACHE.getDateInstance(style, timeZone, locale); 203 } 204 205 /** 206 * Gets a date/time formatter instance using the specified style in the default time zone and locale. 207 * 208 * @param dateStyle date style: {@link #FULL}, {@link #LONG}, {@link #MEDIUM}, or {@link #SHORT}. 209 * @param timeStyle time style: {@link #FULL}, {@link #LONG}, {@link #MEDIUM}, or {@link #SHORT}. 210 * @return A localized standard date/time formatter. 211 * @throws IllegalArgumentException Thrown if the Locale has no date/time pattern defined. 212 * @since 2.1 213 */ 214 public static FastDateFormat getDateTimeInstance(final int dateStyle, final int timeStyle) { 215 return CACHE.getDateTimeInstance(dateStyle, timeStyle, null, null); 216 } 217 218 /** 219 * Gets a date/time formatter instance using the specified style and locale in the default time zone. 220 * 221 * @param dateStyle date style: {@link #FULL}, {@link #LONG}, {@link #MEDIUM}, or {@link #SHORT}. 222 * @param timeStyle time style: {@link #FULL}, {@link #LONG}, {@link #MEDIUM}, or {@link #SHORT}. 223 * @param locale optional locale, overrides system locale. 224 * @return A localized standard date/time formatter. 225 * @throws IllegalArgumentException Thrown if the Locale has no date/time pattern defined. 226 * @since 2.1 227 */ 228 public static FastDateFormat getDateTimeInstance(final int dateStyle, final int timeStyle, final Locale locale) { 229 return CACHE.getDateTimeInstance(dateStyle, timeStyle, null, locale); 230 } 231 232 /** 233 * Gets a date/time formatter instance using the specified style and time zone in the default locale. 234 * 235 * @param dateStyle date style: {@link #FULL}, {@link #LONG}, {@link #MEDIUM}, or {@link #SHORT}. 236 * @param timeStyle time style: {@link #FULL}, {@link #LONG}, {@link #MEDIUM}, or {@link #SHORT}. 237 * @param timeZone optional time zone, overrides time zone of formatted date. 238 * @return A localized standard date/time formatter. 239 * @throws IllegalArgumentException Thrown if the Locale has no date/time pattern defined. 240 * @since 2.1 241 */ 242 public static FastDateFormat getDateTimeInstance(final int dateStyle, final int timeStyle, final TimeZone timeZone) { 243 return getDateTimeInstance(dateStyle, timeStyle, timeZone, null); 244 } 245 246 /** 247 * Gets a date/time formatter instance using the specified style, time zone and locale. 248 * 249 * @param dateStyle date style: {@link #FULL}, {@link #LONG}, {@link #MEDIUM}, or {@link #SHORT}. 250 * @param timeStyle time style: {@link #FULL}, {@link #LONG}, {@link #MEDIUM}, or {@link #SHORT}. 251 * @param timeZone optional time zone, overrides time zone of formatted date. 252 * @param locale optional locale, overrides system locale. 253 * @return A localized standard date/time formatter. 254 * @throws IllegalArgumentException Thrown if the Locale has no date/time pattern defined. 255 */ 256 public static FastDateFormat getDateTimeInstance(final int dateStyle, final int timeStyle, final TimeZone timeZone, final Locale locale) { 257 return CACHE.getDateTimeInstance(dateStyle, timeStyle, timeZone, locale); 258 } 259 260 /** 261 * Gets a formatter instance using the default pattern in the default locale. 262 * 263 * @return A date/time formatter. 264 */ 265 public static FastDateFormat getInstance() { 266 return CACHE.getInstance(); 267 } 268 269 /** 270 * Gets a formatter instance using the specified pattern in the default locale and time zone. 271 * 272 * @param pattern {@link java.text.SimpleDateFormat} compatible pattern. 273 * @return A pattern based date/time formatter. 274 * @throws IllegalArgumentException Thrown if pattern is invalid. 275 */ 276 public static FastDateFormat getInstance(final String pattern) { 277 return CACHE.getInstance(pattern, null, null); 278 } 279 280 /** 281 * Gets a formatter instance using the specified pattern and locale using the default time zone. 282 * 283 * @param pattern {@link java.text.SimpleDateFormat} compatible pattern. 284 * @param locale optional locale, overrides system locale. 285 * @return A pattern based date/time formatter. 286 * @throws IllegalArgumentException Thrown if pattern is invalid. 287 */ 288 public static FastDateFormat getInstance(final String pattern, final Locale locale) { 289 return CACHE.getInstance(pattern, null, locale); 290 } 291 292 /** 293 * Gets a formatter instance using the specified pattern and time zone. 294 * 295 * @param pattern {@link java.text.SimpleDateFormat} compatible pattern. 296 * @param timeZone optional time zone, overrides time zone of formatted date. 297 * @return A pattern based date/time formatter. 298 * @throws IllegalArgumentException Thrown if pattern is invalid. 299 */ 300 public static FastDateFormat getInstance(final String pattern, final TimeZone timeZone) { 301 return CACHE.getInstance(pattern, timeZone, null); 302 } 303 304 /** 305 * Gets a formatter instance using the specified pattern, time zone and locale. 306 * 307 * @param pattern {@link java.text.SimpleDateFormat} compatible pattern. 308 * @param timeZone optional time zone, overrides time zone of formatted date. 309 * @param locale optional locale, overrides system locale. 310 * @return A pattern based date/time formatter. 311 * @throws IllegalArgumentException Thrown if pattern is invalid or {@code null}. 312 */ 313 public static FastDateFormat getInstance(final String pattern, final TimeZone timeZone, final Locale locale) { 314 return CACHE.getInstance(pattern, timeZone, locale); 315 } 316 317 /** 318 * Gets a time formatter instance using the specified style in the default time zone and locale. 319 * 320 * @param style time style: {@link #FULL}, {@link #LONG}, {@link #MEDIUM}, or {@link #SHORT}. 321 * @return A localized standard time formatter. 322 * @throws IllegalArgumentException Thrown if the Locale has no time pattern defined. 323 * @since 2.1 324 */ 325 public static FastDateFormat getTimeInstance(final int style) { 326 return CACHE.getTimeInstance(style, null, null); 327 } 328 329 /** 330 * Gets a time formatter instance using the specified style and locale in the default time zone. 331 * 332 * @param style time style: {@link #FULL}, {@link #LONG}, {@link #MEDIUM}, or {@link #SHORT}. 333 * @param locale optional locale, overrides system locale. 334 * @return A localized standard time formatter. 335 * @throws IllegalArgumentException Thrown if the Locale has no time pattern defined. 336 * @since 2.1 337 */ 338 public static FastDateFormat getTimeInstance(final int style, final Locale locale) { 339 return CACHE.getTimeInstance(style, null, locale); 340 } 341 342 /** 343 * Gets a time formatter instance using the specified style and time zone in the default locale. 344 * 345 * @param style time style: {@link #FULL}, {@link #LONG}, {@link #MEDIUM}, or {@link #SHORT}. 346 * @param timeZone optional time zone, overrides time zone of formatted time. 347 * @return A localized standard time formatter. 348 * @throws IllegalArgumentException Thrown if the Locale has no time pattern defined. 349 * @since 2.1 350 */ 351 public static FastDateFormat getTimeInstance(final int style, final TimeZone timeZone) { 352 return CACHE.getTimeInstance(style, timeZone, null); 353 } 354 355 /** 356 * Gets a time formatter instance using the specified style, time zone and locale. 357 * 358 * @param style time style: {@link #FULL}, {@link #LONG}, {@link #MEDIUM}, or {@link #SHORT}. 359 * @param timeZone optional time zone, overrides time zone of formatted time. 360 * @param locale optional locale, overrides system locale. 361 * @return A localized standard time formatter. 362 * @throws IllegalArgumentException Thrown if the Locale has no time pattern defined. 363 */ 364 public static FastDateFormat getTimeInstance(final int style, final TimeZone timeZone, final Locale locale) { 365 return CACHE.getTimeInstance(style, timeZone, locale); 366 } 367 368 /** Our fast printer. */ 369 private final FastDatePrinter printer; 370 371 /** Our fast parser. */ 372 private final FastDateParser parser; 373 374 /** 375 * Constructs a new FastDateFormat. 376 * 377 * @param pattern {@link java.text.SimpleDateFormat} compatible pattern. 378 * @param timeZone non-null time zone to use. 379 * @param locale non-null locale to use. 380 * @throws NullPointerException Thrown if pattern, timeZone, or locale is null. 381 */ 382 protected FastDateFormat(final String pattern, final TimeZone timeZone, final Locale locale) { 383 this(pattern, timeZone, locale, null); 384 } 385 386 /** 387 * Constructs a new FastDateFormat. 388 * 389 * @param pattern {@link java.text.SimpleDateFormat} compatible pattern. 390 * @param timeZone non-null time zone to use. 391 * @param locale non-null locale to use. 392 * @param centuryStart The start of the 100-year period to use as the "default century" for 2 digit year parsing. If centuryStart is null, defaults to now - 393 * 80 years. 394 * @throws NullPointerException Thrown if pattern, timeZone, or locale is null. 395 */ 396 protected FastDateFormat(final String pattern, final TimeZone timeZone, final Locale locale, final Date centuryStart) { 397 printer = new FastDatePrinter(pattern, timeZone, locale); 398 parser = new FastDateParser(pattern, timeZone, locale, centuryStart); 399 } 400 401 /** 402 * Performs the formatting by applying the rules to the specified calendar. 403 * 404 * @param calendar The calendar to format. 405 * @param buf The buffer to format into. 406 * @return The specified string buffer. 407 * @deprecated Use {@link #format(Calendar, Appendable)} 408 */ 409 @Deprecated 410 protected StringBuffer applyRules(final Calendar calendar, final StringBuffer buf) { 411 return printer.format(calendar, buf); 412 } 413 414 /** 415 * Compares two objects for equality. 416 * 417 * @param obj The object to compare to. 418 * @return {@code true} if equal. 419 */ 420 @Override 421 public boolean equals(final Object obj) { 422 if (!(obj instanceof FastDateFormat)) { 423 return false; 424 } 425 final FastDateFormat other = (FastDateFormat) obj; 426 // no need to check parser, as it has same invariants as printer 427 return printer.equals(other.printer); 428 } 429 430 /** 431 * Formats a {@link Calendar} object. 432 * 433 * @param calendar The calendar to format. 434 * @return The formatted string. 435 */ 436 @Override 437 public String format(final Calendar calendar) { 438 return printer.format(calendar); 439 } 440 441 /** 442 * Formats a {@link Calendar} object into the supplied {@link StringBuffer}. 443 * 444 * @param calendar The calendar to format. 445 * @param buf The buffer to format into. 446 * @return The specified string buffer. 447 * @since 3.5 448 */ 449 @Override 450 public <B extends Appendable> B format(final Calendar calendar, final B buf) { 451 return printer.format(calendar, buf); 452 } 453 454 /** 455 * Formats a {@link Calendar} object into the supplied {@link StringBuffer}. 456 * 457 * @param calendar The calendar to format. 458 * @param buf The buffer to format into. 459 * @return The specified string buffer. 460 * @deprecated Use {{@link #format(Calendar, Appendable)}. 461 */ 462 @Deprecated 463 @Override 464 public StringBuffer format(final Calendar calendar, final StringBuffer buf) { 465 return printer.format(calendar, buf); 466 } 467 468 /** 469 * Formats a {@link Date} object using a {@link GregorianCalendar}. 470 * 471 * @param date The date to format. 472 * @return The formatted string. 473 */ 474 @Override 475 public String format(final Date date) { 476 return printer.format(date); 477 } 478 479 /** 480 * Formats a {@link Date} object into the supplied {@link StringBuffer} using a {@link GregorianCalendar}. 481 * 482 * @param date The date to format. 483 * @param buf The buffer to format into. 484 * @return The specified string buffer. 485 * @since 3.5 486 */ 487 @Override 488 public <B extends Appendable> B format(final Date date, final B buf) { 489 return printer.format(date, buf); 490 } 491 492 /** 493 * Formats a {@link Date} object into the supplied {@link StringBuffer} using a {@link GregorianCalendar}. 494 * 495 * @param date The date to format. 496 * @param buf The buffer to format into. 497 * @return The specified string buffer. 498 * @deprecated Use {{@link #format(Date, Appendable)}. 499 */ 500 @Deprecated 501 @Override 502 public StringBuffer format(final Date date, final StringBuffer buf) { 503 return printer.format(date, buf); 504 } 505 506 /** 507 * Formats a millisecond {@code long} value. 508 * 509 * @param millis The millisecond value to format. 510 * @return The formatted string. 511 * @since 2.1 512 */ 513 @Override 514 public String format(final long millis) { 515 return printer.format(millis); 516 } 517 518 /** 519 * Formats a millisecond {@code long} value into the supplied {@link StringBuffer}. 520 * 521 * @param millis The millisecond value to format. 522 * @param buf The buffer to format into. 523 * @return The specified string buffer. 524 * @since 3.5 525 */ 526 @Override 527 public <B extends Appendable> B format(final long millis, final B buf) { 528 return printer.format(millis, buf); 529 } 530 531 /** 532 * Formats a millisecond {@code long} value into the supplied {@link StringBuffer}. 533 * 534 * @param millis The millisecond value to format. 535 * @param buf The buffer to format into. 536 * @return The specified string buffer. 537 * @since 2.1 538 * @deprecated Use {{@link #format(long, Appendable)}. 539 */ 540 @Deprecated 541 @Override 542 public StringBuffer format(final long millis, final StringBuffer buf) { 543 return printer.format(millis, buf); 544 } 545 546 /** 547 * Formats a {@link Date}, {@link Calendar} or {@link Long} (milliseconds) object. This method is an implementation of 548 * {@link Format#format(Object, StringBuffer, FieldPosition)} 549 * 550 * @param obj The object to format. 551 * @param toAppendTo The buffer to append to. 552 * @param pos The position, ignored. 553 * @return The given buffer. 554 */ 555 @Override 556 public StringBuffer format(final Object obj, final StringBuffer toAppendTo, final FieldPosition pos) { 557 return toAppendTo.append(printer.format(obj)); 558 } 559 560 /** 561 * Gets the locale used by this formatter. 562 * 563 * @return The locale. 564 */ 565 @Override 566 public Locale getLocale() { 567 return printer.getLocale(); 568 } 569 570 /** 571 * Gets an estimate for the maximum string length that the formatter will produce. 572 * 573 * <p> 574 * The actual formatted length will almost always be less than or equal to this amount. 575 * </p> 576 * 577 * @return The maximum formatted length. 578 */ 579 public int getMaxLengthEstimate() { 580 return printer.getMaxLengthEstimate(); 581 } 582 583 /** 584 * Gets the pattern used by this formatter. 585 * 586 * @return The pattern, {@link java.text.SimpleDateFormat} compatible. 587 */ 588 @Override 589 public String getPattern() { 590 return printer.getPattern(); 591 } 592 593 /** 594 * Gets the time zone used by this formatter. 595 * 596 * <p> 597 * This zone is always used for {@link Date} formatting. 598 * </p> 599 * 600 * @return A copy of the time zone, changing it has no effect on this formatter. 601 */ 602 @Override 603 public TimeZone getTimeZone() { 604 return printer.getTimeZone(); 605 } 606 607 /** 608 * Returns a hash code compatible with equals. 609 * 610 * @return A hash code compatible with equals. 611 */ 612 @Override 613 public int hashCode() { 614 return printer.hashCode(); 615 } 616 617 /* 618 * (non-Javadoc) 619 * 620 * @see DateParser#parse(String) 621 */ 622 @Override 623 public Date parse(final String source) throws ParseException { 624 return parser.parse(source); 625 } 626 627 /* 628 * (non-Javadoc) 629 * 630 * @see DateParser#parse(String, java.text.ParsePosition) 631 */ 632 @Override 633 public Date parse(final String source, final ParsePosition pos) { 634 return parser.parse(source, pos); 635 } 636 637 /* 638 * (non-Javadoc) 639 * 640 * @see org.apache.commons.lang3.time.DateParser#parse(String, java.text.ParsePosition, java.util.Calendar) 641 */ 642 @Override 643 public boolean parse(final String source, final ParsePosition pos, final Calendar calendar) { 644 return parser.parse(source, pos, calendar); 645 } 646 647 /* 648 * (non-Javadoc) 649 * 650 * @see java.text.Format#parseObject(String, java.text.ParsePosition) 651 */ 652 @Override 653 public Object parseObject(final String source, final ParsePosition pos) { 654 return parser.parseObject(source, pos); 655 } 656 657 /** 658 * Gets a debugging string version of this formatter. 659 * 660 * @return A debug string. 661 */ 662 @Override 663 public String toString() { 664 return "FastDateFormat[" + printer.getPattern() + "," + printer.getLocale() + "," + printer.getTimeZone().getID() + "]"; 665 } 666}