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 9ea54ca2d..e9a8f53f8 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 @@ -15,11 +15,7 @@ */ package org.teavm.classlib.impl.tz; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.GregorianCalendar; -import java.util.Iterator; +import java.util.*; import org.teavm.classlib.impl.Base46; import org.teavm.classlib.impl.CharFlow; @@ -69,6 +65,8 @@ import org.teavm.classlib.impl.CharFlow; * @since 1.0 */ public class DateTimeZoneBuilder { + private static TimeZone GMT = TimeZone.getTimeZone("GMT+00:00"); + private static StorableDateTimeZone buildFixedZone(String id, int wallOffset, int standardOffset) { return new FixedDateTimeZone(id, wallOffset, standardOffset); } @@ -348,7 +346,7 @@ public class DateTimeZoneBuilder { offset = 0; } - Calendar calendar = Calendar.getInstance(); + Calendar calendar = Calendar.getInstance(GMT); calendar.setTimeInMillis(0); calendar.set(Calendar.YEAR, year); calendar.set(Calendar.MONTH, iMonthOfYear - 1); @@ -364,7 +362,7 @@ public class DateTimeZoneBuilder { } // Convert from local time to UTC. - return calendar.getTimeInMillis() + calendar.get(Calendar.ZONE_OFFSET) - offset; + return calendar.getTimeInMillis() - offset; } /** @@ -383,7 +381,7 @@ public class DateTimeZoneBuilder { // Convert from UTC to local time. instant += offset; - GregorianCalendar calendar = new GregorianCalendar(); + GregorianCalendar calendar = new GregorianCalendar(GMT); calendar.setTimeInMillis(instant); calendar.set(Calendar.MONTH, iMonthOfYear - 1); calendar.set(Calendar.DATE, 1); @@ -395,13 +393,13 @@ public class DateTimeZoneBuilder { setDayOfMonthNext(calendar); if (iDayOfWeek == 0) { - if (calendar.getTimeInMillis() + calendar.get(Calendar.ZONE_OFFSET) <= instant) { + if (calendar.getTimeInMillis() <= instant) { calendar.add(Calendar.YEAR, 1); setDayOfMonthNext(calendar); } } else { setDayOfWeek(calendar); - if (calendar.getTimeInMillis() + calendar.get(Calendar.ZONE_OFFSET) <= instant) { + if (calendar.getTimeInMillis() <= instant) { calendar.add(Calendar.YEAR, 1); calendar.set(Calendar.MONTH, iMonthOfYear - 1); setDayOfMonthNext(calendar); @@ -410,7 +408,7 @@ public class DateTimeZoneBuilder { } // Convert from local time to UTC. - return calendar.getTimeInMillis() + calendar.get(Calendar.ZONE_OFFSET) - offset; + return calendar.getTimeInMillis() - offset; } /** @@ -429,7 +427,7 @@ public class DateTimeZoneBuilder { // Convert from UTC to local time. instant += offset; - GregorianCalendar calendar = new GregorianCalendar(); + GregorianCalendar calendar = new GregorianCalendar(GMT); calendar.setTimeInMillis(instant); calendar.set(Calendar.MONTH, iMonthOfYear - 1); calendar.set(Calendar.DATE, 1); @@ -442,13 +440,13 @@ public class DateTimeZoneBuilder { setDayOfMonthPrevious(calendar); if (iDayOfWeek == 0) { - if (calendar.getTimeInMillis() + calendar.get(Calendar.ZONE_OFFSET) >= instant) { + if (calendar.getTimeInMillis() >= instant) { calendar.add(Calendar.YEAR, -1); setDayOfMonthPrevious(calendar); } } else { setDayOfWeek(calendar); - if (calendar.getTimeInMillis() + calendar.get(Calendar.ZONE_OFFSET) >= instant) { + if (calendar.getTimeInMillis() >= instant) { calendar.add(Calendar.YEAR, -1); calendar.set(Calendar.MONTH, iMonthOfYear - 1); setDayOfMonthPrevious(calendar); @@ -457,7 +455,7 @@ public class DateTimeZoneBuilder { } // Convert from local time to UTC. - return calendar.getTimeInMillis() + calendar.get(Calendar.ZONE_OFFSET) - offset; + return calendar.getTimeInMillis() - offset; } /** @@ -591,7 +589,7 @@ public class DateTimeZoneBuilder { } public long next(final long instant, int standardOffset, int saveMillis) { - Calendar calendar = Calendar.getInstance(); + Calendar calendar = Calendar.getInstance(GMT); final int wallOffset = standardOffset + saveMillis; long testInstant = instant; @@ -607,7 +605,7 @@ public class DateTimeZoneBuilder { calendar.setTimeInMillis(0); calendar.set(Calendar.YEAR, iFromYear); // First advance instant to start of from year. - testInstant = calendar.getTimeInMillis() + calendar.get(Calendar.ZONE_OFFSET) - wallOffset; + testInstant = calendar.getTimeInMillis() - wallOffset; // Back off one millisecond to account for next recurrence // being exactly at the beginning of the year. testInstant -= 1; @@ -846,7 +844,7 @@ public class DateTimeZoneBuilder { } // Stop precalculating if year reaches some arbitrary limit. - Calendar c = Calendar.getInstance(); + Calendar c = Calendar.getInstance(GMT); c.setTimeInMillis(nextMillis); if (c.get(Calendar.YEAR) >= YEAR_LIMIT) { return null; diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/DateTimeZoneProvider.java b/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/DateTimeZoneProvider.java index a4d300a5a..a7c4b554f 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/DateTimeZoneProvider.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/DateTimeZoneProvider.java @@ -50,7 +50,7 @@ public class DateTimeZoneProvider { } String data = res.getData(); CharFlow flow = new CharFlow(data.toCharArray()); - if (Base46.decode(flow) == StorableDateTimeZone.ALIAS) { + if (Base46.decodeUnsigned(flow) == StorableDateTimeZone.ALIAS) { String aliasId = data.substring(flow.pointer); return new AliasDateTimeZone(id, getTimeZone(aliasId)); } else { diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TCalendar.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TCalendar.java index e971d771f..4a0c27dab 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TCalendar.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TCalendar.java @@ -146,15 +146,26 @@ public abstract class TCalendar implements TSerializable, TCloneable, TComparabl "DAY_OF_MONTH=", "DAY_OF_YEAR=", "DAY_OF_WEEK=", "DAY_OF_WEEK_IN_MONTH=", "AM_PM=", "HOUR=", "HOUR_OF_DAY", "MINUTE=", "SECOND=", "MILLISECOND=", "ZONE_OFFSET=", "DST_OFFSET=" }; + private TTimeZone zone; + private static int firstDayOfWeekCache = -1; private static int minimalDaysInFirstWeekCache = -1; private static TLocale cacheFor; protected TCalendar() { - this(TLocale.getDefault()); + this(TTimeZone.getDefault(), TLocale.getDefault()); } - protected TCalendar(TLocale locale) { + TCalendar(TTimeZone timezone) { + fields = new int[FIELD_COUNT]; + isSet = new boolean[FIELD_COUNT]; + areFieldsSet = isTimeSet = false; + setLenient(true); + setTimeZone(timezone); + } + + protected TCalendar(TTimeZone timezone, TLocale locale) { + this(timezone); fields = new int[FIELD_COUNT]; isSet = new boolean[FIELD_COUNT]; areFieldsSet = isTimeSet = false; @@ -231,6 +242,7 @@ public abstract class TCalendar implements TSerializable, TCloneable, TComparabl TCalendar clone = (TCalendar) super.clone(); clone.fields = fields.clone(); clone.isSet = isSet.clone(); + clone.zone = (TTimeZone)zone.clone(); return clone; } catch (CloneNotSupportedException e) { return null; @@ -263,7 +275,8 @@ public abstract class TCalendar implements TSerializable, TCloneable, TComparabl TCalendar cal = (TCalendar) object; return getTimeInMillis() == cal.getTimeInMillis() && isLenient() == cal.isLenient() && getFirstDayOfWeek() == cal.getFirstDayOfWeek() && - getMinimalDaysInFirstWeek() == cal.getMinimalDaysInFirstWeek(); + getMinimalDaysInFirstWeek() == cal.getMinimalDaysInFirstWeek() && + zone.equals(cal.zone); } public int get(int field) { @@ -325,6 +338,14 @@ public abstract class TCalendar implements TSerializable, TCloneable, TComparabl return new TGregorianCalendar(locale); } + public static TCalendar getInstance(TTimeZone timezone) { + return new TGregorianCalendar(timezone); + } + + public static TCalendar getInstance(TTimeZone timezone, TLocale locale) { + return new TGregorianCalendar(timezone, locale); + } + abstract public int getLeastMaximum(int field); abstract public int getMaximum(int field); @@ -347,6 +368,15 @@ public abstract class TCalendar implements TSerializable, TCloneable, TComparabl return time; } + public TTimeZone getTimeZone() { + return zone; + } + + public void setTimeZone(TTimeZone timezone) { + zone = timezone; + areFieldsSet = false; + } + @Override public int hashCode() { return (isLenient() ? 1237 : 1231) + getFirstDayOfWeek() + getMinimalDaysInFirstWeek(); diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TGregorianCalendar.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TGregorianCalendar.java index 3159017e4..46f9b61cb 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TGregorianCalendar.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TGregorianCalendar.java @@ -76,11 +76,20 @@ public class TGregorianCalendar extends TCalendar { } public TGregorianCalendar(TLocale locale) { - super(locale); + this(TTimeZone.getDefault(), locale); + } + + public TGregorianCalendar(TTimeZone timezone) { + this(timezone, TLocale.getDefault()); + } + + public TGregorianCalendar(TTimeZone timezone, TLocale locale) { + super(timezone, locale); setTimeInMillis(System.currentTimeMillis()); } TGregorianCalendar(@SuppressWarnings("unused") boolean ignored) { + super(TTimeZone.getDefault()); setFirstDayOfWeek(SUNDAY); setMinimalDaysInFirstWeek(1); } @@ -302,8 +311,8 @@ public class TGregorianCalendar extends TCalendar { } } - private static int getTimeZoneOffset(double time) { - return -TDate.getTimezoneOffset(time) * 1000 * 60; + int getTimeZoneOffset(long localTime) { + return getTimeZone().getOffset(localTime); } @Override diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TIANATimeZone.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TIANATimeZone.java index e6eb6e7f3..6c56f6415 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TIANATimeZone.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TIANATimeZone.java @@ -62,7 +62,7 @@ class TIANATimeZone extends TTimeZone { @Override public boolean useDaylightTime() { - return true; + return underlyingZone.isFixed(); } @Override