jdk/src/share/classes/java/text/SimpleDateFormat.java
changeset 14765 0987999ed367
parent 14014 da3648e13e67
child 16010 2727163b5df5
equal deleted inserted replaced
14764:6dd2370b4cd3 14765:0987999ed367
    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;
  2096                 {
  2104                 {
  2097                     if ((text.length() - pos.index) <= 0) {
  2105                     if ((text.length() - pos.index) <= 0) {
  2098                         break parsing;
  2106                         break parsing;
  2099                     }
  2107                     }
  2100 
  2108 
  2101                     int sign = 0;
  2109                     int sign;
  2102                     char c = text.charAt(pos.index);
  2110                     char c = text.charAt(pos.index);
  2103                     if (c == 'Z') {
  2111                     if (c == 'Z') {
  2104                         calb.set(Calendar.ZONE_OFFSET, 0).set(Calendar.DST_OFFSET, 0);
  2112                         calb.set(Calendar.ZONE_OFFSET, 0).set(Calendar.DST_OFFSET, 0);
  2105                         return ++pos.index;
  2113                         return ++pos.index;
  2106                     }
  2114                     }
  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