From dadc693c9ff25cf6b6a9ad811b0cc4d53f40da31 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Thu, 14 May 2015 18:38:30 +0400 Subject: [PATCH] Very first version of TeaVM time zone compiler --- .../classlib/impl/tz/TimeZoneGenerator.java | 124 +++++++----------- .../classlib/impl/tz/ZoneInfoCompiler.java | 8 +- .../org/teavm/classlib/java/lang/TClass.java | 2 +- .../org/teavm/classlib/impl/Base46Test.java | 1 - 4 files changed, 53 insertions(+), 82 deletions(-) diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/TimeZoneGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/TimeZoneGenerator.java index 87abbed84..a17d5c814 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/TimeZoneGenerator.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/TimeZoneGenerator.java @@ -15,8 +15,13 @@ */ package org.teavm.classlib.impl.tz; -import org.joda.time.DateTimeZone; -import org.teavm.classlib.impl.Base46; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; import org.teavm.model.MethodReference; import org.teavm.platform.metadata.MetadataGenerator; import org.teavm.platform.metadata.MetadataGeneratorContext; @@ -27,19 +32,49 @@ import org.teavm.platform.metadata.ResourceMap; * @author Alexey Andreev */ public class TimeZoneGenerator implements MetadataGenerator { - private static int[] divisors = { 60_000, 300_000, 1800_000, 3600_000 }; - public static int RESOLUTION_MINUTE = 0; - public static int RESOLUTION_5_MINUTES = 1; - public static int RESOLUTION_HALF_HOUR = 2; - public static int RESOLUTION_HOUR = 3; - + private static final String tzPath = "org/teavm/classlib/impl/tz/tzdata2015d.zip"; @Override public ResourceMap> generateMetadata( MetadataGeneratorContext context, MethodReference method) { ResourceMap> result = context.createResourceMap(); - for (String id : DateTimeZone.getAvailableIDs()) { + ZoneInfoCompiler compiler = new ZoneInfoCompiler(); + try (InputStream input = context.getClassLoader().getResourceAsStream(tzPath)) { + try (ZipInputStream zip = new ZipInputStream(input)) { + while (true) { + ZipEntry entry = zip.getNextEntry(); + if (entry == null) { + break; + } + switch (entry.getName().substring("tzdata2015d/".length())) { + case "africa": + case "antarctica": + case "asia": + case "australasia": + case "etcetera": + case "europe": + case "northamerica": + case "pacificnew": + case "southamerica": + compiler.parseDataFile(new BufferedReader(new InputStreamReader(zip, "UTF-8")), false); + break; + /*case "backward": + case "backzone": + compiler.parseDataFile(new BufferedReader(new InputStreamReader(zip, "UTF-8")), true); + break;*/ + } + } + } + } catch (IOException e) { + throw new RuntimeException("Error generating TimeZones", e); + } + + Map zoneMap = compiler.compile(); + for (String id : zoneMap.keySet()) { int sepIndex = id.indexOf('/'); + if (sepIndex < 0) { + continue; + } String areaName = id.substring(0, sepIndex); String locationName = id.substring(sepIndex + 1); ResourceMap area = result.get(areaName); @@ -48,78 +83,15 @@ public class TimeZoneGenerator implements MetadataGenerator { result.put(areaName, area); } - DateTimeZone tz = DateTimeZone.forID(id); + StorableDateTimeZone tz = zoneMap.get(id); TimeZoneResource tzRes = context.createResource(TimeZoneResource.class); tzRes.setAbbreviation(locationName); - tzRes.setData(encodeData(tz)); + StringBuilder data = new StringBuilder(); + tz.write(data); + tzRes.setData(data.toString()); area.put(locationName, tzRes); } return result; } - - public String encodeData(DateTimeZone tz) { - // Find resolution - int resolution = RESOLUTION_HOUR; - long current = 0; - long offset = tz.getOffset(0); - while (true) { - long next = tz.nextTransition(current); - if (next == current) { - break; - } - current = next; - - int nextOffset = tz.getOffset(next); - if (nextOffset == offset) { - continue; - } - - offset = nextOffset; - resolution = getResolution(resolution, current); - resolution = getResolution(resolution, offset); - if (resolution == 0) { - break; - } - } - - StringBuilder sb = new StringBuilder(); - Base46.encode(sb, resolution); - - current = 0; - offset = tz.getOffset(0); - int divisor = divisors[resolution]; - long last = 0; - long lastOffset = offset / divisor; - Base46.encode(sb, lastOffset); - while (true) { - long next = tz.nextTransition(current); - if (next == current) { - break; - } - current = next; - - int nextOffset = tz.getOffset(next); - if (nextOffset == offset) { - continue; - } - - offset = nextOffset; - long newTime = current / divisor; - long newOffset = offset / divisor; - Base46.encodeUnsigned(sb, newTime - last); - Base46.encode(sb, newOffset - lastOffset); - last = newTime; - lastOffset = newOffset; - } - - return sb.toString(); - } - - private int getResolution(int currentResolution, long value) { - while (currentResolution > 0 && value % divisors[currentResolution] != 0) { - --currentResolution; - } - return currentResolution; - } } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/ZoneInfoCompiler.java b/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/ZoneInfoCompiler.java index 3ff358357..abb7445c9 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/ZoneInfoCompiler.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/ZoneInfoCompiler.java @@ -237,8 +237,8 @@ public class ZoneInfoCompiler { String alias = iGoodLinks.get(i + 1); Zone sourceZone = sourceMap.get(baseId); if (sourceZone == null) { - throw new RuntimeException("Cannot find source zone '" + baseId + "' to link alias '" + - alias + "' to"); + /*throw new RuntimeException("Cannot find source zone '" + baseId + "' to link alias '" + + alias + "' to");*/ } else { DateTimeZoneBuilder builder = new DateTimeZoneBuilder(); sourceZone.addToBuilder(builder, iRuleSets); @@ -257,10 +257,10 @@ public class ZoneInfoCompiler { String alias = iBackLinks.get(i + 1); StorableDateTimeZone tz = map.get(id); if (tz == null) { - if (pass > 0) { + /*if (pass > 0) { throw new RuntimeException("Cannot find time zone '" + id + "' to link alias '" + alias + "' to"); - } + }*/ } else { map.put(alias, tz); } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java index 46be09ec6..6123109cc 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java @@ -174,7 +174,7 @@ public class TClass extends TObject { return forName(name); } - @SuppressWarnings({ "unchecked", "unused" }) + @SuppressWarnings({ "unchecked" }) public T newInstance() throws TInstantiationException, TIllegalAccessException { Object instance = Platform.newInstance(platformClass); if (instance == null) { diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/impl/Base46Test.java b/teavm-classlib/src/test/java/org/teavm/classlib/impl/Base46Test.java index ff04563a5..6120d8adb 100644 --- a/teavm-classlib/src/test/java/org/teavm/classlib/impl/Base46Test.java +++ b/teavm-classlib/src/test/java/org/teavm/classlib/impl/Base46Test.java @@ -29,7 +29,6 @@ public class Base46Test { for (int i = -65536; i <= 65536; ++i) { sb.setLength(0); Base46.encode(sb, i); - System.out.println(i + " - " + sb); CharFlow flow = new CharFlow(sb.toString().toCharArray()); int num = Base46.decode(flow); assertEquals(i, num);