| 1 52 53 package com.go.trove.util; 54 55 import java.util.Date ; 56 import java.util.Calendar ; 57 import java.util.GregorianCalendar ; 58 import java.util.Locale ; 59 import java.util.TimeZone ; 60 import java.util.List ; 61 import java.util.ArrayList ; 62 import java.util.Map ; 63 import java.util.HashMap ; 64 import java.text.DateFormatSymbols ; 65 import java.text.DateFormat ; 66 import java.text.SimpleDateFormat ; 67 68 77 public class FastDateFormat { 78 79 public static final Object  80 FULL = new Integer (SimpleDateFormat.FULL), 81 LONG = new Integer (SimpleDateFormat.LONG), 82 MEDIUM = new Integer (SimpleDateFormat.MEDIUM), 83 SHORT = new Integer (SimpleDateFormat.SHORT); 84 85 private static final double LOG_10 = Math.log(10); 86 87 private static String cDefaultPattern; 88 private static TimeZone cDefaultTimeZone = TimeZone.getDefault(); 89 90 private static Map cTimeZoneDisplayCache = new HashMap (); 91 92 private static Map cInstanceCache = new HashMap (7); 93 private static Map cDateInstanceCache = new HashMap (7); 94 private static Map cTimeInstanceCache = new HashMap (7); 95 private static Map cDateTimeInstanceCache = new HashMap (7); 96 97 public static FastDateFormat getInstance() { 98 return getInstance(getDefaultPattern(), null, null, null); 99 } 100 101 104 public static FastDateFormat getInstance(String pattern) 105 throws IllegalArgumentException  106 { 107 return getInstance(pattern, null, null, null); 108 } 109 110 115 public static FastDateFormat getInstance 116 (String pattern, TimeZone timeZone) throws IllegalArgumentException  117 { 118 return getInstance(pattern, timeZone, null, null); 119 } 120 121 125 public static FastDateFormat getInstance 126 (String pattern, Locale locale) throws IllegalArgumentException  127 { 128 return getInstance(pattern, null, locale, null); 129 } 130 131 136 public static FastDateFormat getInstance 137 (String pattern, DateFormatSymbols symbols) 138 throws IllegalArgumentException  139 { 140 return getInstance(pattern, null, null, symbols); 141 } 142 143 149 public static FastDateFormat getInstance 150 (String pattern, TimeZone timeZone, Locale locale) 151 throws IllegalArgumentException  152 { 153 return getInstance(pattern, timeZone, locale, null); 154 } 155 156 164 public static synchronized FastDateFormat getInstance 165 (String pattern, TimeZone timeZone, Locale locale, 166 DateFormatSymbols symbols) 167 throws IllegalArgumentException  168 { 169 Object key = pattern; 170 171 if (timeZone != null) { 172 key = new Pair(key, timeZone); 173 } 174 if (locale != null) { 175 key = new Pair(key, locale); 176 } 177 if (symbols != null) { 178 key = new Pair(key, symbols); 179 } 180 181 FastDateFormat format = (FastDateFormat)cInstanceCache.get(key); 182 if (format == null) { 183 if (locale == null) { 184 locale = Locale.getDefault(); 185 } 186 if (symbols == null) { 187 symbols = new DateFormatSymbols (locale); 188 } 189 format = new FastDateFormat(pattern, timeZone, locale, symbols); 190 cInstanceCache.put(key, format); 191 } 192 return format; 193 } 194 195 201 public static synchronized FastDateFormat getDateInstance 202 (Object style, TimeZone timeZone, Locale locale) 203 throws IllegalArgumentException  204 { 205 Object key = style; 206 207 if (timeZone != null) { 208 key = new Pair(key, timeZone); 209 } 210 if (locale == null) { 211 key = new Pair(key, locale); 212 } 213 214 FastDateFormat format = (FastDateFormat)cDateInstanceCache.get(key); 215 216 if (format == null) { 217 int ds; 218 try { 219 ds = ((Integer )style).intValue(); 220 } 221 catch (ClassCastException e) { 222 throw new IllegalArgumentException  223 ("Illegal date style: " + style); 224 } 225 226 if (locale == null) { 227 locale = Locale.getDefault(); 228 } 229 230 try { 231 String pattern = ((SimpleDateFormat )DateFormat.getDateInstance(ds, locale)).toPattern(); 232 format = getInstance(pattern, timeZone, locale); 233 cDateInstanceCache.put(key, format); 234 } 235 catch (ClassCastException e) { 236 throw new IllegalArgumentException  237 ("No date pattern for locale: " + locale); 238 } 239 } 240 241 return format; 242 } 243 244 250 public static synchronized FastDateFormat getTimeInstance 251 (Object style, TimeZone timeZone, Locale locale) 252 throws IllegalArgumentException  253 { 254 Object key = style; 255 256 if (timeZone != null) { 257 key = new Pair(key, timeZone); 258 } 259 if (locale != null) { 260 key = new Pair(key, locale); 261 } 262 263 FastDateFormat format = (FastDateFormat)cTimeInstanceCache.get(key); 264 265 if (format == null) { 266 int ts; 267 try { 268 ts = ((Integer )style).intValue(); 269 } 270 catch (ClassCastException e) { 271 throw new IllegalArgumentException  272 ("Illegal time style: " + style); 273 } 274 275 if (locale == null) { 276 locale = Locale.getDefault(); 277 } 278 279 try { 280 String pattern = ((SimpleDateFormat )DateFormat.getTimeInstance(ts, locale)).toPattern(); 281 format = getInstance(pattern, timeZone, locale); 282 cTimeInstanceCache.put(key, format); 283 } 284 catch (ClassCastException e) { 285 throw new IllegalArgumentException  286 ("No date pattern for locale: " + locale); 287 } 288 } 289 290 return format; 291 } 292 293 300 public static synchronized FastDateFormat getDateTimeInstance 301 (Object dateStyle, Object timeStyle, TimeZone timeZone, Locale locale) 302 throws IllegalArgumentException  303 { 304 Object key = new Pair(dateStyle, timeStyle); 305 306 if (timeZone != null) { 307 key = new Pair(key, timeZone); 308 } 309 if (locale != null) { 310 key = new Pair(key, locale); 311 } 312 313 FastDateFormat format = 314 (FastDateFormat)cDateTimeInstanceCache.get(key); 315 316 if (format == null) { 317 int ds; 318 try { 319 ds = ((Integer )dateStyle).intValue(); 320 } 321 catch (ClassCastException e) { 322 throw new IllegalArgumentException  323 ("Illegal date style: " + dateStyle); 324 } 325 326 int ts; 327 try { 328 ts = ((Integer )timeStyle).intValue(); 329 } 330 catch (ClassCastException e) { 331 throw new IllegalArgumentException  332 ("Illegal time style: " + timeStyle); 333 } 334 335 if (locale == null) { 336 locale = Locale.getDefault(); 337 } 338 339 try { 340 String pattern = ((SimpleDateFormat )DateFormat.getDateTimeInstance(ds, ts, locale)).toPattern(); 341 format = getInstance(pattern, timeZone, locale); 342 cDateTimeInstanceCache.put(key, format); 343 } 344 catch (ClassCastException e) { 345 throw new IllegalArgumentException  346 ("No date time pattern for locale: " + locale); 347 } 348 } 349 350 return format; 351 } 352 353 static synchronized String getTimeZoneDisplay(TimeZone tz, 354 boolean daylight, 355 int style, 356 Locale locale) { 357 Object key = new TimeZoneDisplayKey(tz, daylight, style, locale); 358 String value = (String )cTimeZoneDisplayCache.get(key); 359 if (value == null) { 360 value = tz.getDisplayName(daylight, style, locale); 362 cTimeZoneDisplayCache.put(key, value); 363 } 364 return value; 365 } 366 367 private static synchronized String getDefaultPattern() { 368 if (cDefaultPattern == null) { 369 cDefaultPattern = new SimpleDateFormat ().toPattern(); 370 } 371 return cDefaultPattern; 372 } 373 374 377 private static List parse(String pattern, TimeZone timeZone, Locale locale, 378 DateFormatSymbols symbols) { 379 List rules = new ArrayList (); 380 381 String [] ERAs = symbols.getEras(); 382 String [] months = symbols.getMonths(); 383 String [] shortMonths = symbols.getShortMonths(); 384 String [] weekdays = symbols.getWeekdays(); 385 String [] shortWeekdays = symbols.getShortWeekdays(); 386 String [] AmPmStrings = symbols.getAmPmStrings(); 387 388 int length = pattern.length(); 389 int[] indexRef = new int[1]; 390 391 for (int i=0; i<length; i++) { 392 indexRef[0] = i; 393 String token = parseToken(pattern, indexRef); 394 i = indexRef[0]; 395 396 int tokenLen = token.length(); 397 if (tokenLen == 0) { 398 break; 399 } 400 401 Rule rule; 402 char c = token.charAt(0); 403 404 switch (c) { 405 case 'G': rule = new TextField(Calendar.ERA, ERAs); 407 break; 408 case 'y': if (tokenLen >= 4) { 410 rule = new UnpaddedNumberField(Calendar.YEAR); 411 } 412 else { 413 rule = new TwoDigitYearField(); 414 } 415 break; 416 case 'M': if (tokenLen >= 4) { 418 rule = new TextField(Calendar.MONTH, months); 419 } 420 else if (tokenLen == 3) { 421 rule = new TextField(Calendar.MONTH, shortMonths); 422 } 423 else if (tokenLen == 2) { 424 rule = new TwoDigitMonthField(); 425 } 426 else { 427 rule = new UnpaddedMonthField(); 428 } 429 break; 430 case 'd': rule = selectNumberRule(Calendar.DAY_OF_MONTH, tokenLen); 432 break; 433 case 'h': rule = new TwelveHourField 435 (selectNumberRule(Calendar.HOUR, tokenLen)); 436 break; 437 case 'H': rule = selectNumberRule(Calendar.HOUR_OF_DAY, tokenLen); 439 break; 440 case 'm': rule = selectNumberRule(Calendar.MINUTE, tokenLen); 442 break; 443 case 's': rule = selectNumberRule(Calendar.SECOND, tokenLen); 445 break; 446 case 'S': rule = selectNumberRule(Calendar.MILLISECOND, tokenLen); 448 break; 449 case 'E': rule = new TextField 451 (Calendar.DAY_OF_WEEK, 452 tokenLen < 4 ? shortWeekdays : weekdays); 453 break; 454 case 'D': rule = selectNumberRule(Calendar.DAY_OF_YEAR, tokenLen); 456 break; 457 case 'F': rule = selectNumberRule 459 (Calendar.DAY_OF_WEEK_IN_MONTH, tokenLen); 460 break; 461 case 'w': rule = selectNumberRule(Calendar.WEEK_OF_YEAR, tokenLen); 463 break; 464 case 'W': rule = selectNumberRule(Calendar.WEEK_OF_MONTH, tokenLen); 466 break; 467 case 'a': rule = new TextField(Calendar.AM_PM, AmPmStrings); 469 break; 470 case 'k': rule = new TwentyFourHourField 472 (selectNumberRule(Calendar.HOUR_OF_DAY, tokenLen)); 473 break; 474 case 'K': rule = selectNumberRule(Calendar.HOUR, tokenLen); 476 break; 477 case 'z': if (tokenLen >= 4) { 479 rule = new TimeZoneRule(timeZone, locale, TimeZone.LONG); 480 } 481 else { 482 rule = new TimeZoneRule(timeZone, locale, TimeZone.SHORT); 483 } 484 break; 485 case '\'': String sub = token.substring(1); 487 if (sub.length() == 1) { 488 rule = new CharacterLiteral(sub.charAt(0)); 489 } 490 else { 491 rule = new StringLiteral(new String (sub)); 492 } 493 break; 494 default: 495 throw new IllegalArgumentException  496 ("Illegal pattern component: " + token); 497 } 498 499 rules.add(rule); 500 } 501 502 return rules; 503 } 504 505 private static String parseToken(String pattern, int[] indexRef) { 506 StringBuffer buf = new StringBuffer (); 507 508 int i = indexRef[0]; 509 int length = pattern.length(); 510 511 char c = pattern.charAt(i); 512 if (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z') { 513 buf.append(c); 516 517 while (i + 1 < length) { 518 char peek = pattern.charAt(i + 1); 519 if (peek == c) { 520 buf.append(c); 521 i++; 522 } 523 else { 524 break; 525 } 526 } 527 } 528 else { 529 buf.append('\''); 531 532 boolean inLiteral = false; 533 534 for (; i < length; i++) { 535 c = pattern.charAt(i); 536 537 if (c == '\'') { 538 if (i + 1 < length && pattern.charAt(i + 1) == '\'') { 539 i++; 541 buf.append(c); 542 } 543 else { 544 inLiteral = !inLiteral; 545 } 546 } 547 else if (!inLiteral && 548 (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z')) { 549 i--; 550 break; 551 } 552 else { 553 buf.append(c); 554 } 555 } 556 } 557 558 indexRef[0] = i; 559 return buf.toString(); 560 } 561 562 private static NumberRule selectNumberRule(int field, int padding) { 563 switch (padding) { 564 case 1: 565 return new UnpaddedNumberField(field); 566 case 2: 567 return new TwoDigitNumberField(field); 568 default: 569 return new PaddedNumberField(field, padding); 570 } 571 } 572 573 private final String mPattern; 574 private final TimeZone mTimeZone; 575 private final Locale mLocale; 576 private final Rule[] mRules; 577 private final int mMaxLengthEstimate; 578 579 private FastDateFormat() { 580 this(getDefaultPattern(), null, null, null); 581 } 582 583 586 private FastDateFormat(String pattern) throws IllegalArgumentException { 587 this(pattern, null, null, null); 588 } 589 590 595 private FastDateFormat(String pattern, TimeZone timeZone) 596 throws IllegalArgumentException  597 { 598 this(pattern, timeZone, null, null); 599 } 600 601 605 private FastDateFormat(String pattern, Locale locale) 606 throws IllegalArgumentException  607 { 608 this(pattern, null, locale, null); 609 } 610 611 616 private FastDateFormat(String pattern, DateFormatSymbols symbols) 617 throws IllegalArgumentException  618 { 619 this(pattern, null, null, symbols); 620 } 621 622 628 private FastDateFormat(String pattern, TimeZone timeZone, Locale locale) 629 throws IllegalArgumentException 630 { 631 this(pattern, timeZone, locale, null); 632 } 633 634 642 private FastDateFormat(String pattern, TimeZone timeZone, Locale locale, 643 DateFormatSymbols symbols) 644 throws IllegalArgumentException  645 { 646 if (locale == null) { 647 locale = Locale.getDefault(); 648 } 649 650 mPattern = pattern; 651 mTimeZone = timeZone; 652 mLocale = locale; 653 654 if (symbols == null) { 655 symbols = new DateFormatSymbols (locale); 656 } 657 658 List rulesList = parse(pattern, timeZone, locale, symbols); 659 mRules = (Rule[])rulesList.toArray(new Rule[rulesList.size()]); 660 661 int len = 0; 662 for (int i=mRules.length; --i >= 0; ) { 663 len += mRules[i].estimateLength(); 664 } 665 666 mMaxLengthEstimate = len; 667 } 668 669 public String format(Date date) { 670 Calendar c = new GregorianCalendar (cDefaultTimeZone); 671 c.setTime(date); 672 if (mTimeZone != null) { 673 c.setTimeZone(mTimeZone); 674 } 675 return applyRules(c, new StringBuffer (mMaxLengthEstimate)).toString(); 676 } 677 678 public String format(Calendar calendar) { 679 return format(calendar, new StringBuffer (mMaxLengthEstimate)) 680 .toString(); 681 } 682 683 public StringBuffer format(Date date, StringBuffer buf) { 684 Calendar c = new GregorianCalendar (cDefaultTimeZone); 685 c.setTime(date); 686 if (mTimeZone != null) { 687 c.setTimeZone(mTimeZone); 688 } 689 return applyRules(c, buf); 690 } 691 692 public StringBuffer format(Calendar calendar, StringBuffer buf) { 693 if (mTimeZone != null) { 694 calendar = (Calendar )calendar.clone(); 695 calendar.setTimeZone(mTimeZone); 696 } 697 return applyRules(calendar, buf); 698 } 699 700 private StringBuffer applyRules(Calendar calendar, StringBuffer buf) { 701 Rule[] rules = mRules; 702 int len = mRules.length; 703 for (int i=0; i<len; i++) { 704 rules[i].appendTo(buf, calendar); 705 } 706 return buf; 707 } 708 709 public String getPattern() { 710 return mPattern; 711 } 712 713 717 public TimeZone getTimeZone() { 718 return mTimeZone; 719 } 720 721 public Locale getLocale() { 722 return mLocale; 723 } 724 725 730 public int getMaxLengthEstimate() { 731 return mMaxLengthEstimate; 732 } 733 734 private interface Rule { 735 int estimateLength(); 736 737 void appendTo(StringBuffer buffer, Calendar calendar); 738 } 739 740 private interface NumberRule extends Rule { 741 void appendTo(StringBuffer buffer, int value); 742 } 743 744 private static class CharacterLiteral implements Rule { 745 private final char mValue; 746 747 CharacterLiteral(char value) { 748 mValue = value; 749 } 750 751 public int estimateLength() { 752 return 1; 753 } 754 755 public void appendTo(StringBuffer buffer, Calendar calendar) { 756 buffer.append(mValue); 757 } 758 } 759 760 private static class StringLiteral implements Rule { 761 private final String mValue; 762 763 StringLiteral(String value) { 764 mValue = value; 765 } 766 767 public int estimateLength() { 768 return mValue.length(); 769 } 770 771 public void appendTo(StringBuffer buffer, Calendar calendar) { 772 buffer.append(mValue); 773 } 774 } 775 776 private static class TextField implements Rule { 777 private final int mField; 778 private final String [] mValues; 779 780 TextField(int field, String [] values) { 781 mField = field; 782 mValues = values; 783 } 784 785 public int estimateLength() { 786 int max = 0; 787 for (int i=mValues.length; --i >= 0; ) { 788 int len = mValues[i].length(); 789 if (len > max) { 790 max = len; 791 } 792 } 793 return max; 794 } 795 796 public void appendTo(StringBuffer buffer, Calendar calendar) { 797 buffer.append(mValues[calendar.get(mField)]); 798 } 799 } 800 801 private static class UnpaddedNumberField implements NumberRule { 802 private final int mField; 803 804 UnpaddedNumberField(int field) { 805 mField = field; 806 } 807 808 public int estimateLength() { 809 return 4; 810 } 811 812 public void appendTo(StringBuffer buffer, Calendar calendar) { 813 appendTo(buffer, calendar.get(mField)); 814 } 815 816 public final void appendTo(StringBuffer buffer, int value) { 817 if (value < 10) { 818 buffer.append((char)(value + '0')); 819 } 820 else if (value < 100) { 821 buffer.append((char)(value / 10 + '0')); 822 buffer.append((char)(value % 10 + '0')); 823 } 824 else { 825 buffer.append(Integer.toString(value)); 826 } 827 } 828 } 829 830 private static class UnpaddedMonthField implements NumberRule { 831 UnpaddedMonthField() { 832 } 833 834 public int estimateLength() { 835 return 2; 836 } 837 838 public void appendTo(StringBuffer buffer, Calendar calendar) { 839 appendTo(buffer, calendar.get(Calendar.MONTH) + 1); 840 } 841 842 public final void appendTo(StringBuffer buffer, int value) { 843 if (value < 10) { 844 buffer.append((char)(value + '0')); 845 } 846 else { 847 buffer.append((char)(value / 10 + '0')); 848 buffer.append((char)(value % 10 + '0')); 849 } 850 } 851 } 852 853 private static class PaddedNumberField implements NumberRule { 854 private final int mField; 855 private final int mSize; 856 857 PaddedNumberField(int field, int size) { 858 if (size < 3) { 859 throw new IllegalArgumentException (); 861 } 862 mField = field; 863 mSize = size; 864 } 865 866 public int estimateLength() { 867 return 4; 868 } 869 870 public void appendTo(StringBuffer buffer, Calendar calendar) { 871 appendTo(buffer, calendar.get(mField)); 872 } 873 874 public final void appendTo(StringBuffer buffer, int value) { 875 if (value < 100) { 876 for (int i = mSize; --i >= 2; ) { 877 buffer.append('0'); 878 } 879 buffer.append((char)(value / 10 + '0')); 880 buffer.append((char)(value % 10 + '0')); 881 } 882 else { 883 int digits; 884 if (value < 1000) { 885 digits = 3; 886 } 887 else { 888 digits = (int)(Math.log(value) / LOG_10) + 1; 889 } 890 for (int i = mSize; --i >= digits; ) { 891 buffer.append('0'); 892 } 893 buffer.append(Integer.toString(value)); 894 } 895 } 896 } 897 898 private static class TwoDigitNumberField implements NumberRule { 899 private final int mField; 900 901 TwoDigitNumberField(int field) { 902 mField = field; 903 } 904 905 public int estimateLength() { 906 return 2; 907 } 908 909 public void appendTo(StringBuffer buffer, Calendar calendar) { 910 appendTo(buffer, calendar.get(mField)); 911 } 912 913 public final void appendTo(StringBuffer buffer, int value) { 914 if (value < 100) { 915 buffer.append((char)(value / 10 + '0')); 916 buffer.append((char)(value % 10 + '0')); 917 } 918 else { 919 buffer.append(Integer.toString(value)); 920 } 921 } 922 } 923 924 private static class TwoDigitYearField implements NumberRule { 925 TwoDigitYearField() { 926 } 927 928 public int estimateLength() { 929 return 2; 930 } 931 932 public void appendTo(StringBuffer buffer, Calendar calendar) { 933 appendTo(buffer, calendar.get(Calendar.YEAR) % 100); 934 } 935 936 public final void appendTo(StringBuffer buffer, int value) { 937 buffer.append((char)(value / 10 + '0')); 938 buffer.append((char)(value % 10 + '0')); 939 } 940 } 941 942 private static class TwoDigitMonthField implements NumberRule { 943 TwoDigitMonthField() { 944 } 945 946 public int estimateLength() { 947 return 2; 948 } 949 950 public void appendTo(StringBuffer buffer, Calendar calendar) { 951 appendTo(buffer, calendar.get(Calendar.MONTH) + 1); 952 } 953 954 public final void appendTo(StringBuffer buffer, int value) { 955 buffer.append((char)(value / 10 + '0')); 956 buffer.append((char)(value % 10 + '0')); 957 } 958 } 959 960 private static class TwelveHourField implements NumberRule { 961 private final NumberRule mRule; 962 963 TwelveHourField(NumberRule rule) { 964 mRule = rule; 965 } 966 967 public int estimateLength() { 968 return mRule.estimateLength(); 969 } 970 971 public void appendTo(StringBuffer buffer, Calendar calendar) { 972 int value = calendar.get(Calendar.HOUR); 973 if (value == 0) { 974 value = calendar.getLeastMaximum(Calendar.HOUR) + 1; 975 } 976 mRule.appendTo(buffer, value); 977 } 978 979 public void appendTo(StringBuffer buffer, int value) { 980 mRule.appendTo(buffer, value); 981 } 982 } 983 984 private static class TwentyFourHourField implements NumberRule { 985 private final NumberRule mRule; 986 987 TwentyFourHourField(NumberRule rule) { 988 mRule = rule; 989 } 990 991 public int estimateLength() { 992 return mRule.estimateLength(); 993 } 994 995 public void appendTo(StringBuffer buffer, Calendar calendar) { 996 int value = calendar.get(Calendar.HOUR_OF_DAY); 997 if (value == 0) { 998 value = calendar.getMaximum(Calendar.HOUR_OF_DAY) + 1; 999 } 1000 mRule.appendTo(buffer, value); 1001 } 1002 1003 public void appendTo(StringBuffer buffer, int value) { 1004 mRule.appendTo(buffer, value); 1005 } 1006 } 1007 1008 private static class TimeZoneRule implements Rule { 1009 private final TimeZone mTimeZone; 1010 private final Locale mLocale; 1011 private final int mStyle; 1012 private final String mStandard; 1013 private final String mDaylight; 1014 1015 TimeZoneRule(TimeZone timeZone, Locale locale, int style) { 1016 mTimeZone = timeZone; 1017 mLocale = locale; 1018 mStyle = style; 1019 1020 if (timeZone != null) { 1021 mStandard = getTimeZoneDisplay(timeZone, false, style, locale); 1022 mDaylight = getTimeZoneDisplay(timeZone, true, style, locale); 1023 } 1024 else { 1025 mStandard = null; 1026 mDaylight = null; 1027 } 1028 } 1029 1030 public int estimateLength() { 1031 if (mTimeZone != null) { 1032 return Math.max(mStandard.length(), mDaylight.length()); 1033 } 1034 else if (mStyle == TimeZone.SHORT) { 1035 return 4; 1036 } 1037 else { 1038 return 40; 1039 } 1040 } 1041 1042 public void appendTo(StringBuffer buffer, Calendar calendar) { 1043 TimeZone timeZone; 1044 if ((timeZone = mTimeZone) != null) { 1045 if (timeZone.useDaylightTime() && 1046 calendar.get(Calendar.DST_OFFSET) != 0) { 1047 1048 buffer.append(mDaylight); 1049 } 1050 else { 1051 buffer.append(mStandard); 1052 } 1053 } 1054 else { 1055 timeZone = calendar.getTimeZone(); 1056 if (timeZone.useDaylightTime() && 1057 calendar.get(Calendar.DST_OFFSET) != 0) { 1058 1059 buffer.append(getTimeZoneDisplay 1060 (timeZone, true, mStyle, mLocale)); 1061 } 1062 else { 1063 buffer.append(getTimeZoneDisplay 1064 (timeZone, false, mStyle, mLocale)); 1065 } 1066 } 1067 } 1068 } 1069 1070 private static class TimeZoneDisplayKey { 1071 private final TimeZone mTimeZone; 1072 private final int mStyle; 1073 private final Locale mLocale; 1074 1075 TimeZoneDisplayKey(TimeZone timeZone, 1076 boolean daylight, int style, Locale locale) { 1077 mTimeZone = timeZone; 1078 if (daylight) { 1079 style |= 0x80000000; 1080 } 1081 mStyle = style; 1082 mLocale = locale; 1083 } 1084 1085 public int hashCode() { 1086 return mStyle * 31 + mLocale.hashCode(); 1087 } 1088 1089 public boolean equals(Object obj) { 1090 if (this == obj) { 1091 return true; 1092 } 1093 if (obj instanceof TimeZoneDisplayKey) { 1094 TimeZoneDisplayKey other = (TimeZoneDisplayKey)obj; 1095 return 1096 mTimeZone.equals(other.mTimeZone) && 1097 mStyle == other.mStyle && 1098 mLocale.equals(other.mLocale); 1099 } 1100 return false; 1101 } 1102 } 1103} 1104 | Popular Tags |