Further work on SimpleTimeZone

This commit is contained in:
Alexey Andreev 2015-05-20 18:38:50 +04:00
parent 71bfaa9d66
commit bfd97bcae7
7 changed files with 98 additions and 17 deletions

View File

@ -92,6 +92,9 @@ public class CLDRHelper {
public static String getTimeZoneName(String language, String country, String id) { public static String getTimeZoneName(String language, String country, String id) {
String locale = getCode(language, country); String locale = getCode(language, country);
if (!getTimeZoneLocalizationMap().has(locale)) {
locale = language;
}
if (!getTimeZoneLocalizationMap().has(locale)) { if (!getTimeZoneLocalizationMap().has(locale)) {
return null; return null;
} }

View File

@ -48,6 +48,7 @@ public abstract class TDateFormat extends TFormat {
public final static int TIMEZONE_FIELD = 17; public final static int TIMEZONE_FIELD = 17;
protected TDateFormat() { protected TDateFormat() {
calendar = TCalendar.getInstance();
} }
@Override @Override
@ -96,6 +97,14 @@ public abstract class TDateFormat extends TFormat {
return calendar; return calendar;
} }
public TTimeZone getTimeZone() {
return calendar.getTimeZone();
}
public void setTimeZone(TTimeZone timeZone) {
calendar.setTimeZone(timeZone);
}
public static TDateFormat getDateInstance() { public static TDateFormat getDateInstance() {
return getDateInstance(DEFAULT); return getDateInstance(DEFAULT);
} }

View File

@ -345,6 +345,7 @@ abstract class TDateFormatElement {
public static class GeneralTimezone extends TDateFormatElement { public static class GeneralTimezone extends TDateFormatElement {
private static Map<TLocale, GeneralTimezone> cache; private static Map<TLocale, GeneralTimezone> cache;
private static TrieNode idSearchTrie;
private TLocale locale; private TLocale locale;
private TrieNode searchTrie; private TrieNode searchTrie;
@ -370,7 +371,7 @@ abstract class TDateFormatElement {
if (tz.getID().startsWith("GMT")) { if (tz.getID().startsWith("GMT")) {
int minutes = tz.getRawOffset() / 60_000; int minutes = tz.getRawOffset() / 60_000;
buffer.append("GMT"); buffer.append("GMT");
if (minutes > 0) { if (minutes >= 0) {
buffer.append('+'); buffer.append('+');
} else { } else {
minutes = -minutes; minutes = -minutes;
@ -399,23 +400,24 @@ abstract class TDateFormatElement {
if (position.getIndex() + 1 < text.length()) { if (position.getIndex() + 1 < text.length()) {
} }
TTimeZone tz = match(text, position); TTimeZone tz = match(searchTrie, text, position);
if (tz != null) {
date.setTimeZone(tz);
} else {
prepareIdTrie();
tz = match(idSearchTrie, text, position);
if (tz != null) { if (tz != null) {
date.setTimeZone(tz); date.setTimeZone(tz);
} else { } else {
position.setErrorIndex(position.getIndex()); position.setErrorIndex(position.getIndex());
} }
} }
private void parseHoursMinutes(String text, TCalendar date, TParsePosition position) {
} }
public TTimeZone match(String text, TParsePosition position) { public TTimeZone match(TrieNode node, String text, TParsePosition position) {
prepareTrie(); prepareTrie();
int start = position.getIndex(); int start = position.getIndex();
int index = start; int index = start;
TrieNode node = searchTrie;
int lastMatch = start; int lastMatch = start;
TTimeZone tz = null; TTimeZone tz = null;
while (node.childNodes.length > 0) { while (node.childNodes.length > 0) {
@ -426,7 +428,7 @@ abstract class TDateFormatElement {
if (index >= text.length()) { if (index >= text.length()) {
break; break;
} }
int next = Arrays.binarySearch(node.chars, text.charAt(index++)); int next = Arrays.binarySearch(node.chars, Character.toLowerCase(text.charAt(index++)));
if (next < 0) { if (next < 0) {
return null; return null;
} }
@ -445,7 +447,58 @@ abstract class TDateFormatElement {
TTimeZone tz = TTimeZone.getTimeZone(tzId); TTimeZone tz = TTimeZone.getTimeZone(tzId);
builder.add(tz.getDisplayName(locale), tz); builder.add(tz.getDisplayName(locale), tz);
} }
searchTrie = builder.build();
} }
private static void prepareIdTrie() {
if (idSearchTrie != null) {
return;
}
TrieBuilder builder = new TrieBuilder();
for (String tzId : TTimeZone.getAvailableIDs()) {
TTimeZone tz = TTimeZone.getTimeZone(tzId);
builder.add(tz.getID(), tz);
}
}
}
static void parseHoursMinutes(String text, TCalendar date, TParsePosition position) {
int index = position.getIndex() + 3;
int sign = text.charAt(index++) == '-' ? -1 : 1;
if (index >= text.length() || !Character.isDigit(text.charAt(index))) {
position.setErrorIndex(index);
return;
}
int hours = Character.digit(text.charAt(index++), 10);
if (index >= text.length()) {
position.setErrorIndex(index);
return;
}
if (text.charAt(index) != ':') {
if (!Character.isDigit(text.charAt(index))) {
position.setErrorIndex(index);
return;
}
hours = 10 * hours + Character.digit(text.charAt(index), 10);
}
if (index >= text.length() || text.charAt(index) != ':') {
position.setErrorIndex(index);
return;
}
if (index + 2 > text.length() || !Character.isDigit(text.charAt(index)) ||
!Character.isDigit(text.charAt(index + 1))) {
position.setErrorIndex(index);
return;
}
int minutes = Character.digit(text.charAt(index), 10) * 10 + Character.digit(text.charAt(index), 10);
position.setIndex(index + 2);
TTimeZone tz = getStaticTimeZone(sign * hours, minutes);
date.setTimeZone(tz);
}
static TTimeZone getStaticTimeZone(int hours, int minutes) {
return TTimeZone.getTimeZone("GMT" + (hours) + ":" + (minutes / 10) + (minutes % 10));
} }
static class TrieNode { static class TrieNode {
@ -461,7 +514,7 @@ abstract class TDateFormatElement {
int index = 0; int index = 0;
TrieNodeBuilder node = root; TrieNodeBuilder node = root;
while (index < text.length()) { while (index < text.length()) {
char c = text.charAt(index); char c = Character.toLowerCase(text.charAt(index));
while (node.ch != c) { while (node.ch != c) {
if (node.ch == '\0') { if (node.ch == '\0') {
node.ch = c; node.ch = c;
@ -478,7 +531,11 @@ abstract class TDateFormatElement {
node.tz = tz; node.tz = tz;
} }
public TrieNode build(TrieNodeBuilder builder) { public TrieNode build() {
return build(root);
}
TrieNode build(TrieNodeBuilder builder) {
TrieNode node = new TrieNode(); TrieNode node = new TrieNode();
node.tz = builder.tz; node.tz = builder.tz;
List<TrieNodeBuilder> builders = new ArrayList<>(); List<TrieNodeBuilder> builders = new ArrayList<>();

View File

@ -59,6 +59,7 @@ public class TSimpleDateFormat extends TDateFormat {
public StringBuffer format(TDate date, StringBuffer buffer, TFieldPosition field) { public StringBuffer format(TDate date, StringBuffer buffer, TFieldPosition field) {
TCalendar calendar = new TGregorianCalendar(locale); TCalendar calendar = new TGregorianCalendar(locale);
calendar.setTime(date); calendar.setTime(date);
calendar.setTimeZone(this.calendar.getTimeZone());
for (TDateFormatElement element : elements) { for (TDateFormatElement element : elements) {
element.format(calendar, buffer); element.format(calendar, buffer);
} }
@ -71,7 +72,7 @@ public class TSimpleDateFormat extends TDateFormat {
} }
private void reparsePattern() { private void reparsePattern() {
TSimpleDatePatternParser parser = new TSimpleDatePatternParser(dateFormatSymbols); TSimpleDatePatternParser parser = new TSimpleDatePatternParser(dateFormatSymbols, locale);
parser.parsePattern(pattern); parser.parsePattern(pattern);
elements = parser.getElements().toArray(new TDateFormatElement[0]); elements = parser.getElements().toArray(new TDateFormatElement[0]);
} }

View File

@ -18,6 +18,7 @@ package org.teavm.classlib.java.text;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.teavm.classlib.java.util.TCalendar; import org.teavm.classlib.java.util.TCalendar;
import org.teavm.classlib.java.util.TLocale;
/** /**
* *
@ -25,12 +26,14 @@ import org.teavm.classlib.java.util.TCalendar;
*/ */
class TSimpleDatePatternParser { class TSimpleDatePatternParser {
private TDateFormatSymbols symbols; private TDateFormatSymbols symbols;
private TLocale locale;
private List<TDateFormatElement> elements = new ArrayList<>(); private List<TDateFormatElement> elements = new ArrayList<>();
private int index; private int index;
private String pattern; private String pattern;
public TSimpleDatePatternParser(TDateFormatSymbols symbols) { public TSimpleDatePatternParser(TDateFormatSymbols symbols, TLocale locale) {
this.symbols = symbols; this.symbols = symbols;
this.locale = locale;
} }
public List<TDateFormatElement> getElements() { public List<TDateFormatElement> getElements() {
@ -148,6 +151,11 @@ class TSimpleDatePatternParser {
elements.add(new TDateFormatElement.Numeric(TCalendar.MILLISECOND, rep)); elements.add(new TDateFormatElement.Numeric(TCalendar.MILLISECOND, rep));
break; break;
} }
case 'z': {
parseRepetitions();
elements.add(TDateFormatElement.GeneralTimezone.get(locale));
break;
}
default: default:
if (isControl(c)) { if (isControl(c)) {
parseRepetitions(); parseRepetitions();

View File

@ -26,10 +26,13 @@ class TIANATimeZone extends TTimeZone {
private static final long serialVersionUID = -8196006595542230951L; private static final long serialVersionUID = -8196006595542230951L;
private DateTimeZone underlyingZone; private DateTimeZone underlyingZone;
private int rawOffset; private int rawOffset;
private int diff;
public TIANATimeZone(DateTimeZone underlyingZone) { public TIANATimeZone(DateTimeZone underlyingZone) {
super(underlyingZone.getID()); super(underlyingZone.getID());
this.underlyingZone = underlyingZone; this.underlyingZone = underlyingZone;
rawOffset = underlyingZone.getStandardOffset(System.currentTimeMillis());
diff = -rawOffset;
} }
@Override @Override
@ -43,7 +46,7 @@ class TIANATimeZone extends TTimeZone {
@Override @Override
public int getOffset(long time) { public int getOffset(long time) {
return rawOffset + underlyingZone.getOffset(time); return rawOffset + diff + underlyingZone.getOffset(time);
} }
@Override @Override
@ -63,7 +66,7 @@ class TIANATimeZone extends TTimeZone {
@Override @Override
public boolean useDaylightTime() { public boolean useDaylightTime() {
return underlyingZone.isFixed(); return !underlyingZone.isFixed();
} }
@Override @Override

View File

@ -69,7 +69,7 @@ public final class TLocale implements TCloneable, TSerializable {
static { static {
String localeName = CLDRHelper.getDefaultLocale().getValue(); String localeName = CLDRHelper.getDefaultLocale().getValue();
int countryIndex = localeName.indexOf('_'); int countryIndex = localeName.indexOf('_');
defaultLocale = new TLocale(localeName.substring(0, countryIndex), localeName.substring(countryIndex) + 1, ""); defaultLocale = new TLocale(localeName.substring(0, countryIndex), localeName.substring(countryIndex + 1), "");
} }
private transient String countryCode; private transient String countryCode;