mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-10 08:54:11 -08:00
Adding support of timezones in SimpleDateFormat
This commit is contained in:
parent
76cf035660
commit
71bfaa9d66
|
@ -15,8 +15,17 @@
|
|||
*/
|
||||
package org.teavm.classlib.java.text;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.teavm.classlib.java.util.TCalendar;
|
||||
import org.teavm.classlib.java.util.TGregorianCalendar;
|
||||
import org.teavm.classlib.java.util.TLocale;
|
||||
import org.teavm.classlib.java.util.TTimeZone;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -333,4 +342,170 @@ abstract class TDateFormatElement {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class GeneralTimezone extends TDateFormatElement {
|
||||
private static Map<TLocale, GeneralTimezone> cache;
|
||||
private TLocale locale;
|
||||
private TrieNode searchTrie;
|
||||
|
||||
private GeneralTimezone(TLocale locale) {
|
||||
this.locale = locale;
|
||||
}
|
||||
|
||||
public static GeneralTimezone get(TLocale locale) {
|
||||
if (cache == null) {
|
||||
cache = new HashMap<>();
|
||||
}
|
||||
GeneralTimezone elem = cache.get(locale);
|
||||
if (elem == null) {
|
||||
elem = new GeneralTimezone(locale);
|
||||
cache.put(locale, elem);
|
||||
}
|
||||
return elem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void format(TCalendar date, StringBuffer buffer) {
|
||||
TTimeZone tz = date.getTimeZone();
|
||||
if (tz.getID().startsWith("GMT")) {
|
||||
int minutes = tz.getRawOffset() / 60_000;
|
||||
buffer.append("GMT");
|
||||
if (minutes > 0) {
|
||||
buffer.append('+');
|
||||
} else {
|
||||
minutes = -minutes;
|
||||
buffer.append('-');
|
||||
}
|
||||
int hours = minutes / 60;
|
||||
minutes %= 60;
|
||||
buffer.append(hours / 10).append(hours % 10).append(':').append(minutes / 10).append(minutes % 10);
|
||||
} else {
|
||||
buffer.append(tz.getDisplayName(locale));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parse(String text, TCalendar date, TParsePosition position) {
|
||||
if (position.getIndex() + 4 < text.length()) {
|
||||
int signIndex = position.getIndex() + 3;
|
||||
if (text.substring(position.getIndex(), signIndex).equals("GMT")) {
|
||||
char signChar = text.charAt(signIndex);
|
||||
if (signChar == '+' || signChar == '-') {
|
||||
parseHoursMinutes(text, date, position);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (position.getIndex() + 1 < text.length()) {
|
||||
|
||||
}
|
||||
TTimeZone tz = match(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) {
|
||||
prepareTrie();
|
||||
int start = position.getIndex();
|
||||
int index = start;
|
||||
TrieNode node = searchTrie;
|
||||
int lastMatch = start;
|
||||
TTimeZone tz = null;
|
||||
while (node.childNodes.length > 0) {
|
||||
if (node.tz != null) {
|
||||
lastMatch = index;
|
||||
tz = node.tz;
|
||||
}
|
||||
if (index >= text.length()) {
|
||||
break;
|
||||
}
|
||||
int next = Arrays.binarySearch(node.chars, text.charAt(index++));
|
||||
if (next < 0) {
|
||||
return null;
|
||||
}
|
||||
node = node.childNodes[index];
|
||||
}
|
||||
position.setIndex(lastMatch);
|
||||
return tz;
|
||||
}
|
||||
|
||||
private void prepareTrie() {
|
||||
if (searchTrie != null) {
|
||||
return;
|
||||
}
|
||||
TrieBuilder builder = new TrieBuilder();
|
||||
for (String tzId : TTimeZone.getAvailableIDs()) {
|
||||
TTimeZone tz = TTimeZone.getTimeZone(tzId);
|
||||
builder.add(tz.getDisplayName(locale), tz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class TrieNode {
|
||||
char[] chars;
|
||||
TrieNode[] childNodes;
|
||||
TTimeZone tz;
|
||||
}
|
||||
|
||||
static class TrieBuilder {
|
||||
TrieNodeBuilder root = new TrieNodeBuilder();
|
||||
|
||||
public void add(String text, TTimeZone tz) {
|
||||
int index = 0;
|
||||
TrieNodeBuilder node = root;
|
||||
while (index < text.length()) {
|
||||
char c = text.charAt(index);
|
||||
while (node.ch != c) {
|
||||
if (node.ch == '\0') {
|
||||
node.ch = c;
|
||||
node.sibling = new TrieNodeBuilder();
|
||||
break;
|
||||
}
|
||||
node = node.sibling;
|
||||
}
|
||||
if (node.next == null) {
|
||||
node.next = new TrieNodeBuilder();
|
||||
}
|
||||
node = node.next;
|
||||
}
|
||||
node.tz = tz;
|
||||
}
|
||||
|
||||
public TrieNode build(TrieNodeBuilder builder) {
|
||||
TrieNode node = new TrieNode();
|
||||
node.tz = builder.tz;
|
||||
List<TrieNodeBuilder> builders = new ArrayList<>();
|
||||
TrieNodeBuilder tmp = builder;
|
||||
while (tmp.ch != '\0') {
|
||||
builders.add(builder);
|
||||
builder = builder.sibling;
|
||||
}
|
||||
Collections.sort(builders, new Comparator<TrieNodeBuilder>() {
|
||||
@Override public int compare(TrieNodeBuilder o1, TrieNodeBuilder o2) {
|
||||
return Character.compare(o1.ch, o2.ch);
|
||||
}
|
||||
});
|
||||
node.chars = new char[builders.size()];
|
||||
node.childNodes = new TrieNode[builders.size()];
|
||||
for (int i = 0; i < node.chars.length; ++i) {
|
||||
node.chars[i] = builders.get(i).ch;
|
||||
node.childNodes[i] = build(builders.get(i));
|
||||
}
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
static class TrieNodeBuilder {
|
||||
char ch;
|
||||
TrieNodeBuilder next;
|
||||
TTimeZone tz;
|
||||
TrieNodeBuilder sibling;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user