mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-09 08:24:10 -08:00
First version of time zone detector
This commit is contained in:
parent
05c74a2d8a
commit
46da627318
|
@ -1169,6 +1169,7 @@ public class DateTimeZoneBuilder {
|
||||||
|
|
||||||
DSTZone tailZone;
|
DSTZone tailZone;
|
||||||
if (flow.characters[flow.pointer++] == 'y') {
|
if (flow.characters[flow.pointer++] == 'y') {
|
||||||
|
flow.pointer++;
|
||||||
tailZone = DSTZone.readZone(id, flow);
|
tailZone = DSTZone.readZone(id, flow);
|
||||||
} else {
|
} else {
|
||||||
tailZone = null;
|
tailZone = null;
|
||||||
|
|
|
@ -16,11 +16,16 @@
|
||||||
package org.teavm.classlib.impl.tz;
|
package org.teavm.classlib.impl.tz;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.PriorityQueue;
|
||||||
|
import java.util.Set;
|
||||||
import org.teavm.classlib.impl.Base46;
|
import org.teavm.classlib.impl.Base46;
|
||||||
import org.teavm.classlib.impl.CharFlow;
|
import org.teavm.classlib.impl.CharFlow;
|
||||||
|
import org.teavm.jso.JSBody;
|
||||||
import org.teavm.platform.metadata.MetadataProvider;
|
import org.teavm.platform.metadata.MetadataProvider;
|
||||||
import org.teavm.platform.metadata.ResourceMap;
|
import org.teavm.platform.metadata.ResourceMap;
|
||||||
|
|
||||||
|
@ -67,6 +72,96 @@ public class DateTimeZoneProvider {
|
||||||
return ids.toArray(new String[ids.size()]);
|
return ids.toArray(new String[ids.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static DateTimeZone detectTimezone() {
|
||||||
|
List<Score> zones = new ArrayList<>();
|
||||||
|
long time = System.currentTimeMillis();
|
||||||
|
int offset = -getNativeOffset(System.currentTimeMillis());
|
||||||
|
for (String id : getIds()) {
|
||||||
|
DateTimeZone tz = getTimeZone(id);
|
||||||
|
int tzOffset = tz.getOffset(time) / 60_000;
|
||||||
|
if (Math.abs(tzOffset - offset) > 120) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
zones.add(new Score(tz));
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Score> scoreTable = new ArrayList<>();
|
||||||
|
scoreTable.addAll(zones);
|
||||||
|
Map<Long, List<Score>> zoneMap = new HashMap<>();
|
||||||
|
PriorityQueue<Long> queue = new PriorityQueue<>(zones.size(), new Comparator<Long>() {
|
||||||
|
@Override public int compare(Long o1, Long o2) {
|
||||||
|
return o2.compareTo(o1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Set<Long> timeInQueue = new HashSet<>();
|
||||||
|
long last = time;
|
||||||
|
queue.add(time);
|
||||||
|
zoneMap.put(time, new ArrayList<>(zones));
|
||||||
|
|
||||||
|
while (!queue.isEmpty() && scoreTable.size() > 1) {
|
||||||
|
time = queue.remove();
|
||||||
|
timeInQueue.remove(time);
|
||||||
|
zones = zoneMap.remove(time);
|
||||||
|
offset = -getNativeOffset(time);
|
||||||
|
|
||||||
|
for (Score score : zones) {
|
||||||
|
long prev = score.tz.previousTransition(time);
|
||||||
|
if (prev == time) {
|
||||||
|
if (scoreTable.get(0) == score) {
|
||||||
|
return score.tz;
|
||||||
|
}
|
||||||
|
scoreTable.remove(score);
|
||||||
|
} else {
|
||||||
|
int tzOffset = score.tz.getOffset(time) / 60_000;
|
||||||
|
if (Math.abs(tzOffset - offset) > 120) {
|
||||||
|
scoreTable.remove(score);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
List<Score> prevZones = zoneMap.get(prev);
|
||||||
|
if (prevZones == null) {
|
||||||
|
prevZones = new ArrayList<>();
|
||||||
|
zoneMap.put(prev, prevZones);
|
||||||
|
}
|
||||||
|
prevZones.add(score);
|
||||||
|
if (timeInQueue.add(prev)) {
|
||||||
|
queue.add(prev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scoreTable.get(0).tz.previousTransition(time) == time) {
|
||||||
|
return scoreTable.get(0).tz;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = scoreTable.size() - 1; i >= 0; --i) {
|
||||||
|
Score score = scoreTable.get(i);
|
||||||
|
int tzOffset = score.tz.getOffset(time) / 60_000;
|
||||||
|
if (tzOffset != offset) {
|
||||||
|
score.value += (int)((last - time) / 60_000) * (Math.abs(tzOffset - offset)) / 30;
|
||||||
|
}
|
||||||
|
int j = i + 1;
|
||||||
|
while (j < scoreTable.size() && score.value > scoreTable.get(j).value) {
|
||||||
|
scoreTable.set(j - 1, scoreTable.get(j));
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
scoreTable.set(j - 1, score);
|
||||||
|
}
|
||||||
|
|
||||||
|
last = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
return scoreTable.get(0).tz;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Score {
|
||||||
|
DateTimeZone tz;
|
||||||
|
int value;
|
||||||
|
|
||||||
|
public Score(DateTimeZone tz) {
|
||||||
|
this.tz = tz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static TimeZoneResource getTimeZoneResource(String id) {
|
private static TimeZoneResource getTimeZoneResource(String id) {
|
||||||
String areaName;
|
String areaName;
|
||||||
String locationName;
|
String locationName;
|
||||||
|
@ -85,6 +180,9 @@ public class DateTimeZoneProvider {
|
||||||
return area.get(locationName);
|
return area.get(locationName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JSBody(params = "instant", script = "return new Date(instant).getTimezoneOffset();")
|
||||||
|
private static native int getNativeOffset(double instant);
|
||||||
|
|
||||||
@MetadataProvider(TimeZoneGenerator.class)
|
@MetadataProvider(TimeZoneGenerator.class)
|
||||||
private static native ResourceMap<ResourceMap<TimeZoneResource>> getResource();
|
private static native ResourceMap<ResourceMap<TimeZoneResource>> getResource();
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,7 +120,7 @@ public abstract class StorableDateTimeZone extends DateTimeZone {
|
||||||
|
|
||||||
public static StorableDateTimeZone read(String id, String text) {
|
public static StorableDateTimeZone read(String id, String text) {
|
||||||
CharFlow flow = new CharFlow(text.toCharArray());
|
CharFlow flow = new CharFlow(text.toCharArray());
|
||||||
int type = Base46.decode(flow);
|
int type = Base46.decodeUnsigned(flow);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case PRECALCULATED:
|
case PRECALCULATED:
|
||||||
return PrecalculatedZone.readZone(id, flow);
|
return PrecalculatedZone.readZone(id, flow);
|
||||||
|
|
|
@ -30,7 +30,7 @@ public class LongNativeGenerator implements Generator {
|
||||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||||
switch (methodRef.getName()) {
|
switch (methodRef.getName()) {
|
||||||
case "compare":
|
case "compare":
|
||||||
writer.append("Long_compare(").append(context.getParameterName(1)).append(", ")
|
writer.append("return Long_compare(").append(context.getParameterName(1)).append(", ")
|
||||||
.append(context.getParameterName(2)).append(");").softNewLine();
|
.append(context.getParameterName(2)).append(");").softNewLine();
|
||||||
break;
|
break;
|
||||||
case "hashCode":
|
case "hashCode":
|
||||||
|
|
|
@ -205,7 +205,6 @@ public class TPriorityQueue<E> extends TAbstractQueue<E> implements TSerializabl
|
||||||
private void removeAt(int index) {
|
private void removeAt(int index) {
|
||||||
++version;
|
++version;
|
||||||
Object item = data[size - 1];
|
Object item = data[size - 1];
|
||||||
data[--size] = null;
|
|
||||||
while (true) {
|
while (true) {
|
||||||
int left = index * 2 + 1;
|
int left = index * 2 + 1;
|
||||||
int right = left + 1;
|
int right = left + 1;
|
||||||
|
@ -224,6 +223,7 @@ public class TPriorityQueue<E> extends TAbstractQueue<E> implements TSerializabl
|
||||||
index = next;
|
index = next;
|
||||||
}
|
}
|
||||||
data[index] = item;
|
data[index] = item;
|
||||||
|
data[--size] = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ensureCapacity(int capacity) {
|
private void ensureCapacity(int capacity) {
|
||||||
|
|
|
@ -16,5 +16,6 @@ public class TimeZoneTest {
|
||||||
assertEquals(1414274399999L, tz.previousTransition(1431781727159L));
|
assertEquals(1414274399999L, tz.previousTransition(1431781727159L));
|
||||||
assertEquals(1301183999999L, tz.previousTransition(1414274399999L));
|
assertEquals(1301183999999L, tz.previousTransition(1414274399999L));
|
||||||
assertEquals(1288479599999L, tz.previousTransition(1301183999999L));
|
assertEquals(1288479599999L, tz.previousTransition(1301183999999L));
|
||||||
|
System.out.println(DateTimeZoneProvider.detectTimezone().getID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user