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) {
String locale = getCode(language, country);
if (!getTimeZoneLocalizationMap().has(locale)) {
locale = language;
}
if (!getTimeZoneLocalizationMap().has(locale)) {
return null;
}

View File

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

View File

@ -345,6 +345,7 @@ abstract class TDateFormatElement {
public static class GeneralTimezone extends TDateFormatElement {
private static Map<TLocale, GeneralTimezone> cache;
private static TrieNode idSearchTrie;
private TLocale locale;
private TrieNode searchTrie;
@ -370,7 +371,7 @@ abstract class TDateFormatElement {
if (tz.getID().startsWith("GMT")) {
int minutes = tz.getRawOffset() / 60_000;
buffer.append("GMT");
if (minutes > 0) {
if (minutes >= 0) {
buffer.append('+');
} else {
minutes = -minutes;
@ -399,23 +400,24 @@ abstract class TDateFormatElement {
if (position.getIndex() + 1 < text.length()) {
}
TTimeZone tz = match(text, position);
TTimeZone tz = match(searchTrie, text, position);
if (tz != null) {
date.setTimeZone(tz);
} else {
position.setErrorIndex(position.getIndex());
prepareIdTrie();
tz = match(idSearchTrie, text, position);
if (tz != null) {
date.setTimeZone(tz);
} else {
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();
int start = position.getIndex();
int index = start;
TrieNode node = searchTrie;
int lastMatch = start;
TTimeZone tz = null;
while (node.childNodes.length > 0) {
@ -426,7 +428,7 @@ abstract class TDateFormatElement {
if (index >= text.length()) {
break;
}
int next = Arrays.binarySearch(node.chars, text.charAt(index++));
int next = Arrays.binarySearch(node.chars, Character.toLowerCase(text.charAt(index++)));
if (next < 0) {
return null;
}
@ -445,7 +447,58 @@ abstract class TDateFormatElement {
TTimeZone tz = TTimeZone.getTimeZone(tzId);
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 {
@ -461,7 +514,7 @@ abstract class TDateFormatElement {
int index = 0;
TrieNodeBuilder node = root;
while (index < text.length()) {
char c = text.charAt(index);
char c = Character.toLowerCase(text.charAt(index));
while (node.ch != c) {
if (node.ch == '\0') {
node.ch = c;
@ -478,7 +531,11 @@ abstract class TDateFormatElement {
node.tz = tz;
}
public TrieNode build(TrieNodeBuilder builder) {
public TrieNode build() {
return build(root);
}
TrieNode build(TrieNodeBuilder builder) {
TrieNode node = new TrieNode();
node.tz = builder.tz;
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) {
TCalendar calendar = new TGregorianCalendar(locale);
calendar.setTime(date);
calendar.setTimeZone(this.calendar.getTimeZone());
for (TDateFormatElement element : elements) {
element.format(calendar, buffer);
}
@ -71,7 +72,7 @@ public class TSimpleDateFormat extends TDateFormat {
}
private void reparsePattern() {
TSimpleDatePatternParser parser = new TSimpleDatePatternParser(dateFormatSymbols);
TSimpleDatePatternParser parser = new TSimpleDatePatternParser(dateFormatSymbols, locale);
parser.parsePattern(pattern);
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.List;
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 {
private TDateFormatSymbols symbols;
private TLocale locale;
private List<TDateFormatElement> elements = new ArrayList<>();
private int index;
private String pattern;
public TSimpleDatePatternParser(TDateFormatSymbols symbols) {
public TSimpleDatePatternParser(TDateFormatSymbols symbols, TLocale locale) {
this.symbols = symbols;
this.locale = locale;
}
public List<TDateFormatElement> getElements() {
@ -148,6 +151,11 @@ class TSimpleDatePatternParser {
elements.add(new TDateFormatElement.Numeric(TCalendar.MILLISECOND, rep));
break;
}
case 'z': {
parseRepetitions();
elements.add(TDateFormatElement.GeneralTimezone.get(locale));
break;
}
default:
if (isControl(c)) {
parseRepetitions();

View File

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

View File

@ -69,7 +69,7 @@ public final class TLocale implements TCloneable, TSerializable {
static {
String localeName = CLDRHelper.getDefaultLocale().getValue();
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;