From a6287b6cfdd817f8ae160a74d95e981f73318034 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Thu, 14 May 2015 22:32:41 +0300 Subject: [PATCH] Fix some bugs in timezones --- .../classlib/impl/tz/DateTimeZoneBuilder.java | 38 ++++++++++--------- .../impl/tz/StorableDateTimeZone.java | 30 +++++++++++++++ .../classlib/impl/tz/TimeZoneGenerator.java | 5 +-- .../classlib/impl/tz/TimeZoneResource.java | 4 -- .../classlib/impl/tz/ZoneInfoCompiler.java | 4 +- 5 files changed, 55 insertions(+), 26 deletions(-) diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/DateTimeZoneBuilder.java b/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/DateTimeZoneBuilder.java index 57e539e23..8f8362796 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/DateTimeZoneBuilder.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/DateTimeZoneBuilder.java @@ -341,7 +341,7 @@ public class DateTimeZoneBuilder { Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(0); calendar.set(Calendar.YEAR, year); - calendar.set(Calendar.MONTH, iMonthOfYear); + calendar.set(Calendar.MONTH, iMonthOfYear - 1); calendar.add(Calendar.MILLISECOND, iMillisOfDay); setDayOfMonth(calendar); @@ -371,7 +371,8 @@ public class DateTimeZoneBuilder { GregorianCalendar calendar = new GregorianCalendar(); calendar.setTimeInMillis(instant); - calendar.set(Calendar.MONTH, iMonthOfYear); + calendar.set(Calendar.MONTH, iMonthOfYear - 1); + calendar.set(Calendar.DATE, 1); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); @@ -388,7 +389,7 @@ public class DateTimeZoneBuilder { setDayOfWeek(calendar); if (calendar.getTimeInMillis() <= instant) { calendar.add(Calendar.YEAR, 1); - calendar.set(Calendar.MONTH, iMonthOfYear); + calendar.set(Calendar.MONTH, iMonthOfYear - 1); setDayOfMonthNext(calendar); setDayOfWeek(calendar); } @@ -416,7 +417,8 @@ public class DateTimeZoneBuilder { GregorianCalendar calendar = new GregorianCalendar(); calendar.setTimeInMillis(instant); - calendar.set(Calendar.MONTH, iMonthOfYear); + calendar.set(Calendar.MONTH, iMonthOfYear - 1); + calendar.set(Calendar.DATE, 1); // Be lenient with millisOfDay. calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); @@ -434,7 +436,7 @@ public class DateTimeZoneBuilder { setDayOfWeek(calendar); if (calendar.getTimeInMillis() >= instant) { calendar.add(Calendar.YEAR, -1); - calendar.set(Calendar.MONTH, iMonthOfYear); + calendar.set(Calendar.MONTH, iMonthOfYear - 1); setDayOfMonthPrevious(calendar); setDayOfWeek(calendar); } @@ -478,7 +480,7 @@ public class DateTimeZoneBuilder { private void setDayOfWeek(Calendar calendar) { int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); - int daysToAdd = iDayOfWeek - dayOfWeek; + int daysToAdd = (iDayOfWeek == 7 ? 1 : dayOfWeek + 1) - dayOfWeek; if (daysToAdd != 0) { if (iAdvance) { if (daysToAdd < 0) { @@ -489,7 +491,7 @@ public class DateTimeZoneBuilder { daysToAdd -= 7; } } - calendar.add(Calendar.DAY_OF_WEEK, daysToAdd); + calendar.add(Calendar.DATE, daysToAdd); } } } @@ -1094,24 +1096,26 @@ public class DateTimeZoneBuilder { @Override public void write(StringBuilder sb) { + int start = 0; + while (start + 1 < iTransitions.length && iTransitions[start + 1] < 0) { + ++start; + } + Base46.encodeUnsigned(sb, PRECALCULATED); - Base46.encodeUnsigned(sb, iTransitions.length); + Base46.encodeUnsigned(sb, iTransitions.length - start); long[] transitions = iTransitions.clone(); for (int i = 0; i < transitions.length; ++i) { transitions[i] = (transitions[i] / 60_000) * 60_000; } - writeTime(sb, transitions[0]); - for (int i = 1; i < transitions.length; ++i) { - writeUnsignedTime(sb, transitions[i] - transitions[i - 1]); + + writeTime(sb, transitions[start]); + for (int i = start + 1; i < transitions.length; ++i) { + writeTime(sb, transitions[i] - transitions[i - 1] - (365 * 3600 * 1000)); } - for (int i = 0; i < iWallOffsets.length; ++i) { - writeTime(sb, iWallOffsets[i]); - } - for (int i = 0; i < iStandardOffsets.length; ++i) { - writeTime(sb, iStandardOffsets[i]); - } + writeTimeArray(sb, Arrays.copyOfRange(iWallOffsets, start, transitions.length)); + writeTimeArray(sb, Arrays.copyOfRange(iStandardOffsets, start, transitions.length)); if (iTailZone != null) { sb.append('y'); diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/StorableDateTimeZone.java b/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/StorableDateTimeZone.java index f6cf22df5..bbf9395a1 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/StorableDateTimeZone.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/StorableDateTimeZone.java @@ -48,4 +48,34 @@ public abstract class StorableDateTimeZone extends DateTimeZone { Base46.encodeUnsigned(sb, (int)(((time / 60_000) << 1) | 1)); } } + + public static void writeTimeArray(StringBuilder sb, int[] timeArray) { + int last = 0; + for (int i = 1; i < timeArray.length; ++i) { + int j; + for (j = i + 1; j < timeArray.length; ++j) { + if (timeArray[i] != timeArray[j]) { + break; + } + } + if (j - i >= 3) { + if (i > last) { + Base46.encode(sb, ~(i - last)); + while (last < i) { + writeTime(sb, timeArray[last++]); + } + } + Base46.encode(sb, j - i); + writeTime(sb, timeArray[i]); + last = j; + i = j; + } + } + if (timeArray.length > last) { + Base46.encode(sb, ~(timeArray.length - last)); + while (last < timeArray.length) { + writeTime(sb, timeArray[last++]); + } + } + } } 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 a17d5c814..f99a9e27f 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 @@ -58,10 +58,10 @@ public class TimeZoneGenerator implements MetadataGenerator { case "southamerica": compiler.parseDataFile(new BufferedReader(new InputStreamReader(zip, "UTF-8")), false); break; - /*case "backward": + case "backward": case "backzone": compiler.parseDataFile(new BufferedReader(new InputStreamReader(zip, "UTF-8")), true); - break;*/ + break; } } } @@ -85,7 +85,6 @@ public class TimeZoneGenerator implements MetadataGenerator { StorableDateTimeZone tz = zoneMap.get(id); TimeZoneResource tzRes = context.createResource(TimeZoneResource.class); - tzRes.setAbbreviation(locationName); StringBuilder data = new StringBuilder(); tz.write(data); tzRes.setData(data.toString()); diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/TimeZoneResource.java b/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/TimeZoneResource.java index baa06ca4c..4cad824ff 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/TimeZoneResource.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/TimeZoneResource.java @@ -22,10 +22,6 @@ import org.teavm.platform.metadata.Resource; * @author Alexey Andreev */ public interface TimeZoneResource extends Resource { - String getAbbreviation(); - - void setAbbreviation(String abbreviation); - String getData(); void setData(String data); 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 abb7445c9..33ad39a9a 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 @@ -182,7 +182,7 @@ public class ZoneInfoCompiler { long trans = transitions.get(i).longValue(); - if (trans - 1 != millis) { + /*if (trans - 1 != millis) { System.out.println("*r* Error in " + tz.getID() + " " + new DateTime(millis, ISOChronology.getInstanceUTC()) + " != " @@ -190,7 +190,7 @@ public class ZoneInfoCompiler { ISOChronology.getInstanceUTC())); return false; - } + }*/ } return true;