1614 String bestMatch = null; 1615 1616 for (String name : data.keySet()) { 1617 int length = name.length(); 1618 if (bestMatch == null || length > bestMatch.length()) { 1619 if (text.regionMatches(true, start, name, 0, length)) { 1620 bestMatch = name; 1621 } 1622 } 1623 } 1624 1625 if (bestMatch != null) { 1626 calb.set(field, data.get(bestMatch)); 1627 return start + bestMatch.length(); 1628 } 1629 } 1630 return -start; 1631 } 1632 1633 private int matchZoneString(String text, int start, String[] zoneNames) { 1634 for (int i = 1; i <= 4; ++i) { 1635 // Checking long and short zones [1 & 2], 1636 // and long and short daylight [3 & 4]. 1637 String zoneName = zoneNames[i]; 1638 if (text.regionMatches(true, start, 1639 zoneName, 0, zoneName.length())) { 1640 return i; 1641 } 1642 } 1643 return -1; 1644 } 1645 1646 private boolean matchDSTString(String text, int start, int zoneIndex, int standardIndex, 1647 String[][] zoneStrings) { 1648 int index = standardIndex + 2; 1649 String zoneName = zoneStrings[zoneIndex][index]; 1650 if (text.regionMatches(true, start, 1651 zoneName, 0, zoneName.length())) { 1652 return true; 1653 } 1654 return false; 1655 } 1656 1657 /** 1658 * find time zone 'text' matched zoneStrings and set to internal 1659 * calendar. 1660 */ 1661 private int subParseZoneString(String text, int start, CalendarBuilder calb) { 1662 boolean useSameName = false; // true if standard and daylight time use the same abbreviation. 1663 TimeZone currentTimeZone = getTimeZone(); 1664 1665 // At this point, check for named time zones by looking through 1666 // the locale data from the TimeZoneNames strings. 1667 // Want to be able to parse both short and long forms. 1668 int zoneIndex = formatData.getZoneIndex(currentTimeZone.getID()); 1669 TimeZone tz = null; 1670 String[][] zoneStrings = formatData.getZoneStringsWrapper(); 1671 String[] zoneNames = null; 1672 int nameIndex = 0; 1673 if (zoneIndex != -1) { 1674 zoneNames = zoneStrings[zoneIndex]; 1675 if ((nameIndex = matchZoneString(text, start, zoneNames)) > 0) { 1676 if (nameIndex <= 2) { 1677 // Check if the standard name (abbr) and the daylight name are the same. 1678 useSameName = zoneNames[nameIndex].equalsIgnoreCase(zoneNames[nameIndex + 2]); 1679 } 1680 tz = TimeZone.getTimeZone(zoneNames[0]); 1681 } 1682 } 1683 if (tz == null) { 1684 zoneIndex = formatData.getZoneIndex(TimeZone.getDefault().getID()); 1685 if (zoneIndex != -1) { 1686 zoneNames = zoneStrings[zoneIndex]; 1687 if ((nameIndex = matchZoneString(text, start, zoneNames)) > 0) { 1688 if (nameIndex <= 2) { 1689 useSameName = zoneNames[nameIndex].equalsIgnoreCase(zoneNames[nameIndex + 2]); 1690 } 1691 tz = TimeZone.getTimeZone(zoneNames[0]); 1692 } 1693 } 1694 } 1695 1696 if (tz == null) { 1697 int len = zoneStrings.length; 1698 for (int i = 0; i < len; i++) { 1699 zoneNames = zoneStrings[i]; 1700 if ((nameIndex = matchZoneString(text, start, zoneNames)) > 0) { 1701 if (nameIndex <= 2) { 1702 useSameName = zoneNames[nameIndex].equalsIgnoreCase(zoneNames[nameIndex + 2]); 1703 } 1704 tz = TimeZone.getTimeZone(zoneNames[0]); 1705 break; 1706 } 1707 } 1708 } 1709 if (tz != null) { // Matched any ? 1710 if (!tz.equals(currentTimeZone)) { 1711 setTimeZone(tz); 1712 } 1713 // If the time zone matched uses the same name 1714 // (abbreviation) for both standard and daylight time, 1715 // let the time zone in the Calendar decide which one. 1716 // 1717 // Also if tz.getDSTSaving() returns 0 for DST, use tz to 1718 // determine the local time. (6645292) 1719 int dstAmount = (nameIndex >= 3) ? tz.getDSTSavings() : 0; 1720 if (!(useSameName || (nameIndex >= 3 && dstAmount == 0))) { 1721 calb.clear(Calendar.ZONE_OFFSET).set(Calendar.DST_OFFSET, dstAmount); 1722 } 1723 return (start + zoneNames[nameIndex].length()); 1724 } 2058 } 2059 if (sign == 0) { 2060 // Try parsing a custom time zone "GMT+hh:mm" or "GMT". 2061 if ((c == 'G' || c == 'g') 2062 && (text.length() - start) >= GMT.length() 2063 && text.regionMatches(true, start, GMT, 0, GMT.length())) { 2064 pos.index = start + GMT.length(); 2065 2066 if ((text.length() - pos.index) > 0) { 2067 c = text.charAt(pos.index); 2068 if (c == '+') { 2069 sign = 1; 2070 } else if (c == '-') { 2071 sign = -1; 2072 } 2073 } 2074 2075 if (sign == 0) { /* "GMT" without offset */ 2076 calb.set(Calendar.ZONE_OFFSET, 0) 2077 .set(Calendar.DST_OFFSET, 0); 2078 return pos.index; 2079 } 2080 2081 // Parse the rest as "hh:mm" 2082 int i = subParseNumericZone(text, ++pos.index, 2083 sign, 0, true, calb); 2084 if (i > 0) { 2085 return i; 2086 } 2087 pos.index = -i; 2088 } else { 2089 // Try parsing the text as a time zone 2090 // name or abbreviation. 2091 int i = subParseZoneString(text, pos.index, calb); 2092 if (i > 0) { 2093 return i; 2094 } 2095 pos.index = -i; 2096 } 2097 } else { | 1614 String bestMatch = null; 1615 1616 for (String name : data.keySet()) { 1617 int length = name.length(); 1618 if (bestMatch == null || length > bestMatch.length()) { 1619 if (text.regionMatches(true, start, name, 0, length)) { 1620 bestMatch = name; 1621 } 1622 } 1623 } 1624 1625 if (bestMatch != null) { 1626 calb.set(field, data.get(bestMatch)); 1627 return start + bestMatch.length(); 1628 } 1629 } 1630 return -start; 1631 } 1632 1633 private int matchZoneString(String text, int start, String[] zoneNames) { 1634 for (int i = 0; i <= 4; ++i) { 1635 // Checking main zone[0], long and short zones [1 & 2], 1636 // and long and short daylight [3 & 4]. 1637 String zoneName = zoneNames[i]; 1638 if (text.regionMatches(true, start, 1639 zoneName, 0, zoneName.length())) { 1640 return i; 1641 } 1642 } 1643 return -1; 1644 } 1645 1646 private boolean matchDSTString(String text, int start, int zoneIndex, int standardIndex, 1647 String[][] zoneStrings) { 1648 int index = standardIndex + 2; 1649 String zoneName = zoneStrings[zoneIndex][index]; 1650 if (text.regionMatches(true, start, 1651 zoneName, 0, zoneName.length())) { 1652 return true; 1653 } 1654 return false; 1655 } 1656 1657 /** 1658 * find time zone 'text' matched zoneStrings and set to internal 1659 * calendar. 1660 * To fix the Bug 8141243, this method is slightly altered and works like this: 1661 * If nameIndex is matching DST in zoneNames(i.e.nameIndex>2), then tz is assigned to the first timezone (at index 0), 1662 * otherwise "tz" is assigned to the timzone at nameIndex in the zoneNames.This will make sure that, 1663 * if any of the abbreviated timezones(like UTC,IST,PST,etc...) which is also part of the main timezone groups is set properly. 1664 * Also, there is a special condition added for the other virtual timezones which are not part of the main timezones 1665 * like AKST,ACST,AEST,WAT,etc.(i.e. "TimeZone.getTimeZone(zoneNames)" always returns "GMT" for those timezones), 1666 * in which the timezone "tz" is always set to the first timezone in the group(at index 0). 1667 */ 1668 private int subParseZoneString(String text, int start, CalendarBuilder calb) { 1669 boolean useSameName = false; // true if standard and daylight time use the same abbreviation. 1670 TimeZone currentTimeZone = getTimeZone(); 1671 1672 // At this point, check for named time zones by looking through 1673 // the locale data from the TimeZoneNames strings. 1674 // Want to be able to parse both short and long forms. 1675 int zoneIndex = formatData.getZoneIndex(currentTimeZone.getID()); 1676 TimeZone tz = null; 1677 String[][] zoneStrings = formatData.getZoneStringsWrapper(); 1678 String[] zoneNames = null; 1679 int nameIndex = -1; 1680 if (zoneIndex != -1) { 1681 zoneNames = zoneStrings[zoneIndex]; 1682 if ((nameIndex = matchZoneString(text, start, zoneNames)) >= 0) { 1683 if (nameIndex > 0 && nameIndex < 3) { 1684 // Check if the standard name (abbr) and the daylight name are the same. 1685 useSameName = zoneNames[nameIndex].equalsIgnoreCase(zoneNames[nameIndex + 2]); 1686 } 1687 int index = (nameIndex <= 2) ? nameIndex : 0; 1688 tz = TimeZone.getTimeZone(zoneNames[index]); 1689 if (!("GMT".equals(currentTimeZone.getID()) || "GMT".equals(zoneNames[index])) 1690 && "GMT".equals(tz.getID())) { 1691 tz = TimeZone.getTimeZone(zoneNames[0]); 1692 } 1693 } 1694 } 1695 if (tz == null) { 1696 zoneIndex = formatData.getZoneIndex(TimeZone.getDefault().getID()); 1697 if (zoneIndex != -1) { 1698 zoneNames = zoneStrings[zoneIndex]; 1699 if ((nameIndex = matchZoneString(text, start, zoneNames)) >= 0) { 1700 if (nameIndex > 0 && nameIndex < 3) { 1701 useSameName = zoneNames[nameIndex].equalsIgnoreCase(zoneNames[nameIndex + 2]); 1702 } 1703 int index = (nameIndex <= 2) ? nameIndex : 0; 1704 tz = TimeZone.getTimeZone(zoneNames[index]); 1705 if (!("GMT".equals(TimeZone.getDefault().getID()) || "GMT".equals(zoneNames[index])) 1706 && "GMT".equals(tz.getID())) { 1707 tz = TimeZone.getTimeZone(zoneNames[0]); 1708 } 1709 } 1710 } 1711 } 1712 1713 if (tz == null) { 1714 int len = zoneStrings.length; 1715 for (int i = 0; i < len; i++) { 1716 zoneNames = zoneStrings[i]; 1717 if ((nameIndex = matchZoneString(text, start, zoneNames)) >= 0) { 1718 if (nameIndex > 0 && nameIndex < 3) { 1719 useSameName = zoneNames[nameIndex].equalsIgnoreCase(zoneNames[nameIndex + 2]); 1720 } 1721 int index = (nameIndex <= 2) ? nameIndex : 0; 1722 tz = TimeZone.getTimeZone(zoneNames[index]); 1723 if (!("GMT".equals(zoneNames[0]) || "GMT".equals(zoneNames[index])) && "GMT".equals(tz.getID())) { 1724 tz = TimeZone.getTimeZone(zoneNames[0]); 1725 } 1726 break; 1727 } 1728 } 1729 } 1730 if (tz != null) { // Matched any ? 1731 if (!tz.equals(currentTimeZone)) { 1732 setTimeZone(tz); 1733 } 1734 // If the time zone matched uses the same name 1735 // (abbreviation) for both standard and daylight time, 1736 // let the time zone in the Calendar decide which one. 1737 // 1738 // Also if tz.getDSTSaving() returns 0 for DST, use tz to 1739 // determine the local time. (6645292) 1740 int dstAmount = (nameIndex >= 3) ? tz.getDSTSavings() : 0; 1741 if (!(useSameName || (nameIndex >= 3 && dstAmount == 0))) { 1742 calb.clear(Calendar.ZONE_OFFSET).set(Calendar.DST_OFFSET, dstAmount); 1743 } 1744 return (start + zoneNames[nameIndex].length()); 1745 } 2079 } 2080 if (sign == 0) { 2081 // Try parsing a custom time zone "GMT+hh:mm" or "GMT". 2082 if ((c == 'G' || c == 'g') 2083 && (text.length() - start) >= GMT.length() 2084 && text.regionMatches(true, start, GMT, 0, GMT.length())) { 2085 pos.index = start + GMT.length(); 2086 2087 if ((text.length() - pos.index) > 0) { 2088 c = text.charAt(pos.index); 2089 if (c == '+') { 2090 sign = 1; 2091 } else if (c == '-') { 2092 sign = -1; 2093 } 2094 } 2095 2096 if (sign == 0) { /* "GMT" without offset */ 2097 calb.set(Calendar.ZONE_OFFSET, 0) 2098 .set(Calendar.DST_OFFSET, 0); 2099 // set the timezone "GMT" to internal calendar, since it will not be set later. 2100 setTimeZone(TimeZone.getTimeZone("GMT")); 2101 return pos.index; 2102 } 2103 2104 // Parse the rest as "hh:mm" 2105 int i = subParseNumericZone(text, ++pos.index, 2106 sign, 0, true, calb); 2107 if (i > 0) { 2108 return i; 2109 } 2110 pos.index = -i; 2111 } else { 2112 // Try parsing the text as a time zone 2113 // name or abbreviation. 2114 int i = subParseZoneString(text, pos.index, calb); 2115 if (i > 0) { 2116 return i; 2117 } 2118 pos.index = -i; 2119 } 2120 } else { |