mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-09 00:14: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;
|
||||
if (flow.characters[flow.pointer++] == 'y') {
|
||||
flow.pointer++;
|
||||
tailZone = DSTZone.readZone(id, flow);
|
||||
} else {
|
||||
tailZone = null;
|
||||
|
|
|
@ -16,11 +16,16 @@
|
|||
package org.teavm.classlib.impl.tz;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.PriorityQueue;
|
||||
import java.util.Set;
|
||||
import org.teavm.classlib.impl.Base46;
|
||||
import org.teavm.classlib.impl.CharFlow;
|
||||
import org.teavm.jso.JSBody;
|
||||
import org.teavm.platform.metadata.MetadataProvider;
|
||||
import org.teavm.platform.metadata.ResourceMap;
|
||||
|
||||
|
@ -67,6 +72,96 @@ public class DateTimeZoneProvider {
|
|||
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) {
|
||||
String areaName;
|
||||
String locationName;
|
||||
|
@ -85,6 +180,9 @@ public class DateTimeZoneProvider {
|
|||
return area.get(locationName);
|
||||
}
|
||||
|
||||
@JSBody(params = "instant", script = "return new Date(instant).getTimezoneOffset();")
|
||||
private static native int getNativeOffset(double instant);
|
||||
|
||||
@MetadataProvider(TimeZoneGenerator.class)
|
||||
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) {
|
||||
CharFlow flow = new CharFlow(text.toCharArray());
|
||||
int type = Base46.decode(flow);
|
||||
int type = Base46.decodeUnsigned(flow);
|
||||
switch (type) {
|
||||
case PRECALCULATED:
|
||||
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 {
|
||||
switch (methodRef.getName()) {
|
||||
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();
|
||||
break;
|
||||
case "hashCode":
|
||||
|
|
|
@ -205,7 +205,6 @@ public class TPriorityQueue<E> extends TAbstractQueue<E> implements TSerializabl
|
|||
private void removeAt(int index) {
|
||||
++version;
|
||||
Object item = data[size - 1];
|
||||
data[--size] = null;
|
||||
while (true) {
|
||||
int left = index * 2 + 1;
|
||||
int right = left + 1;
|
||||
|
@ -224,6 +223,7 @@ public class TPriorityQueue<E> extends TAbstractQueue<E> implements TSerializabl
|
|||
index = next;
|
||||
}
|
||||
data[index] = item;
|
||||
data[--size] = null;
|
||||
}
|
||||
|
||||
private void ensureCapacity(int capacity) {
|
||||
|
|
|
@ -16,5 +16,6 @@ public class TimeZoneTest {
|
|||
assertEquals(1414274399999L, tz.previousTransition(1431781727159L));
|
||||
assertEquals(1301183999999L, tz.previousTransition(1414274399999L));
|
||||
assertEquals(1288479599999L, tz.previousTransition(1301183999999L));
|
||||
System.out.println(DateTimeZoneProvider.detectTimezone().getID());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user