46 import java.util.Date; |
46 import java.util.Date; |
47 import java.util.GregorianCalendar; |
47 import java.util.GregorianCalendar; |
48 import java.util.Locale; |
48 import java.util.Locale; |
49 import java.util.Map; |
49 import java.util.Map; |
50 import java.util.SimpleTimeZone; |
50 import java.util.SimpleTimeZone; |
|
51 import java.util.SortedMap; |
51 import java.util.TimeZone; |
52 import java.util.TimeZone; |
52 import java.util.concurrent.ConcurrentHashMap; |
53 import java.util.concurrent.ConcurrentHashMap; |
53 import java.util.concurrent.ConcurrentMap; |
54 import java.util.concurrent.ConcurrentMap; |
54 import sun.util.locale.provider.LocaleProviderAdapter; |
|
55 import sun.util.calendar.CalendarUtils; |
55 import sun.util.calendar.CalendarUtils; |
56 import sun.util.calendar.ZoneInfoFile; |
56 import sun.util.calendar.ZoneInfoFile; |
|
57 import sun.util.locale.provider.LocaleProviderAdapter; |
57 |
58 |
58 /** |
59 /** |
59 * <code>SimpleDateFormat</code> is a concrete class for formatting and |
60 * <code>SimpleDateFormat</code> is a concrete class for formatting and |
60 * parsing dates in a locale-sensitive manner. It allows for formatting |
61 * parsing dates in a locale-sensitive manner. It allows for formatting |
61 * (date -> text), parsing (text -> date), and normalization. |
62 * (date -> text), parsing (text -> date), and normalization. |
1591 * String[]. |
1592 * String[]. |
1592 */ |
1593 */ |
1593 private int matchString(String text, int start, int field, |
1594 private int matchString(String text, int start, int field, |
1594 Map<String,Integer> data, CalendarBuilder calb) { |
1595 Map<String,Integer> data, CalendarBuilder calb) { |
1595 if (data != null) { |
1596 if (data != null) { |
|
1597 // TODO: make this default when it's in the spec. |
|
1598 if (data instanceof SortedMap) { |
|
1599 for (String name : data.keySet()) { |
|
1600 if (text.regionMatches(true, start, name, 0, name.length())) { |
|
1601 calb.set(field, data.get(name)); |
|
1602 return start + name.length(); |
|
1603 } |
|
1604 } |
|
1605 return -start; |
|
1606 } |
|
1607 |
1596 String bestMatch = null; |
1608 String bestMatch = null; |
1597 |
1609 |
1598 for (String name : data.keySet()) { |
1610 for (String name : data.keySet()) { |
1599 int length = name.length(); |
1611 int length = name.length(); |
1600 if (bestMatch == null || length > bestMatch.length()) { |
1612 if (bestMatch == null || length > bestMatch.length()) { |
1801 */ |
1813 */ |
1802 private int subParse(String text, int start, int patternCharIndex, int count, |
1814 private int subParse(String text, int start, int patternCharIndex, int count, |
1803 boolean obeyCount, boolean[] ambiguousYear, |
1815 boolean obeyCount, boolean[] ambiguousYear, |
1804 ParsePosition origPos, |
1816 ParsePosition origPos, |
1805 boolean useFollowingMinusSignAsDelimiter, CalendarBuilder calb) { |
1817 boolean useFollowingMinusSignAsDelimiter, CalendarBuilder calb) { |
1806 Number number = null; |
1818 Number number; |
1807 int value = 0; |
1819 int value = 0; |
1808 ParsePosition pos = new ParsePosition(0); |
1820 ParsePosition pos = new ParsePosition(0); |
1809 pos.index = start; |
1821 pos.index = start; |
1810 if (patternCharIndex == PATTERN_WEEK_YEAR && !calendar.isWeekDateSupported()) { |
1822 if (patternCharIndex == PATTERN_WEEK_YEAR && !calendar.isWeekDateSupported()) { |
1811 // use calendar year 'y' instead |
1823 // use calendar year 'y' instead |
1874 if (useDateFormatSymbols) { |
1886 if (useDateFormatSymbols) { |
1875 if ((index = matchString(text, start, Calendar.ERA, formatData.getEras(), calb)) > 0) { |
1887 if ((index = matchString(text, start, Calendar.ERA, formatData.getEras(), calb)) > 0) { |
1876 return index; |
1888 return index; |
1877 } |
1889 } |
1878 } else { |
1890 } else { |
1879 Map<String, Integer> map = calendar.getDisplayNames(field, |
1891 Map<String, Integer> map = getDisplayNamesMap(field, locale); |
1880 Calendar.ALL_STYLES, |
|
1881 locale); |
|
1882 if ((index = matchString(text, start, field, map, calb)) > 0) { |
1892 if ((index = matchString(text, start, field, map, calb)) > 0) { |
1883 return index; |
1893 return index; |
1884 } |
1894 } |
1885 } |
1895 } |
1886 break parsing; |
1896 break parsing; |
1938 |
1948 |
1939 if (useDateFormatSymbols) { |
1949 if (useDateFormatSymbols) { |
1940 // count >= 3 // i.e., MMM or MMMM |
1950 // count >= 3 // i.e., MMM or MMMM |
1941 // Want to be able to parse both short and long forms. |
1951 // Want to be able to parse both short and long forms. |
1942 // Try count == 4 first: |
1952 // Try count == 4 first: |
1943 int newStart = 0; |
1953 int newStart; |
1944 if ((newStart = matchString(text, start, Calendar.MONTH, |
1954 if ((newStart = matchString(text, start, Calendar.MONTH, |
1945 formatData.getMonths(), calb)) > 0) { |
1955 formatData.getMonths(), calb)) > 0) { |
1946 return newStart; |
1956 return newStart; |
1947 } |
1957 } |
1948 // count == 4 failed, now try count == 3 |
1958 // count == 4 failed, now try count == 3 |
1949 if ((index = matchString(text, start, Calendar.MONTH, |
1959 if ((index = matchString(text, start, Calendar.MONTH, |
1950 formatData.getShortMonths(), calb)) > 0) { |
1960 formatData.getShortMonths(), calb)) > 0) { |
1951 return index; |
1961 return index; |
1952 } |
1962 } |
1953 } else { |
1963 } else { |
1954 Map<String, Integer> map = calendar.getDisplayNames(field, |
1964 Map<String, Integer> map = getDisplayNamesMap(field, locale); |
1955 Calendar.ALL_STYLES, |
|
1956 locale); |
|
1957 if ((index = matchString(text, start, field, map, calb)) > 0) { |
1965 if ((index = matchString(text, start, field, map, calb)) > 0) { |
1958 return index; |
1966 return index; |
1959 } |
1967 } |
1960 } |
1968 } |
1961 break parsing; |
1969 break parsing; |
1977 case PATTERN_DAY_OF_WEEK: // 'E' |
1985 case PATTERN_DAY_OF_WEEK: // 'E' |
1978 { |
1986 { |
1979 if (useDateFormatSymbols) { |
1987 if (useDateFormatSymbols) { |
1980 // Want to be able to parse both short and long forms. |
1988 // Want to be able to parse both short and long forms. |
1981 // Try count == 4 (DDDD) first: |
1989 // Try count == 4 (DDDD) first: |
1982 int newStart = 0; |
1990 int newStart; |
1983 if ((newStart=matchString(text, start, Calendar.DAY_OF_WEEK, |
1991 if ((newStart=matchString(text, start, Calendar.DAY_OF_WEEK, |
1984 formatData.getWeekdays(), calb)) > 0) { |
1992 formatData.getWeekdays(), calb)) > 0) { |
1985 return newStart; |
1993 return newStart; |
1986 } |
1994 } |
1987 // DDDD failed, now try DDD |
1995 // DDDD failed, now try DDD |
2006 if ((index = matchString(text, start, Calendar.AM_PM, |
2014 if ((index = matchString(text, start, Calendar.AM_PM, |
2007 formatData.getAmPmStrings(), calb)) > 0) { |
2015 formatData.getAmPmStrings(), calb)) > 0) { |
2008 return index; |
2016 return index; |
2009 } |
2017 } |
2010 } else { |
2018 } else { |
2011 Map<String,Integer> map = calendar.getDisplayNames(field, Calendar.ALL_STYLES, locale); |
2019 Map<String,Integer> map = getDisplayNamesMap(field, locale); |
2012 if ((index = matchString(text, start, field, map, calb)) > 0) { |
2020 if ((index = matchString(text, start, field, map, calb)) > 0) { |
2013 return index; |
2021 return index; |
2014 } |
2022 } |
2015 } |
2023 } |
2016 break parsing; |
2024 break parsing; |
2338 SimpleDateFormat that = (SimpleDateFormat) obj; |
2346 SimpleDateFormat that = (SimpleDateFormat) obj; |
2339 return (pattern.equals(that.pattern) |
2347 return (pattern.equals(that.pattern) |
2340 && formatData.equals(that.formatData)); |
2348 && formatData.equals(that.formatData)); |
2341 } |
2349 } |
2342 |
2350 |
|
2351 private static final int[] REST_OF_STYLES = { |
|
2352 Calendar.SHORT_STANDALONE, Calendar.LONG_FORMAT, Calendar.LONG_STANDALONE, |
|
2353 }; |
|
2354 private Map<String, Integer> getDisplayNamesMap(int field, Locale locale) { |
|
2355 Map<String, Integer> map = calendar.getDisplayNames(field, Calendar.SHORT_FORMAT, locale); |
|
2356 // Get all SHORT and LONG styles (avoid NARROW styles). |
|
2357 for (int style : REST_OF_STYLES) { |
|
2358 Map<String, Integer> m = calendar.getDisplayNames(field, style, locale); |
|
2359 if (m != null) { |
|
2360 map.putAll(m); |
|
2361 } |
|
2362 } |
|
2363 return map; |
|
2364 } |
|
2365 |
2343 /** |
2366 /** |
2344 * After reading an object from the input stream, the format |
2367 * After reading an object from the input stream, the format |
2345 * pattern in the object is verified. |
2368 * pattern in the object is verified. |
2346 * <p> |
2369 * <p> |
2347 * @exception InvalidObjectException if the pattern is invalid |
2370 * @exception InvalidObjectException if the pattern is invalid |