51 import java.security.ProtectionDomain; |
51 import java.security.ProtectionDomain; |
52 import java.text.DateFormat; |
52 import java.text.DateFormat; |
53 import java.text.DateFormatSymbols; |
53 import java.text.DateFormatSymbols; |
54 import java.util.concurrent.ConcurrentHashMap; |
54 import java.util.concurrent.ConcurrentHashMap; |
55 import java.util.concurrent.ConcurrentMap; |
55 import java.util.concurrent.ConcurrentMap; |
|
56 import java.util.spi.CalendarDataProvider; |
56 import sun.util.BuddhistCalendar; |
57 import sun.util.BuddhistCalendar; |
|
58 import sun.util.locale.provider.LocaleProviderAdapter; |
57 import sun.util.calendar.ZoneInfo; |
59 import sun.util.calendar.ZoneInfo; |
58 import sun.util.resources.LocaleData; |
60 import sun.util.locale.provider.CalendarDataUtility; |
59 |
61 |
60 /** |
62 /** |
61 * The <code>Calendar</code> class is an abstract class that provides methods |
63 * The <code>Calendar</code> class is an abstract class that provides methods |
62 * for converting between a specific instant in time and a set of {@link |
64 * for converting between a specific instant in time and a set of {@link |
63 * #fields calendar fields} such as <code>YEAR</code>, <code>MONTH</code>, |
65 * #fields calendar fields} such as <code>YEAR</code>, <code>MONTH</code>, |
705 /** |
707 /** |
706 * A style specifier for {@link #getDisplayNames(int, int, Locale) |
708 * A style specifier for {@link #getDisplayNames(int, int, Locale) |
707 * getDisplayNames} indicating names in all styles, such as |
709 * getDisplayNames} indicating names in all styles, such as |
708 * "January" and "Jan". |
710 * "January" and "Jan". |
709 * |
711 * |
|
712 * @see #SHORT_FORMAT |
|
713 * @see #LONG_FORMAT |
|
714 * @see #SHORT_STANDALONE |
|
715 * @see #LONG_STANDALONE |
710 * @see #SHORT |
716 * @see #SHORT |
711 * @see #LONG |
717 * @see #LONG |
712 * @since 1.6 |
718 * @since 1.6 |
713 */ |
719 */ |
714 public static final int ALL_STYLES = 0; |
720 public static final int ALL_STYLES = 0; |
715 |
721 |
|
722 static final int STANDALONE_MASK = 0x8000; |
|
723 |
716 /** |
724 /** |
717 * A style specifier for {@link #getDisplayName(int, int, Locale) |
725 * A style specifier for {@link #getDisplayName(int, int, Locale) |
718 * getDisplayName} and {@link #getDisplayNames(int, int, Locale) |
726 * getDisplayName} and {@link #getDisplayNames(int, int, Locale) |
719 * getDisplayNames} indicating a short name, such as "Jan". |
727 * getDisplayNames} equivalent to {@link #SHORT_FORMAT}. |
720 * |
728 * |
|
729 * @see #SHORT_STANDALONE |
721 * @see #LONG |
730 * @see #LONG |
722 * @since 1.6 |
731 * @since 1.6 |
723 */ |
732 */ |
724 public static final int SHORT = 1; |
733 public static final int SHORT = 1; |
725 |
734 |
726 /** |
735 /** |
727 * A style specifier for {@link #getDisplayName(int, int, Locale) |
736 * A style specifier for {@link #getDisplayName(int, int, Locale) |
728 * getDisplayName} and {@link #getDisplayNames(int, int, Locale) |
737 * getDisplayName} and {@link #getDisplayNames(int, int, Locale) |
729 * getDisplayNames} indicating a long name, such as "January". |
738 * getDisplayNames} equivalent to {@link #LONG_FORMAT}. |
730 * |
739 * |
|
740 * @see #LONG_STANDALONE |
731 * @see #SHORT |
741 * @see #SHORT |
732 * @since 1.6 |
742 * @since 1.6 |
733 */ |
743 */ |
734 public static final int LONG = 2; |
744 public static final int LONG = 2; |
|
745 |
|
746 /** |
|
747 * A style specifier for {@link #getDisplayName(int, int, Locale) |
|
748 * getDisplayName} and {@link #getDisplayNames(int, int, Locale) |
|
749 * getDisplayNames} indicating a short name used for format. |
|
750 * |
|
751 * @see #SHORT_STANDALONE |
|
752 * @see #LONG_FORMAT |
|
753 * @see #LONG_STANDALONE |
|
754 * @since 1.8 |
|
755 */ |
|
756 public static final int SHORT_FORMAT = 1; |
|
757 |
|
758 /** |
|
759 * A style specifier for {@link #getDisplayName(int, int, Locale) |
|
760 * getDisplayName} and {@link #getDisplayNames(int, int, Locale) |
|
761 * getDisplayNames} indicating a long name used for format. |
|
762 * |
|
763 * @see #LONG_STANDALONE |
|
764 * @see #SHORT_FORMAT |
|
765 * @see #SHORT_STANDALONE |
|
766 * @since 1.8 |
|
767 */ |
|
768 public static final int LONG_FORMAT = 2; |
|
769 |
|
770 /** |
|
771 * A style specifier for {@link #getDisplayName(int, int, Locale) |
|
772 * getDisplayName} and {@link #getDisplayNames(int, int, Locale) |
|
773 * getDisplayNames} indicating a short name used independently, |
|
774 * such as a month abbreviation as calendar headers. |
|
775 * |
|
776 * @see #SHORT_FORMAT |
|
777 * @see #LONG_FORMAT |
|
778 * @see #LONG_STANDALONE |
|
779 * @since 1.8 |
|
780 */ |
|
781 public static final int SHORT_STANDALONE = SHORT | STANDALONE_MASK; |
|
782 |
|
783 /** |
|
784 * A style specifier for {@link #getDisplayName(int, int, Locale) |
|
785 * getDisplayName} and {@link #getDisplayNames(int, int, Locale) |
|
786 * getDisplayNames} indicating a long name used independently, |
|
787 * such as a month name as calendar headers. |
|
788 * |
|
789 * @see #LONG_FORMAT |
|
790 * @see #SHORT_FORMAT |
|
791 * @see #SHORT_STANDALONE |
|
792 * @since 1.8 |
|
793 */ |
|
794 public static final int LONG_STANDALONE = LONG | STANDALONE_MASK; |
735 |
795 |
736 // Internal notes: |
796 // Internal notes: |
737 // Calendar contains two kinds of time representations: current "time" in |
797 // Calendar contains two kinds of time representations: current "time" in |
738 // milliseconds, and a set of calendar "fields" representing the current time. |
798 // milliseconds, and a set of calendar "fields" representing the current time. |
739 // The two representations are usually in sync, but can get out of sync |
799 // The two representations are usually in sync, but can get out of sync |
748 * The calendar field values for the currently set time for this calendar. |
808 * The calendar field values for the currently set time for this calendar. |
749 * This is an array of <code>FIELD_COUNT</code> integers, with index values |
809 * This is an array of <code>FIELD_COUNT</code> integers, with index values |
750 * <code>ERA</code> through <code>DST_OFFSET</code>. |
810 * <code>ERA</code> through <code>DST_OFFSET</code>. |
751 * @serial |
811 * @serial |
752 */ |
812 */ |
|
813 @SuppressWarnings("ProtectedField") |
753 protected int fields[]; |
814 protected int fields[]; |
754 |
815 |
755 /** |
816 /** |
756 * The flags which tell if a specified calendar field for the calendar is set. |
817 * The flags which tell if a specified calendar field for the calendar is set. |
757 * A new object has no fields set. After the first call to a method |
818 * A new object has no fields set. After the first call to a method |
758 * which generates the fields, they all remain set after that. |
819 * which generates the fields, they all remain set after that. |
759 * This is an array of <code>FIELD_COUNT</code> booleans, with index values |
820 * This is an array of <code>FIELD_COUNT</code> booleans, with index values |
760 * <code>ERA</code> through <code>DST_OFFSET</code>. |
821 * <code>ERA</code> through <code>DST_OFFSET</code>. |
761 * @serial |
822 * @serial |
762 */ |
823 */ |
|
824 @SuppressWarnings("ProtectedField") |
763 protected boolean isSet[]; |
825 protected boolean isSet[]; |
764 |
826 |
765 /** |
827 /** |
766 * Pseudo-time-stamps which specify when each field was set. There |
828 * Pseudo-time-stamps which specify when each field was set. There |
767 * are two special values, UNSET and COMPUTED. Values from |
829 * are two special values, UNSET and COMPUTED. Values from |
773 * The currently set time for this calendar, expressed in milliseconds after |
835 * The currently set time for this calendar, expressed in milliseconds after |
774 * January 1, 1970, 0:00:00 GMT. |
836 * January 1, 1970, 0:00:00 GMT. |
775 * @see #isTimeSet |
837 * @see #isTimeSet |
776 * @serial |
838 * @serial |
777 */ |
839 */ |
|
840 @SuppressWarnings("ProtectedField") |
778 protected long time; |
841 protected long time; |
779 |
842 |
780 /** |
843 /** |
781 * True if then the value of <code>time</code> is valid. |
844 * True if then the value of <code>time</code> is valid. |
782 * The time is made invalid by a change to an item of <code>field[]</code>. |
845 * The time is made invalid by a change to an item of <code>field[]</code>. |
783 * @see #time |
846 * @see #time |
784 * @serial |
847 * @serial |
785 */ |
848 */ |
|
849 @SuppressWarnings("ProtectedField") |
786 protected boolean isTimeSet; |
850 protected boolean isTimeSet; |
787 |
851 |
788 /** |
852 /** |
789 * True if <code>fields[]</code> are in sync with the currently set time. |
853 * True if <code>fields[]</code> are in sync with the currently set time. |
790 * If false, then the next attempt to get the value of a field will |
854 * If false, then the next attempt to get the value of a field will |
791 * force a recomputation of all fields from the current value of |
855 * force a recomputation of all fields from the current value of |
792 * <code>time</code>. |
856 * <code>time</code>. |
793 * @serial |
857 * @serial |
794 */ |
858 */ |
|
859 @SuppressWarnings("ProtectedField") |
795 protected boolean areFieldsSet; |
860 protected boolean areFieldsSet; |
796 |
861 |
797 /** |
862 /** |
798 * True if all fields have been set. |
863 * True if all fields have been set. |
799 * @serial |
864 * @serial |
908 |
973 |
909 // Proclaim serialization compatibility with JDK 1.1 |
974 // Proclaim serialization compatibility with JDK 1.1 |
910 static final long serialVersionUID = -1807547505821590642L; |
975 static final long serialVersionUID = -1807547505821590642L; |
911 |
976 |
912 // Mask values for calendar fields |
977 // Mask values for calendar fields |
|
978 @SuppressWarnings("PointlessBitwiseExpression") |
913 final static int ERA_MASK = (1 << ERA); |
979 final static int ERA_MASK = (1 << ERA); |
914 final static int YEAR_MASK = (1 << YEAR); |
980 final static int YEAR_MASK = (1 << YEAR); |
915 final static int MONTH_MASK = (1 << MONTH); |
981 final static int MONTH_MASK = (1 << MONTH); |
916 final static int WEEK_OF_YEAR_MASK = (1 << WEEK_OF_YEAR); |
982 final static int WEEK_OF_YEAR_MASK = (1 << WEEK_OF_YEAR); |
917 final static int WEEK_OF_MONTH_MASK = (1 << WEEK_OF_MONTH); |
983 final static int WEEK_OF_MONTH_MASK = (1 << WEEK_OF_MONTH); |
1016 private static Calendar createCalendar(TimeZone zone, |
1082 private static Calendar createCalendar(TimeZone zone, |
1017 Locale aLocale) |
1083 Locale aLocale) |
1018 { |
1084 { |
1019 Calendar cal = null; |
1085 Calendar cal = null; |
1020 |
1086 |
|
1087 if (aLocale.hasExtensions()) { |
1021 String caltype = aLocale.getUnicodeLocaleType("ca"); |
1088 String caltype = aLocale.getUnicodeLocaleType("ca"); |
1022 if (caltype == null) { |
1089 if (caltype != null) { |
1023 // Calendar type is not specified. |
1090 switch (caltype) { |
1024 // If the specified locale is a Thai locale, |
1091 case "buddhist": |
1025 // returns a BuddhistCalendar instance. |
|
1026 if ("th".equals(aLocale.getLanguage()) |
|
1027 && ("TH".equals(aLocale.getCountry()))) { |
|
1028 cal = new BuddhistCalendar(zone, aLocale); |
1092 cal = new BuddhistCalendar(zone, aLocale); |
|
1093 break; |
|
1094 case "japanese": |
|
1095 cal = new JapaneseImperialCalendar(zone, aLocale); |
|
1096 break; |
|
1097 case "gregory": |
|
1098 cal = new GregorianCalendar(zone, aLocale); |
|
1099 break; |
|
1100 } |
|
1101 } |
|
1102 } |
|
1103 if (cal == null) { |
|
1104 // If no known calendar type is explicitly specified, |
|
1105 // perform the traditional way to create a Calendar: |
|
1106 // create a BuddhistCalendar for th_TH locale, |
|
1107 // a JapaneseImperialCalendar for ja_JP_JP locale, or |
|
1108 // a GregorianCalendar for any other locales. |
|
1109 // NOTE: The language, country and variant strings are interned. |
|
1110 if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") { |
|
1111 cal = new BuddhistCalendar(zone, aLocale); |
|
1112 } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja" |
|
1113 && aLocale.getCountry() == "JP") { |
|
1114 cal = new JapaneseImperialCalendar(zone, aLocale); |
1029 } else { |
1115 } else { |
1030 cal = new GregorianCalendar(zone, aLocale); |
1116 cal = new GregorianCalendar(zone, aLocale); |
1031 } |
1117 } |
1032 } else if (caltype.equals("japanese")) { |
1118 } |
1033 cal = new JapaneseImperialCalendar(zone, aLocale); |
|
1034 } else if (caltype.equals("buddhist")) { |
|
1035 cal = new BuddhistCalendar(zone, aLocale); |
|
1036 } else { |
|
1037 // Unsupported calendar type. |
|
1038 // Use Gregorian calendar as a fallback. |
|
1039 cal = new GregorianCalendar(zone, aLocale); |
|
1040 } |
|
1041 |
|
1042 return cal; |
1119 return cal; |
1043 } |
1120 } |
1044 |
1121 |
1045 /** |
1122 /** |
1046 * Returns an array of all locales for which the <code>getInstance</code> |
1123 * Returns an array of all locales for which the <code>getInstance</code> |
1391 * |
1468 * |
1392 * @param field |
1469 * @param field |
1393 * the calendar field for which the string representation |
1470 * the calendar field for which the string representation |
1394 * is returned |
1471 * is returned |
1395 * @param style |
1472 * @param style |
1396 * the style applied to the string representation; one of |
1473 * the style applied to the string representation; one of {@link |
1397 * {@link #SHORT} or {@link #LONG}. |
1474 * #SHORT_FORMAT} ({@link #SHORT}), {@link #SHORT_STANDALONE}, |
|
1475 * {@link #LONG_FORMAT} ({@link #LONG}) or {@link #LONG_STANDALONE}. |
1398 * @param locale |
1476 * @param locale |
1399 * the locale for the string representation |
1477 * the locale for the string representation |
|
1478 * (any calendar types specified by {@code locale} are ignored) |
1400 * @return the string representation of the given |
1479 * @return the string representation of the given |
1401 * <code>field</code> in the given <code>style</code>, or |
1480 * <code>field</code> in the given <code>style</code>, or |
1402 * <code>null</code> if no string representation is |
1481 * <code>null</code> if no string representation is |
1403 * applicable. |
1482 * applicable. |
1404 * @exception IllegalArgumentException |
1483 * @exception IllegalArgumentException |
1408 * @exception NullPointerException |
1487 * @exception NullPointerException |
1409 * if <code>locale</code> is null |
1488 * if <code>locale</code> is null |
1410 * @since 1.6 |
1489 * @since 1.6 |
1411 */ |
1490 */ |
1412 public String getDisplayName(int field, int style, Locale locale) { |
1491 public String getDisplayName(int field, int style, Locale locale) { |
1413 if (!checkDisplayNameParams(field, style, ALL_STYLES, LONG, locale, |
1492 if (!checkDisplayNameParams(field, style, SHORT, LONG, locale, |
1414 ERA_MASK|MONTH_MASK|DAY_OF_WEEK_MASK|AM_PM_MASK)) { |
1493 ERA_MASK|MONTH_MASK|DAY_OF_WEEK_MASK|AM_PM_MASK)) { |
1415 return null; |
1494 return null; |
|
1495 } |
|
1496 |
|
1497 // the standalone styles are supported only through CalendarDataProviders. |
|
1498 if (isStandaloneStyle(style)) { |
|
1499 return CalendarDataUtility.retrieveFieldValueName(getCalendarType(), |
|
1500 field, get(field), |
|
1501 style, locale); |
1416 } |
1502 } |
1417 |
1503 |
1418 DateFormatSymbols symbols = DateFormatSymbols.getInstance(locale); |
1504 DateFormatSymbols symbols = DateFormatSymbols.getInstance(locale); |
1419 String[] strings = getFieldStrings(field, style, symbols); |
1505 String[] strings = getFieldStrings(field, style, symbols); |
1420 if (strings != null) { |
1506 if (strings != null) { |
1451 * and {@link DateFormatSymbols#getMonths()}. |
1537 * and {@link DateFormatSymbols#getMonths()}. |
1452 * |
1538 * |
1453 * @param field |
1539 * @param field |
1454 * the calendar field for which the display names are returned |
1540 * the calendar field for which the display names are returned |
1455 * @param style |
1541 * @param style |
1456 * the style applied to the display names; one of {@link |
1542 * the style applied to the string representation; one of {@link |
1457 * #SHORT}, {@link #LONG}, or {@link #ALL_STYLES}. |
1543 * #SHORT_FORMAT} ({@link #SHORT}), {@link #SHORT_STANDALONE}, |
|
1544 * {@link #LONG_FORMAT} ({@link #LONG}) or {@link #LONG_STANDALONE}. |
1458 * @param locale |
1545 * @param locale |
1459 * the locale for the display names |
1546 * the locale for the display names |
1460 * @return a <code>Map</code> containing all display names in |
1547 * @return a <code>Map</code> containing all display names in |
1461 * <code>style</code> and <code>locale</code> and their |
1548 * <code>style</code> and <code>locale</code> and their |
1462 * field values, or <code>null</code> if no display names |
1549 * field values, or <code>null</code> if no display names |
1472 public Map<String, Integer> getDisplayNames(int field, int style, Locale locale) { |
1559 public Map<String, Integer> getDisplayNames(int field, int style, Locale locale) { |
1473 if (!checkDisplayNameParams(field, style, ALL_STYLES, LONG, locale, |
1560 if (!checkDisplayNameParams(field, style, ALL_STYLES, LONG, locale, |
1474 ERA_MASK|MONTH_MASK|DAY_OF_WEEK_MASK|AM_PM_MASK)) { |
1561 ERA_MASK|MONTH_MASK|DAY_OF_WEEK_MASK|AM_PM_MASK)) { |
1475 return null; |
1562 return null; |
1476 } |
1563 } |
1477 |
1564 if (style == ALL_STYLES || isStandaloneStyle(style)) { |
1478 // ALL_STYLES |
1565 return CalendarDataUtility.retrieveFieldValueNames(getCalendarType(), field, style, locale); |
1479 if (style == ALL_STYLES) { |
1566 } |
1480 Map<String,Integer> shortNames = getDisplayNamesImpl(field, SHORT, locale); |
|
1481 if (field == ERA || field == AM_PM) { |
|
1482 return shortNames; |
|
1483 } |
|
1484 Map<String,Integer> longNames = getDisplayNamesImpl(field, LONG, locale); |
|
1485 if (shortNames == null) { |
|
1486 return longNames; |
|
1487 } |
|
1488 if (longNames != null) { |
|
1489 shortNames.putAll(longNames); |
|
1490 } |
|
1491 return shortNames; |
|
1492 } |
|
1493 |
|
1494 // SHORT or LONG |
1567 // SHORT or LONG |
1495 return getDisplayNamesImpl(field, style, locale); |
1568 return getDisplayNamesImpl(field, style, locale); |
1496 } |
1569 } |
1497 |
1570 |
1498 private Map<String,Integer> getDisplayNamesImpl(int field, int style, Locale locale) { |
1571 private Map<String,Integer> getDisplayNamesImpl(int field, int style, Locale locale) { |
1511 return null; |
1584 return null; |
1512 } |
1585 } |
1513 |
1586 |
1514 boolean checkDisplayNameParams(int field, int style, int minStyle, int maxStyle, |
1587 boolean checkDisplayNameParams(int field, int style, int minStyle, int maxStyle, |
1515 Locale locale, int fieldMask) { |
1588 Locale locale, int fieldMask) { |
|
1589 int baseStyle = getBaseStyle(style); // Ignore the standalone mask |
1516 if (field < 0 || field >= fields.length || |
1590 if (field < 0 || field >= fields.length || |
1517 style < minStyle || style > maxStyle) { |
1591 baseStyle < minStyle || baseStyle > maxStyle) { |
1518 throw new IllegalArgumentException(); |
1592 throw new IllegalArgumentException(); |
1519 } |
1593 } |
1520 if (locale == null) { |
1594 if (locale == null) { |
1521 throw new NullPointerException(); |
1595 throw new NullPointerException(); |
1522 } |
1596 } |
1523 return isFieldSet(fieldMask, field); |
1597 return isFieldSet(fieldMask, field); |
1524 } |
1598 } |
1525 |
1599 |
1526 private String[] getFieldStrings(int field, int style, DateFormatSymbols symbols) { |
1600 private String[] getFieldStrings(int field, int style, DateFormatSymbols symbols) { |
|
1601 int baseStyle = getBaseStyle(style); // ignore the standalone mask |
1527 String[] strings = null; |
1602 String[] strings = null; |
1528 switch (field) { |
1603 switch (field) { |
1529 case ERA: |
1604 case ERA: |
1530 strings = symbols.getEras(); |
1605 strings = symbols.getEras(); |
1531 break; |
1606 break; |
1532 |
1607 |
1533 case MONTH: |
1608 case MONTH: |
1534 strings = (style == LONG) ? symbols.getMonths() : symbols.getShortMonths(); |
1609 strings = (baseStyle == LONG) ? symbols.getMonths() : symbols.getShortMonths(); |
1535 break; |
1610 break; |
1536 |
1611 |
1537 case DAY_OF_WEEK: |
1612 case DAY_OF_WEEK: |
1538 strings = (style == LONG) ? symbols.getWeekdays() : symbols.getShortWeekdays(); |
1613 strings = (baseStyle == LONG) ? symbols.getWeekdays() : symbols.getShortWeekdays(); |
1539 break; |
1614 break; |
1540 |
1615 |
1541 case AM_PM: |
1616 case AM_PM: |
1542 strings = symbols.getAmPmStrings(); |
1617 strings = symbols.getAmPmStrings(); |
1543 break; |
1618 break; |
1863 } |
1939 } |
1864 |
1940 |
1865 return fieldMask; |
1941 return fieldMask; |
1866 } |
1942 } |
1867 |
1943 |
|
1944 int getBaseStyle(int style) { |
|
1945 return style & ~STANDALONE_MASK; |
|
1946 } |
|
1947 |
|
1948 boolean isStandaloneStyle(int style) { |
|
1949 return (style & STANDALONE_MASK) != 0; |
|
1950 } |
|
1951 |
1868 /** |
1952 /** |
1869 * Returns the pseudo-time-stamp for two fields, given their |
1953 * Returns the pseudo-time-stamp for two fields, given their |
1870 * individual pseudo-time-stamps. If either of the fields |
1954 * individual pseudo-time-stamps. If either of the fields |
1871 * is unset, then the aggregate is unset. Otherwise, the |
1955 * is unset, then the aggregate is unset. Otherwise, the |
1872 * aggregate is the later of the two stamps. |
1956 * aggregate is the later of the two stamps. |
1873 */ |
1957 */ |
1874 private static final int aggregateStamp(int stamp_a, int stamp_b) { |
1958 private static int aggregateStamp(int stamp_a, int stamp_b) { |
1875 if (stamp_a == UNSET || stamp_b == UNSET) { |
1959 if (stamp_a == UNSET || stamp_b == UNSET) { |
1876 return UNSET; |
1960 return UNSET; |
1877 } |
1961 } |
1878 return (stamp_a > stamp_b) ? stamp_a : stamp_b; |
1962 return (stamp_a > stamp_b) ? stamp_a : stamp_b; |
|
1963 } |
|
1964 |
|
1965 /** |
|
1966 * Returns the calendar type of this {@code Calendar}. Calendar types are |
|
1967 * defined by the <em>Unicode Locale Data Markup Language (LDML)</em> |
|
1968 * specification. |
|
1969 * |
|
1970 * <p>The default implementation of this method returns the class name of |
|
1971 * this {@code Calendar} instance. Any subclasses that implement |
|
1972 * LDML-defined calendar systems should override this method to return |
|
1973 * appropriate calendar types. |
|
1974 * |
|
1975 * @return the LDML-defined calendar type or the class name of this |
|
1976 * {@code Calendar} instance |
|
1977 * @since 1.8 |
|
1978 * @see <a href="Locale.html#def_extensions">Locale extensions</a> |
|
1979 * @see Locale.Builder#setLocale(Locale) |
|
1980 * @see Locale.Builder#setUnicodeLocaleKeyword(String, String) |
|
1981 */ |
|
1982 public String getCalendarType() { |
|
1983 return this.getClass().getName(); |
1879 } |
1984 } |
1880 |
1985 |
1881 /** |
1986 /** |
1882 * Compares this <code>Calendar</code> to the specified |
1987 * Compares this <code>Calendar</code> to the specified |
1883 * <code>Object</code>. The result is <code>true</code> if and only if |
1988 * <code>Object</code>. The result is <code>true</code> if and only if |
1898 * |
2003 * |
1899 * @param obj the object to compare with. |
2004 * @param obj the object to compare with. |
1900 * @return <code>true</code> if this object is equal to <code>obj</code>; |
2005 * @return <code>true</code> if this object is equal to <code>obj</code>; |
1901 * <code>false</code> otherwise. |
2006 * <code>false</code> otherwise. |
1902 */ |
2007 */ |
|
2008 @SuppressWarnings("EqualsWhichDoesntCheckParameterClass") |
|
2009 @Override |
1903 public boolean equals(Object obj) { |
2010 public boolean equals(Object obj) { |
1904 if (this == obj) |
2011 if (this == obj) { |
1905 return true; |
2012 return true; |
|
2013 } |
1906 try { |
2014 try { |
1907 Calendar that = (Calendar)obj; |
2015 Calendar that = (Calendar)obj; |
1908 return compareTo(getMillisOf(that)) == 0 && |
2016 return compareTo(getMillisOf(that)) == 0 && |
1909 lenient == that.lenient && |
2017 lenient == that.lenient && |
1910 firstDayOfWeek == that.firstDayOfWeek && |
2018 firstDayOfWeek == that.firstDayOfWeek && |
2466 Calendar work = (Calendar)this.clone(); |
2576 Calendar work = (Calendar)this.clone(); |
2467 work.setLenient(true); |
2577 work.setLenient(true); |
2468 |
2578 |
2469 // if we're counting weeks, set the day of the week to Sunday. We know the |
2579 // if we're counting weeks, set the day of the week to Sunday. We know the |
2470 // last week of a month or year will contain the first day of the week. |
2580 // last week of a month or year will contain the first day of the week. |
2471 if (field == WEEK_OF_YEAR || field == WEEK_OF_MONTH) |
2581 if (field == WEEK_OF_YEAR || field == WEEK_OF_MONTH) { |
2472 work.set(DAY_OF_WEEK, firstDayOfWeek); |
2582 work.set(DAY_OF_WEEK, firstDayOfWeek); |
|
2583 } |
2473 |
2584 |
2474 // now try each value from getLeastMaximum() to getMaximum() one by one until |
2585 // now try each value from getLeastMaximum() to getMaximum() one by one until |
2475 // we get a value that normalizes to another value. The last value that |
2586 // we get a value that normalizes to another value. The last value that |
2476 // normalizes to itself is the actual maximum for the current date |
2587 // normalizes to itself is the actual maximum for the current date |
2477 int result = fieldValue; |
2588 int result = fieldValue; |
2541 * format of the returned string may vary between implementations. |
2653 * format of the returned string may vary between implementations. |
2542 * The returned string may be empty but may not be <code>null</code>. |
2654 * The returned string may be empty but may not be <code>null</code>. |
2543 * |
2655 * |
2544 * @return a string representation of this calendar. |
2656 * @return a string representation of this calendar. |
2545 */ |
2657 */ |
|
2658 @Override |
2546 public String toString() { |
2659 public String toString() { |
2547 // NOTE: BuddhistCalendar.toString() interprets the string |
2660 // NOTE: BuddhistCalendar.toString() interprets the string |
2548 // produced by this method so that the Gregorian year number |
2661 // produced by this method so that the Gregorian year number |
2549 // is substituted by its B.E. year value. It relies on |
2662 // is substituted by its B.E. year value. It relies on |
2550 // "...,YEAR=<year>,..." or "...,YEAR=?,...". |
2663 // "...,YEAR=<year>,..." or "...,YEAR=?,...". |
2585 private void setWeekCountData(Locale desiredLocale) |
2698 private void setWeekCountData(Locale desiredLocale) |
2586 { |
2699 { |
2587 /* try to get the Locale data from the cache */ |
2700 /* try to get the Locale data from the cache */ |
2588 int[] data = cachedLocaleData.get(desiredLocale); |
2701 int[] data = cachedLocaleData.get(desiredLocale); |
2589 if (data == null) { /* cache miss */ |
2702 if (data == null) { /* cache miss */ |
2590 ResourceBundle bundle = LocaleData.getCalendarData(desiredLocale); |
2703 LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(CalendarDataProvider.class, desiredLocale); |
|
2704 CalendarDataProvider provider = adapter.getCalendarDataProvider(); |
2591 data = new int[2]; |
2705 data = new int[2]; |
2592 data[0] = Integer.parseInt(bundle.getString("firstDayOfWeek")); |
2706 data[0] = provider.getFirstDayOfWeek(desiredLocale); |
2593 data[1] = Integer.parseInt(bundle.getString("minimalDaysInFirstWeek")); |
2707 data[1] = provider.getMinimalDaysInFirstWeek(desiredLocale); |
|
2708 assert data[0] != 0 && data[1] != 0; |
2594 cachedLocaleData.putIfAbsent(desiredLocale, data); |
2709 cachedLocaleData.putIfAbsent(desiredLocale, data); |
2595 } |
2710 } |
2596 firstDayOfWeek = data[0]; |
2711 firstDayOfWeek = data[0]; |
2597 minimalDaysInFirstWeek = data[1]; |
2712 minimalDaysInFirstWeek = data[1]; |
2598 } |
2713 } |
2769 // fields[], isSet[], isTimeSet, and areFieldsSet may not be |
2886 // fields[], isSet[], isTimeSet, and areFieldsSet may not be |
2770 // streamed out anymore. We expect 'time' to be correct. |
2887 // streamed out anymore. We expect 'time' to be correct. |
2771 if (serialVersionOnStream >= 2) |
2888 if (serialVersionOnStream >= 2) |
2772 { |
2889 { |
2773 isTimeSet = true; |
2890 isTimeSet = true; |
2774 if (fields == null) fields = new int[FIELD_COUNT]; |
2891 if (fields == null) { |
2775 if (isSet == null) isSet = new boolean[FIELD_COUNT]; |
2892 fields = new int[FIELD_COUNT]; |
|
2893 } |
|
2894 if (isSet == null) { |
|
2895 isSet = new boolean[FIELD_COUNT]; |
|
2896 } |
2776 } |
2897 } |
2777 else if (serialVersionOnStream >= 0) |
2898 else if (serialVersionOnStream >= 0) |
2778 { |
2899 { |
2779 for (int i=0; i<FIELD_COUNT; ++i) |
2900 for (int i=0; i<FIELD_COUNT; ++i) { |
2780 stamp[i] = isSet[i] ? COMPUTED : UNSET; |
2901 stamp[i] = isSet[i] ? COMPUTED : UNSET; |
|
2902 } |
2781 } |
2903 } |
2782 |
2904 |
2783 serialVersionOnStream = currentSerialVersion; |
2905 serialVersionOnStream = currentSerialVersion; |
2784 |
2906 |
2785 // If there's a ZoneInfo object, use it for zone. |
2907 // If there's a ZoneInfo object, use it for zone. |
2786 ZoneInfo zi = null; |
2908 ZoneInfo zi = null; |
2787 try { |
2909 try { |
2788 zi = AccessController.doPrivileged( |
2910 zi = AccessController.doPrivileged( |
2789 new PrivilegedExceptionAction<ZoneInfo>() { |
2911 new PrivilegedExceptionAction<ZoneInfo>() { |
|
2912 @Override |
2790 public ZoneInfo run() throws Exception { |
2913 public ZoneInfo run() throws Exception { |
2791 return (ZoneInfo) input.readObject(); |
2914 return (ZoneInfo) input.readObject(); |
2792 } |
2915 } |
2793 }, |
2916 }, |
2794 CalendarAccessControlContext.INSTANCE); |
2917 CalendarAccessControlContext.INSTANCE); |