首页

通过apache的日期格式工具类DateFormatUtils对常用日期字符串格式转换format处理

标签:DateFormatUtils,日期格式工具类,apache,FastDateFormat     发布时间:2017-12-28   

一、前言

对于apache-rat(0.9)包中org.apache.commons.lang.time.DateFormatUtils日期格式工具类,进行yyyy-MM-dd'T'HH:mm:ss"、yyyy-MM-dd'T'HH:mm:ssZZ、HH:mm:ssZZ、yyyy-MM-dd等待不同格式的转换处理。

二、源码说明

1.DateUtils日期工具类

package org.apache.commons.lang.time;@b@@b@import java.util.Date;@b@import java.util.Locale;@b@import java.util.TimeZone;@b@@b@public class DateFormatUtils@b@{@b@  public static final FastDateFormat ISO_DATETIME_FORMAT = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss");@b@  public static final FastDateFormat ISO_DATETIME_TIME_ZONE_FORMAT = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ssZZ");@b@  public static final FastDateFormat ISO_DATE_FORMAT = FastDateFormat.getInstance("yyyy-MM-dd");@b@  public static final FastDateFormat ISO_DATE_TIME_ZONE_FORMAT = FastDateFormat.getInstance("yyyy-MM-ddZZ");@b@  public static final FastDateFormat ISO_TIME_FORMAT = FastDateFormat.getInstance("'T'HH:mm:ss");@b@  public static final FastDateFormat ISO_TIME_TIME_ZONE_FORMAT = FastDateFormat.getInstance("'T'HH:mm:ssZZ");@b@  public static final FastDateFormat ISO_TIME_NO_T_FORMAT = FastDateFormat.getInstance("HH:mm:ss");@b@  public static final FastDateFormat ISO_TIME_NO_T_TIME_ZONE_FORMAT = FastDateFormat.getInstance("HH:mm:ssZZ");@b@  public static final FastDateFormat SMTP_DATETIME_FORMAT = FastDateFormat.getInstance("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);@b@@b@  public static String format(long millis, String pattern)@b@  {@b@    return format(new Date(millis), pattern, null, null);@b@  }@b@@b@  public static String format(long millis, String pattern, Locale locale)@b@  {@b@    return format(new Date(millis), pattern, null, locale);@b@  }@b@@b@  public static String format(long millis, String pattern, TimeZone timeZone)@b@  {@b@    return format(new Date(millis), pattern, timeZone, null);@b@  }@b@@b@  public static String format(long millis, String pattern, TimeZone timeZone, Locale locale)@b@  {@b@    return format(new Date(millis), pattern, timeZone, locale);@b@  }@b@@b@  public static String format(Date date, String pattern)@b@  {@b@    return format(date, pattern, null, null);@b@  }@b@@b@  public static String format(Date date, String pattern, Locale locale)@b@  {@b@    return format(date, pattern, null, locale);@b@  }@b@@b@  public static String format(Date date, String pattern, TimeZone timeZone)@b@  {@b@    return format(date, pattern, timeZone, null);@b@  }@b@@b@  public static String format(Date date, String pattern, TimeZone timeZone, Locale locale)@b@  {@b@    FastDateFormat df = FastDateFormat.getInstance(pattern, timeZone, locale);@b@    return df.format(date);@b@  }@b@@b@  public static String formatUTC(long millis, String pattern)@b@  {@b@    return format(new Date(millis), pattern, DateUtils.UTC_TIME_ZONE, null);@b@  }@b@@b@  public static String formatUTC(long millis, String pattern, Locale locale)@b@  {@b@    return format(new Date(millis), pattern, DateUtils.UTC_TIME_ZONE, locale);@b@  }@b@@b@  public static String formatUTC(Date date, String pattern)@b@  {@b@    return format(date, pattern, DateUtils.UTC_TIME_ZONE, null);@b@  }@b@@b@  public static String formatUTC(Date date, String pattern, Locale locale)@b@  {@b@    return format(date, pattern, DateUtils.UTC_TIME_ZONE, locale);@b@  }@b@}

2.FastDateFormat格式

package org.apache.commons.lang.time;@b@@b@import java.text.DateFormat;@b@import java.text.DateFormatSymbols;@b@import java.text.FieldPosition;@b@import java.text.Format;@b@import java.text.ParsePosition;@b@import java.text.SimpleDateFormat;@b@import java.util.ArrayList;@b@import java.util.Calendar;@b@import java.util.Date;@b@import java.util.GregorianCalendar;@b@import java.util.HashMap;@b@import java.util.List;@b@import java.util.Locale;@b@import java.util.Map;@b@import java.util.TimeZone;@b@@b@public class FastDateFormat extends Format@b@{@b@  public static final int FULL = 0;@b@  public static final int LONG = 1;@b@  public static final int MEDIUM = 2;@b@  public static final int SHORT = 3;@b@  static final double LOG_10 = Math.log(10.0D);@b@  private static String cDefaultPattern;@b@  private static Map cInstanceCache = new HashMap(7);@b@  private static Map cDateInstanceCache = new HashMap(7);@b@  private static Map cTimeInstanceCache = new HashMap(7);@b@  private static Map cDateTimeInstanceCache = new HashMap(7);@b@  private static Map cTimeZoneDisplayCache = new HashMap(7);@b@  private final String mPattern;@b@  private final TimeZone mTimeZone;@b@  private final boolean mTimeZoneForced;@b@  private final Locale mLocale;@b@  private final boolean mLocaleForced;@b@  private Rule[] mRules;@b@  private int mMaxLengthEstimate;@b@@b@  protected FastDateFormat(String pattern, TimeZone timeZone, Locale locale)@b@  {@b@    if (pattern == null)@b@      throw new IllegalArgumentException("The pattern must not be null");@b@@b@    this.mPattern = pattern;@b@@b@    this.mTimeZoneForced = (timeZone != null);@b@    if (timeZone == null)@b@      timeZone = TimeZone.getDefault();@b@@b@    this.mTimeZone = timeZone;@b@@b@    this.mLocaleForced = (locale != null);@b@    if (locale == null)@b@      locale = Locale.getDefault();@b@@b@    this.mLocale = locale;@b@  }@b@@b@  protected StringBuffer applyRules(Calendar calendar, StringBuffer buf)@b@  {@b@    Rule[] rules = this.mRules;@b@    int len = this.mRules.length;@b@    for (int i = 0; i < len; ++i)@b@      rules[i].appendTo(buf, calendar);@b@@b@    return buf;@b@  }@b@@b@  public boolean equals(Object obj)@b@  {@b@    if (obj instanceof FastDateFormat == false)@b@      return false;@b@@b@    FastDateFormat other = (FastDateFormat)obj;@b@@b@    return ((((this.mPattern == other.mPattern) || (this.mPattern.equals(other.mPattern)))) && @b@      (((this.mTimeZone == other.mTimeZone) || (this.mTimeZone.equals(other.mTimeZone)))) && @b@      (((this.mLocale == other.mLocale) || (this.mLocale.equals(other.mLocale)))) && @b@      (this.mTimeZoneForced == other.mTimeZoneForced) && @b@      (this.mLocaleForced == other.mLocaleForced));@b@  }@b@@b@  public String format(long millis)@b@  {@b@    return format(new Date(millis));@b@  }@b@@b@  public StringBuffer format(long millis, StringBuffer buf)@b@  {@b@    return format(new Date(millis), buf);@b@  }@b@@b@  public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos)@b@  {@b@    if (obj instanceof Date)@b@      return format((Date)obj, toAppendTo);@b@    if (obj instanceof Calendar)@b@      return format((Calendar)obj, toAppendTo);@b@    if (obj instanceof Long)@b@      return format(((Long)obj).longValue(), toAppendTo);@b@@b@    throw new IllegalArgumentException("Unknown class: " + @b@      obj.getClass().getName());@b@  }@b@@b@  public String format(Calendar calendar)@b@  {@b@    return format(calendar, new StringBuffer(this.mMaxLengthEstimate)).toString();@b@  }@b@@b@  public StringBuffer format(Calendar calendar, StringBuffer buf)@b@  {@b@    if (this.mTimeZoneForced) {@b@      calendar = (Calendar)calendar.clone();@b@      calendar.setTimeZone(this.mTimeZone);@b@    }@b@    return applyRules(calendar, buf);@b@  }@b@@b@  public String format(Date date)@b@  {@b@    Calendar c = new GregorianCalendar(this.mTimeZone);@b@    c.setTime(date);@b@    return applyRules(c, new StringBuffer(this.mMaxLengthEstimate)).toString();@b@  }@b@@b@  public StringBuffer format(Date date, StringBuffer buf)@b@  {@b@    Calendar c = new GregorianCalendar(this.mTimeZone);@b@    c.setTime(date);@b@    return applyRules(c, buf);@b@  }@b@@b@  public static FastDateFormat getDateInstance(int style)@b@  {@b@    return getDateInstance(style, null, null);@b@  }@b@@b@  public static FastDateFormat getDateInstance(int style, Locale locale)@b@  {@b@    return getDateInstance(style, null, locale);@b@  }@b@@b@  public static FastDateFormat getDateInstance(int style, TimeZone timeZone)@b@  {@b@    return getDateInstance(style, timeZone, null);@b@  }@b@@b@  public static synchronized FastDateFormat getDateInstance(int style, TimeZone timeZone, Locale locale)@b@  {@b@    Object key = new Integer(style);@b@    if (timeZone != null)@b@      key = new Pair(key, timeZone);@b@@b@    if (locale != null) {@b@      key = new Pair(key, locale);@b@    }@b@@b@    FastDateFormat format = (FastDateFormat)cDateInstanceCache.get(key);@b@    if (format == null) {@b@      if (locale == null)@b@        locale = Locale.getDefault();@b@@b@      try@b@      {@b@        SimpleDateFormat formatter = (SimpleDateFormat)DateFormat.getDateInstance(style, locale);@b@        String pattern = formatter.toPattern();@b@        format = getInstance(pattern, timeZone, locale);@b@        cDateInstanceCache.put(key, format);@b@      }@b@      catch (ClassCastException localClassCastException) {@b@        throw new IllegalArgumentException("No date pattern for locale: " + locale);@b@      }@b@    }@b@    return format;@b@  }@b@@b@  public static FastDateFormat getDateTimeInstance(int dateStyle, int timeStyle)@b@  {@b@    return getDateTimeInstance(dateStyle, timeStyle, null, null);@b@  }@b@@b@  public static FastDateFormat getDateTimeInstance(int dateStyle, int timeStyle, Locale locale)@b@  {@b@    return getDateTimeInstance(dateStyle, timeStyle, null, locale);@b@  }@b@@b@  public static FastDateFormat getDateTimeInstance(int dateStyle, int timeStyle, TimeZone timeZone)@b@  {@b@    return getDateTimeInstance(dateStyle, timeStyle, timeZone, null);@b@  }@b@@b@  public static synchronized FastDateFormat getDateTimeInstance(int dateStyle, int timeStyle, TimeZone timeZone, Locale locale)@b@  {@b@    Object key = new Pair(new Integer(dateStyle), new Integer(timeStyle));@b@    if (timeZone != null)@b@      key = new Pair(key, timeZone);@b@@b@    if (locale != null) {@b@      key = new Pair(key, locale);@b@    }@b@@b@    FastDateFormat format = (FastDateFormat)cDateTimeInstanceCache.get(key);@b@    if (format == null) {@b@      if (locale == null)@b@        locale = Locale.getDefault();@b@@b@      try@b@      {@b@        SimpleDateFormat formatter = (SimpleDateFormat)DateFormat.getDateTimeInstance(dateStyle, timeStyle, @b@          locale);@b@        String pattern = formatter.toPattern();@b@        format = getInstance(pattern, timeZone, locale);@b@        cDateTimeInstanceCache.put(key, format);@b@      }@b@      catch (ClassCastException localClassCastException) {@b@        throw new IllegalArgumentException("No date time pattern for locale: " + locale);@b@      }@b@    }@b@    return format;@b@  }@b@@b@  private static synchronized String getDefaultPattern()@b@  {@b@    if (cDefaultPattern == null)@b@      cDefaultPattern = new SimpleDateFormat().toPattern();@b@@b@    return cDefaultPattern;@b@  }@b@@b@  public static FastDateFormat getInstance()@b@  {@b@    return getInstance(getDefaultPattern(), null, null);@b@  }@b@@b@  public static FastDateFormat getInstance(String pattern)@b@  {@b@    return getInstance(pattern, null, null);@b@  }@b@@b@  public static FastDateFormat getInstance(String pattern, Locale locale)@b@  {@b@    return getInstance(pattern, null, locale);@b@  }@b@@b@  public static FastDateFormat getInstance(String pattern, TimeZone timeZone)@b@  {@b@    return getInstance(pattern, timeZone, null);@b@  }@b@@b@  public static synchronized FastDateFormat getInstance(String pattern, TimeZone timeZone, Locale locale)@b@  {@b@    FastDateFormat emptyFormat = new FastDateFormat(pattern, timeZone, locale);@b@    FastDateFormat format = (FastDateFormat)cInstanceCache.get(emptyFormat);@b@    if (format == null) {@b@      format = emptyFormat;@b@      format.init();@b@      cInstanceCache.put(format, format);@b@    }@b@    return format;@b@  }@b@@b@  public Locale getLocale()@b@  {@b@    return this.mLocale;@b@  }@b@@b@  public int getMaxLengthEstimate()@b@  {@b@    return this.mMaxLengthEstimate;@b@  }@b@@b@  public String getPattern()@b@  {@b@    return this.mPattern;@b@  }@b@@b@  public static FastDateFormat getTimeInstance(int style)@b@  {@b@    return getTimeInstance(style, null, null);@b@  }@b@@b@  public static FastDateFormat getTimeInstance(int style, Locale locale)@b@  {@b@    return getTimeInstance(style, null, locale);@b@  }@b@@b@  public static FastDateFormat getTimeInstance(int style, TimeZone timeZone)@b@  {@b@    return getTimeInstance(style, timeZone, null);@b@  }@b@@b@  public static synchronized FastDateFormat getTimeInstance(int style, TimeZone timeZone, Locale locale)@b@  {@b@    Object key = new Integer(style);@b@    if (timeZone != null)@b@      key = new Pair(key, timeZone);@b@@b@    if (locale != null) {@b@      key = new Pair(key, locale);@b@    }@b@@b@    FastDateFormat format = (FastDateFormat)cTimeInstanceCache.get(key);@b@    if (format == null) {@b@      if (locale == null)@b@        locale = Locale.getDefault();@b@@b@      try@b@      {@b@        SimpleDateFormat formatter = (SimpleDateFormat)DateFormat.getTimeInstance(style, locale);@b@        String pattern = formatter.toPattern();@b@        format = getInstance(pattern, timeZone, locale);@b@        cTimeInstanceCache.put(key, format);@b@      }@b@      catch (ClassCastException localClassCastException) {@b@        throw new IllegalArgumentException("No date pattern for locale: " + locale);@b@      }@b@    }@b@    return format;@b@  }@b@@b@  public TimeZone getTimeZone()@b@  {@b@    return this.mTimeZone;@b@  }@b@@b@  static synchronized String getTimeZoneDisplay(TimeZone tz, boolean daylight, int style, Locale locale)@b@  {@b@    Object key = new TimeZoneDisplayKey(tz, daylight, style, locale);@b@    String value = (String)cTimeZoneDisplayCache.get(key);@b@    if (value == null)@b@    {@b@      value = tz.getDisplayName(daylight, style, locale);@b@      cTimeZoneDisplayCache.put(key, value);@b@    }@b@    return value;@b@  }@b@@b@  public boolean getTimeZoneOverridesCalendar()@b@  {@b@    return this.mTimeZoneForced;@b@  }@b@@b@  public int hashCode()@b@  {@b@    int total = 0;@b@    total += this.mPattern.hashCode();@b@    total += this.mTimeZone.hashCode();@b@    total += ((this.mTimeZoneForced) ? 1 : 0);@b@    total += this.mLocale.hashCode();@b@    total += ((this.mLocaleForced) ? 1 : 0);@b@    return total;@b@  }@b@@b@  protected void init()@b@  {@b@    List rulesList = parsePattern();@b@    this.mRules = ((Rule[])rulesList.toArray(new Rule[rulesList.size()]));@b@@b@    int len = 0;@b@    for (int i = this.mRules.length; --i >= 0; ) {@b@      len += this.mRules[i].estimateLength();@b@    }@b@@b@    this.mMaxLengthEstimate = len;@b@  }@b@@b@  public Object parseObject(String source, ParsePosition pos)@b@  {@b@    pos.setIndex(0);@b@    pos.setErrorIndex(0);@b@    return null;@b@  }@b@@b@  protected List parsePattern()@b@  {@b@    DateFormatSymbols symbols = new DateFormatSymbols(this.mLocale);@b@    List rules = new ArrayList();@b@@b@    String[] ERAs = symbols.getEras();@b@    String[] months = symbols.getMonths();@b@    String[] shortMonths = symbols.getShortMonths();@b@    String[] weekdays = symbols.getWeekdays();@b@    String[] shortWeekdays = symbols.getShortWeekdays();@b@    String[] AmPmStrings = symbols.getAmPmStrings();@b@@b@    int length = this.mPattern.length();@b@    int[] indexRef = new int[1];@b@@b@    for (int i = 0; i < length; ++i) {@b@      Rule rule;@b@      indexRef[0] = i;@b@      String token = parseToken(this.mPattern, indexRef);@b@      i = indexRef[0];@b@@b@      int tokenLen = token.length();@b@      if (tokenLen == 0)@b@      {@b@        break;@b@      }@b@@b@      char c = token.charAt(0);@b@@b@      switch (c)@b@      {@b@      case 'G':@b@        rule = new TextField(0, ERAs);@b@        break;@b@      case 'y':@b@        if (tokenLen >= 4)@b@          rule = selectNumberRule(1, tokenLen);@b@        else@b@          rule = TwoDigitYearField.INSTANCE;@b@@b@        break;@b@      case 'M':@b@        if (tokenLen >= 4)@b@          rule = new TextField(2, months);@b@        else if (tokenLen == 3)@b@          rule = new TextField(2, shortMonths);@b@        else if (tokenLen == 2)@b@          rule = TwoDigitMonthField.INSTANCE;@b@        else@b@          rule = UnpaddedMonthField.INSTANCE;@b@@b@        break;@b@      case 'd':@b@        rule = selectNumberRule(5, tokenLen);@b@        break;@b@      case 'h':@b@        rule = new TwelveHourField(selectNumberRule(10, tokenLen));@b@        break;@b@      case 'H':@b@        rule = selectNumberRule(11, tokenLen);@b@        break;@b@      case 'm':@b@        rule = selectNumberRule(12, tokenLen);@b@        break;@b@      case 's':@b@        rule = selectNumberRule(13, tokenLen);@b@        break;@b@      case 'S':@b@        rule = selectNumberRule(14, tokenLen);@b@        break;@b@      case 'E':@b@        rule = new TextField(7, weekdays);@b@        break;@b@      case 'D':@b@        rule = selectNumberRule(6, tokenLen);@b@        break;@b@      case 'F':@b@        rule = selectNumberRule(8, tokenLen);@b@        break;@b@      case 'w':@b@        rule = selectNumberRule(3, tokenLen);@b@        break;@b@      case 'W':@b@        rule = selectNumberRule(4, tokenLen);@b@        break;@b@      case 'a':@b@        rule = new TextField(9, AmPmStrings);@b@        break;@b@      case 'k':@b@        rule = new TwentyFourHourField(selectNumberRule(11, tokenLen));@b@        break;@b@      case 'K':@b@        rule = selectNumberRule(10, tokenLen);@b@        break;@b@      case 'z':@b@        if (tokenLen >= 4)@b@          rule = new TimeZoneNameRule(this.mTimeZone, this.mTimeZoneForced, this.mLocale, 1);@b@        else@b@          rule = new TimeZoneNameRule(this.mTimeZone, this.mTimeZoneForced, this.mLocale, 0);@b@@b@        break;@b@      case 'Z':@b@        if (tokenLen == 1)@b@          rule = TimeZoneNumberRule.INSTANCE_NO_COLON;@b@        else@b@          rule = TimeZoneNumberRule.INSTANCE_COLON;@b@@b@        break;@b@      case '\'':@b@        String sub = token.substring(1);@b@        if (sub.length() == 1)@b@          rule = new CharacterLiteral(sub.charAt(0));@b@        else@b@          rule = new StringLiteral(sub);@b@@b@        break;@b@      default:@b@        throw new IllegalArgumentException("Illegal pattern component: " + token);@b@      }@b@@b@      rules.add(rule);@b@    }@b@@b@    return rules;@b@  }@b@@b@  protected String parseToken(String pattern, int[] indexRef)@b@  {@b@    StringBuffer buf = new StringBuffer();@b@@b@    int i = indexRef[0];@b@    int length = pattern.length();@b@@b@    char c = pattern.charAt(i);@b@    if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')))@b@    {@b@      buf.append(c);@b@@b@      while (i + 1 < length) {@b@        char peek = pattern.charAt(i + 1);@b@        if (peek != c) break label235;@b@        buf.append(c);@b@        ++i;@b@      }@b@@b@    }@b@    else@b@    {@b@      buf.append('\'');@b@@b@      boolean inLiteral = false;@b@@b@      for (; i < length; ++i) {@b@        c = pattern.charAt(i);@b@@b@        if (c == '\'') {@b@          if ((i + 1 < length) && (pattern.charAt(i + 1) == '\''))@b@          {@b@            ++i;@b@            buf.append(c);@b@          } else {@b@            inLiteral ^= true; }@b@        } else {@b@          if ((!(inLiteral)) && ((@b@            ((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'))))) {@b@            --i;@b@            break;@b@          }@b@          buf.append(c);@b@        }@b@      }@b@    }@b@@b@    label235: indexRef[0] = i;@b@    return buf.toString();@b@  }@b@@b@  protected NumberRule selectNumberRule(int field, int padding)@b@  {@b@    switch (padding)@b@    {@b@    case 1:@b@      return new UnpaddedNumberField(field);@b@    case 2:@b@      return new TwoDigitNumberField(field);@b@    }@b@    return new PaddedNumberField(field, padding);@b@  }@b@@b@  public String toString()@b@  {@b@    return "FastDateFormat[" + this.mPattern + "]";@b@  }@b@@b@  private static abstract interface Rule@b@  {@b@    public abstract void appendTo(StringBuffer paramStringBuffer, Calendar paramCalendar);@b@@b@    public abstract int estimateLength();@b@  }@b@@b@  private static abstract interface NumberRule extends FastDateFormat.Rule@b@  {@b@    public abstract void appendTo(StringBuffer paramStringBuffer, int paramInt);@b@  }@b@@b@  private static class CharacterLiteral@b@    implements FastDateFormat.Rule@b@  {@b@    private final char mValue;@b@@b@    CharacterLiteral(char value)@b@    {@b@      this.mValue = value;@b@    }@b@@b@    public void appendTo(StringBuffer buffer, Calendar calendar)@b@    {@b@      buffer.append(this.mValue);@b@    }@b@@b@    public int estimateLength()@b@    {@b@      return 1;@b@    }@b@  }@b@@b@  private static class StringLiteral@b@    implements FastDateFormat.Rule@b@  {@b@    private final String mValue;@b@@b@    StringLiteral(String value)@b@    {@b@      this.mValue = value;@b@    }@b@@b@    public void appendTo(StringBuffer buffer, Calendar calendar)@b@    {@b@      buffer.append(this.mValue);@b@    }@b@@b@    public int estimateLength()@b@    {@b@      return this.mValue.length();@b@    }@b@  }@b@@b@  private static class TextField@b@    implements FastDateFormat.Rule@b@  {@b@    private final int mField;@b@    private final String[] mValues;@b@@b@    TextField(int field, String[] values)@b@    {@b@      this.mField = field;@b@      this.mValues = values;@b@    }@b@@b@    public void appendTo(StringBuffer buffer, Calendar calendar)@b@    {@b@      buffer.append(this.mValues[calendar.get(this.mField)]);@b@    }@b@@b@    public int estimateLength()@b@    {@b@      int max = 0;@b@      for (int i = this.mValues.length; --i >= 0; ) {@b@        int len = this.mValues[i].length();@b@        if (len <= max) break label28;@b@        label28: max = len;@b@      }@b@@b@      return max;@b@    }@b@  }@b@@b@  private static class UnpaddedNumberField@b@    implements FastDateFormat.NumberRule@b@  {@b@    static final UnpaddedNumberField INSTANCE_YEAR = new UnpaddedNumberField(1);@b@    private final int mField;@b@@b@    UnpaddedNumberField(int field)@b@    {@b@      this.mField = field;@b@    }@b@@b@    public final void appendTo(StringBuffer buffer, int value)@b@    {@b@      if (value < 10) {@b@        buffer.append((char)(value + 48));@b@      } else if (value < 100) {@b@        buffer.append((char)(value / 10 + 48));@b@        buffer.append((char)(value % 10 + 48));@b@      } else {@b@        buffer.append(Integer.toString(value));@b@      }@b@    }@b@@b@    public void appendTo(StringBuffer buffer, Calendar calendar)@b@    {@b@      appendTo(buffer, calendar.get(this.mField));@b@    }@b@@b@    public int estimateLength()@b@    {@b@      return 4;@b@    }@b@  }@b@@b@  private static class UnpaddedMonthField@b@    implements FastDateFormat.NumberRule@b@  {@b@    static final UnpaddedMonthField INSTANCE = new UnpaddedMonthField();@b@@b@    public final void appendTo(StringBuffer buffer, int value)@b@    {@b@      if (value < 10) {@b@        buffer.append((char)(value + 48));@b@      } else {@b@        buffer.append((char)(value / 10 + 48));@b@        buffer.append((char)(value % 10 + 48));@b@      }@b@    }@b@@b@    public void appendTo(StringBuffer buffer, Calendar calendar)@b@    {@b@      appendTo(buffer, calendar.get(2) + 1);@b@    }@b@@b@    public int estimateLength()@b@    {@b@      return 2;@b@    }@b@  }@b@@b@  private static class PaddedNumberField@b@    implements FastDateFormat.NumberRule@b@  {@b@    private final int mField;@b@    private final int mSize;@b@@b@    PaddedNumberField(int field, int size)@b@    {@b@      if (size < 3)@b@      {@b@        throw new IllegalArgumentException();@b@      }@b@      this.mField = field;@b@      this.mSize = size;@b@    }@b@@b@    public final void appendTo(StringBuffer buffer, int value)@b@    {@b@      if (value < 100) {@b@        for (int i = this.mSize; --i >= 2; )@b@          buffer.append('0');@b@@b@        buffer.append((char)(value / 10 + 48));@b@        buffer.append((char)(value % 10 + 48));@b@      }@b@      else {@b@        int digits;@b@        if (value < 1000)@b@          digits = 3;@b@        else@b@          digits = (int)(Math.log(value) / FastDateFormat.LOG_10) + 1;@b@@b@        for (int i = this.mSize; --i >= digits; )@b@          buffer.append('0');@b@@b@        buffer.append(Integer.toString(value));@b@      }@b@    }@b@@b@    public void appendTo(StringBuffer buffer, Calendar calendar)@b@    {@b@      appendTo(buffer, calendar.get(this.mField));@b@    }@b@@b@    public int estimateLength()@b@    {@b@      return 4;@b@    }@b@  }@b@@b@  private static class TwoDigitNumberField@b@    implements FastDateFormat.NumberRule@b@  {@b@    private final int mField;@b@@b@    TwoDigitNumberField(int field)@b@    {@b@      this.mField = field;@b@    }@b@@b@    public final void appendTo(StringBuffer buffer, int value)@b@    {@b@      if (value < 100) {@b@        buffer.append((char)(value / 10 + 48));@b@        buffer.append((char)(value % 10 + 48));@b@      } else {@b@        buffer.append(Integer.toString(value));@b@      }@b@    }@b@@b@    public void appendTo(StringBuffer buffer, Calendar calendar)@b@    {@b@      appendTo(buffer, calendar.get(this.mField));@b@    }@b@@b@    public int estimateLength()@b@    {@b@      return 2;@b@    }@b@  }@b@@b@  private static class TwoDigitYearField@b@    implements FastDateFormat.NumberRule@b@  {@b@    static final TwoDigitYearField INSTANCE = new TwoDigitYearField();@b@@b@    public final void appendTo(StringBuffer buffer, int value)@b@    {@b@      buffer.append((char)(value / 10 + 48));@b@      buffer.append((char)(value % 10 + 48));@b@    }@b@@b@    public void appendTo(StringBuffer buffer, Calendar calendar)@b@    {@b@      appendTo(buffer, calendar.get(1) % 100);@b@    }@b@@b@    public int estimateLength()@b@    {@b@      return 2;@b@    }@b@  }@b@@b@  private static class TwoDigitMonthField@b@    implements FastDateFormat.NumberRule@b@  {@b@    static final TwoDigitMonthField INSTANCE = new TwoDigitMonthField();@b@@b@    public final void appendTo(StringBuffer buffer, int value)@b@    {@b@      buffer.append((char)(value / 10 + 48));@b@      buffer.append((char)(value % 10 + 48));@b@    }@b@@b@    public void appendTo(StringBuffer buffer, Calendar calendar)@b@    {@b@      appendTo(buffer, calendar.get(2) + 1);@b@    }@b@@b@    public int estimateLength()@b@    {@b@      return 2;@b@    }@b@  }@b@@b@  private static class TwelveHourField@b@    implements FastDateFormat.NumberRule@b@  {@b@    private final FastDateFormat.NumberRule mRule;@b@@b@    TwelveHourField(FastDateFormat.NumberRule rule)@b@    {@b@      this.mRule = rule;@b@    }@b@@b@    public void appendTo(StringBuffer buffer, int value)@b@    {@b@      this.mRule.appendTo(buffer, value);@b@    }@b@@b@    public void appendTo(StringBuffer buffer, Calendar calendar)@b@    {@b@      int value = calendar.get(10);@b@      if (value == 0)@b@        value = calendar.getLeastMaximum(10) + 1;@b@@b@      this.mRule.appendTo(buffer, value);@b@    }@b@@b@    public int estimateLength()@b@    {@b@      return this.mRule.estimateLength();@b@    }@b@  }@b@@b@  private static class TwentyFourHourField@b@    implements FastDateFormat.NumberRule@b@  {@b@    private final FastDateFormat.NumberRule mRule;@b@@b@    TwentyFourHourField(FastDateFormat.NumberRule rule)@b@    {@b@      this.mRule = rule;@b@    }@b@@b@    public void appendTo(StringBuffer buffer, int value)@b@    {@b@      this.mRule.appendTo(buffer, value);@b@    }@b@@b@    public void appendTo(StringBuffer buffer, Calendar calendar)@b@    {@b@      int value = calendar.get(11);@b@      if (value == 0)@b@        value = calendar.getMaximum(11) + 1;@b@@b@      this.mRule.appendTo(buffer, value);@b@    }@b@@b@    public int estimateLength()@b@    {@b@      return this.mRule.estimateLength();@b@    }@b@  }@b@@b@  private static class TimeZoneNameRule@b@    implements FastDateFormat.Rule@b@  {@b@    private final TimeZone mTimeZone;@b@    private final boolean mTimeZoneForced;@b@    private final Locale mLocale;@b@    private final int mStyle;@b@    private final String mStandard;@b@    private final String mDaylight;@b@@b@    TimeZoneNameRule(TimeZone timeZone, boolean timeZoneForced, Locale locale, int style)@b@    {@b@      this.mTimeZone = timeZone;@b@      this.mTimeZoneForced = timeZoneForced;@b@      this.mLocale = locale;@b@      this.mStyle = style;@b@@b@      if (timeZoneForced) {@b@        this.mStandard = FastDateFormat.getTimeZoneDisplay(timeZone, false, style, locale);@b@        this.mDaylight = FastDateFormat.getTimeZoneDisplay(timeZone, true, style, locale);@b@      } else {@b@        this.mStandard = null;@b@        this.mDaylight = null;@b@      }@b@    }@b@@b@    public void appendTo(StringBuffer buffer, Calendar calendar)@b@    {@b@      if (this.mTimeZoneForced) {@b@        if ((this.mTimeZone.useDaylightTime()) && (calendar.get(16) != 0))@b@          buffer.append(this.mDaylight);@b@        else@b@          buffer.append(this.mStandard);@b@      }@b@      else {@b@        TimeZone timeZone = calendar.getTimeZone();@b@        if ((timeZone.useDaylightTime()) && (calendar.get(16) != 0))@b@          buffer.append(FastDateFormat.getTimeZoneDisplay(timeZone, true, this.mStyle, this.mLocale));@b@        else@b@          buffer.append(FastDateFormat.getTimeZoneDisplay(timeZone, false, this.mStyle, this.mLocale));@b@      }@b@    }@b@@b@    public int estimateLength()@b@    {@b@      if (this.mTimeZoneForced)@b@        return Math.max(this.mStandard.length(), this.mDaylight.length());@b@      if (this.mStyle == 0)@b@        return 4;@b@@b@      return 40;@b@    }@b@  }@b@@b@  private static class TimeZoneNumberRule@b@    implements FastDateFormat.Rule@b@  {@b@    static final TimeZoneNumberRule INSTANCE_COLON = new TimeZoneNumberRule(true);@b@    static final TimeZoneNumberRule INSTANCE_NO_COLON = new TimeZoneNumberRule(false);@b@    final boolean mColon;@b@@b@    TimeZoneNumberRule(boolean colon)@b@    {@b@      this.mColon = colon;@b@    }@b@@b@    public void appendTo(StringBuffer buffer, Calendar calendar)@b@    {@b@      int offset = calendar.get(15) + calendar.get(16);@b@@b@      if (offset < 0) {@b@        buffer.append('-');@b@        offset = -offset;@b@      } else {@b@        buffer.append('+');@b@      }@b@@b@      int hours = offset / 3600000;@b@      buffer.append((char)(hours / 10 + 48));@b@      buffer.append((char)(hours % 10 + 48));@b@@b@      if (this.mColon) {@b@        buffer.append(':');@b@      }@b@@b@      int minutes = offset / 60000 - 60 * hours;@b@      buffer.append((char)(minutes / 10 + 48));@b@      buffer.append((char)(minutes % 10 + 48));@b@    }@b@@b@    public int estimateLength()@b@    {@b@      return 5;@b@    }@b@  }@b@@b@  private static class TimeZoneDisplayKey@b@  {@b@    private final TimeZone mTimeZone;@b@    private final int mStyle;@b@    private final Locale mLocale;@b@@b@    TimeZoneDisplayKey(TimeZone timeZone, boolean daylight, int style, Locale locale)@b@    {@b@      this.mTimeZone = timeZone;@b@      if (daylight)@b@        style |= -2147483648;@b@@b@      this.mStyle = style;@b@      this.mLocale = locale;@b@    }@b@@b@    public boolean equals(Object obj)@b@    {@b@      if (this == obj)@b@        return true;@b@@b@      if (obj instanceof TimeZoneDisplayKey) {@b@        TimeZoneDisplayKey other = (TimeZoneDisplayKey)obj;@b@        return @b@          ((this.mTimeZone.equals(other.mTimeZone)) && @b@          (this.mStyle == other.mStyle) && @b@          (this.mLocale.equals(other.mLocale)));@b@      }@b@      return false;@b@    }@b@@b@    public int hashCode()@b@    {@b@      return (this.mStyle * 31 + this.mLocale.hashCode());@b@    }@b@  }@b@@b@  private static class Pair@b@  {@b@    private final Object mObj1;@b@    private final Object mObj2;@b@@b@    public Pair(Object obj1, Object obj2)@b@    {@b@      this.mObj1 = obj1;@b@      this.mObj2 = obj2;@b@    }@b@@b@    public boolean equals(Object obj) {@b@      if (this == obj) {@b@        return true;@b@      }@b@@b@      if (!(obj instanceof Pair)) {@b@        return false;@b@      }@b@@b@      Pair key = (Pair)obj;@b@@b@      if (this.mObj1 == null);@b@      if (@b@        ((key.mObj1 != null) ? false : this.mObj1.equals(key.mObj1)))@b@        if (this.mObj2 == null);@b@      return @b@        (@b@        ((key.mObj2 != null) ? false : this.mObj2.equals(key.mObj2)));@b@    }@b@@b@    public int hashCode() {@b@      return @b@        (((this.mObj1 == null) ? 0 : this.mObj1.hashCode()) + @b@        ((this.mObj2 == null) ? 0 : this.mObj2.hashCode()));@b@    }@b@@b@    public String toString() {@b@      return "[" + this.mObj1 + ':' + this.mObj2 + ']';@b@    }@b@  }@b@}