Add time zones to calendar

This commit is contained in:
Alexey Andreev 2015-05-19 19:05:31 +04:00
parent a869ebb609
commit 912c72c490
5 changed files with 63 additions and 26 deletions

View File

@ -15,11 +15,7 @@
*/ */
package org.teavm.classlib.impl.tz; package org.teavm.classlib.impl.tz;
import java.util.ArrayList; import java.util.*;
import java.util.Arrays;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Iterator;
import org.teavm.classlib.impl.Base46; import org.teavm.classlib.impl.Base46;
import org.teavm.classlib.impl.CharFlow; import org.teavm.classlib.impl.CharFlow;
@ -69,6 +65,8 @@ import org.teavm.classlib.impl.CharFlow;
* @since 1.0 * @since 1.0
*/ */
public class DateTimeZoneBuilder { public class DateTimeZoneBuilder {
private static TimeZone GMT = TimeZone.getTimeZone("GMT+00:00");
private static StorableDateTimeZone buildFixedZone(String id, int wallOffset, int standardOffset) { private static StorableDateTimeZone buildFixedZone(String id, int wallOffset, int standardOffset) {
return new FixedDateTimeZone(id, wallOffset, standardOffset); return new FixedDateTimeZone(id, wallOffset, standardOffset);
} }
@ -348,7 +346,7 @@ public class DateTimeZoneBuilder {
offset = 0; offset = 0;
} }
Calendar calendar = Calendar.getInstance(); Calendar calendar = Calendar.getInstance(GMT);
calendar.setTimeInMillis(0); calendar.setTimeInMillis(0);
calendar.set(Calendar.YEAR, year); calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, iMonthOfYear - 1); calendar.set(Calendar.MONTH, iMonthOfYear - 1);
@ -364,7 +362,7 @@ public class DateTimeZoneBuilder {
} }
// Convert from local time to UTC. // 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. // Convert from UTC to local time.
instant += offset; instant += offset;
GregorianCalendar calendar = new GregorianCalendar(); GregorianCalendar calendar = new GregorianCalendar(GMT);
calendar.setTimeInMillis(instant); calendar.setTimeInMillis(instant);
calendar.set(Calendar.MONTH, iMonthOfYear - 1); calendar.set(Calendar.MONTH, iMonthOfYear - 1);
calendar.set(Calendar.DATE, 1); calendar.set(Calendar.DATE, 1);
@ -395,13 +393,13 @@ public class DateTimeZoneBuilder {
setDayOfMonthNext(calendar); setDayOfMonthNext(calendar);
if (iDayOfWeek == 0) { if (iDayOfWeek == 0) {
if (calendar.getTimeInMillis() + calendar.get(Calendar.ZONE_OFFSET) <= instant) { if (calendar.getTimeInMillis() <= instant) {
calendar.add(Calendar.YEAR, 1); calendar.add(Calendar.YEAR, 1);
setDayOfMonthNext(calendar); setDayOfMonthNext(calendar);
} }
} else { } else {
setDayOfWeek(calendar); setDayOfWeek(calendar);
if (calendar.getTimeInMillis() + calendar.get(Calendar.ZONE_OFFSET) <= instant) { if (calendar.getTimeInMillis() <= instant) {
calendar.add(Calendar.YEAR, 1); calendar.add(Calendar.YEAR, 1);
calendar.set(Calendar.MONTH, iMonthOfYear - 1); calendar.set(Calendar.MONTH, iMonthOfYear - 1);
setDayOfMonthNext(calendar); setDayOfMonthNext(calendar);
@ -410,7 +408,7 @@ public class DateTimeZoneBuilder {
} }
// Convert from local time to UTC. // 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. // Convert from UTC to local time.
instant += offset; instant += offset;
GregorianCalendar calendar = new GregorianCalendar(); GregorianCalendar calendar = new GregorianCalendar(GMT);
calendar.setTimeInMillis(instant); calendar.setTimeInMillis(instant);
calendar.set(Calendar.MONTH, iMonthOfYear - 1); calendar.set(Calendar.MONTH, iMonthOfYear - 1);
calendar.set(Calendar.DATE, 1); calendar.set(Calendar.DATE, 1);
@ -442,13 +440,13 @@ public class DateTimeZoneBuilder {
setDayOfMonthPrevious(calendar); setDayOfMonthPrevious(calendar);
if (iDayOfWeek == 0) { if (iDayOfWeek == 0) {
if (calendar.getTimeInMillis() + calendar.get(Calendar.ZONE_OFFSET) >= instant) { if (calendar.getTimeInMillis() >= instant) {
calendar.add(Calendar.YEAR, -1); calendar.add(Calendar.YEAR, -1);
setDayOfMonthPrevious(calendar); setDayOfMonthPrevious(calendar);
} }
} else { } else {
setDayOfWeek(calendar); setDayOfWeek(calendar);
if (calendar.getTimeInMillis() + calendar.get(Calendar.ZONE_OFFSET) >= instant) { if (calendar.getTimeInMillis() >= instant) {
calendar.add(Calendar.YEAR, -1); calendar.add(Calendar.YEAR, -1);
calendar.set(Calendar.MONTH, iMonthOfYear - 1); calendar.set(Calendar.MONTH, iMonthOfYear - 1);
setDayOfMonthPrevious(calendar); setDayOfMonthPrevious(calendar);
@ -457,7 +455,7 @@ public class DateTimeZoneBuilder {
} }
// Convert from local time to UTC. // 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) { public long next(final long instant, int standardOffset, int saveMillis) {
Calendar calendar = Calendar.getInstance(); Calendar calendar = Calendar.getInstance(GMT);
final int wallOffset = standardOffset + saveMillis; final int wallOffset = standardOffset + saveMillis;
long testInstant = instant; long testInstant = instant;
@ -607,7 +605,7 @@ public class DateTimeZoneBuilder {
calendar.setTimeInMillis(0); calendar.setTimeInMillis(0);
calendar.set(Calendar.YEAR, iFromYear); calendar.set(Calendar.YEAR, iFromYear);
// First advance instant to start of from year. // 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 // Back off one millisecond to account for next recurrence
// being exactly at the beginning of the year. // being exactly at the beginning of the year.
testInstant -= 1; testInstant -= 1;
@ -846,7 +844,7 @@ public class DateTimeZoneBuilder {
} }
// Stop precalculating if year reaches some arbitrary limit. // Stop precalculating if year reaches some arbitrary limit.
Calendar c = Calendar.getInstance(); Calendar c = Calendar.getInstance(GMT);
c.setTimeInMillis(nextMillis); c.setTimeInMillis(nextMillis);
if (c.get(Calendar.YEAR) >= YEAR_LIMIT) { if (c.get(Calendar.YEAR) >= YEAR_LIMIT) {
return null; return null;

View File

@ -50,7 +50,7 @@ public class DateTimeZoneProvider {
} }
String data = res.getData(); String data = res.getData();
CharFlow flow = new CharFlow(data.toCharArray()); CharFlow flow = new CharFlow(data.toCharArray());
if (Base46.decode(flow) == StorableDateTimeZone.ALIAS) { if (Base46.decodeUnsigned(flow) == StorableDateTimeZone.ALIAS) {
String aliasId = data.substring(flow.pointer); String aliasId = data.substring(flow.pointer);
return new AliasDateTimeZone(id, getTimeZone(aliasId)); return new AliasDateTimeZone(id, getTimeZone(aliasId));
} else { } else {

View File

@ -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", "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=" }; "MINUTE=", "SECOND=", "MILLISECOND=", "ZONE_OFFSET=", "DST_OFFSET=" };
private TTimeZone zone;
private static int firstDayOfWeekCache = -1; private static int firstDayOfWeekCache = -1;
private static int minimalDaysInFirstWeekCache = -1; private static int minimalDaysInFirstWeekCache = -1;
private static TLocale cacheFor; private static TLocale cacheFor;
protected TCalendar() { 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]; fields = new int[FIELD_COUNT];
isSet = new boolean[FIELD_COUNT]; isSet = new boolean[FIELD_COUNT];
areFieldsSet = isTimeSet = false; areFieldsSet = isTimeSet = false;
@ -231,6 +242,7 @@ public abstract class TCalendar implements TSerializable, TCloneable, TComparabl
TCalendar clone = (TCalendar) super.clone(); TCalendar clone = (TCalendar) super.clone();
clone.fields = fields.clone(); clone.fields = fields.clone();
clone.isSet = isSet.clone(); clone.isSet = isSet.clone();
clone.zone = (TTimeZone)zone.clone();
return clone; return clone;
} catch (CloneNotSupportedException e) { } catch (CloneNotSupportedException e) {
return null; return null;
@ -263,7 +275,8 @@ public abstract class TCalendar implements TSerializable, TCloneable, TComparabl
TCalendar cal = (TCalendar) object; TCalendar cal = (TCalendar) object;
return getTimeInMillis() == cal.getTimeInMillis() && isLenient() == cal.isLenient() && return getTimeInMillis() == cal.getTimeInMillis() && isLenient() == cal.isLenient() &&
getFirstDayOfWeek() == cal.getFirstDayOfWeek() && getFirstDayOfWeek() == cal.getFirstDayOfWeek() &&
getMinimalDaysInFirstWeek() == cal.getMinimalDaysInFirstWeek(); getMinimalDaysInFirstWeek() == cal.getMinimalDaysInFirstWeek() &&
zone.equals(cal.zone);
} }
public int get(int field) { public int get(int field) {
@ -325,6 +338,14 @@ public abstract class TCalendar implements TSerializable, TCloneable, TComparabl
return new TGregorianCalendar(locale); 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 getLeastMaximum(int field);
abstract public int getMaximum(int field); abstract public int getMaximum(int field);
@ -347,6 +368,15 @@ public abstract class TCalendar implements TSerializable, TCloneable, TComparabl
return time; return time;
} }
public TTimeZone getTimeZone() {
return zone;
}
public void setTimeZone(TTimeZone timezone) {
zone = timezone;
areFieldsSet = false;
}
@Override @Override
public int hashCode() { public int hashCode() {
return (isLenient() ? 1237 : 1231) + getFirstDayOfWeek() + getMinimalDaysInFirstWeek(); return (isLenient() ? 1237 : 1231) + getFirstDayOfWeek() + getMinimalDaysInFirstWeek();

View File

@ -76,11 +76,20 @@ public class TGregorianCalendar extends TCalendar {
} }
public TGregorianCalendar(TLocale locale) { 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()); setTimeInMillis(System.currentTimeMillis());
} }
TGregorianCalendar(@SuppressWarnings("unused") boolean ignored) { TGregorianCalendar(@SuppressWarnings("unused") boolean ignored) {
super(TTimeZone.getDefault());
setFirstDayOfWeek(SUNDAY); setFirstDayOfWeek(SUNDAY);
setMinimalDaysInFirstWeek(1); setMinimalDaysInFirstWeek(1);
} }
@ -302,8 +311,8 @@ public class TGregorianCalendar extends TCalendar {
} }
} }
private static int getTimeZoneOffset(double time) { int getTimeZoneOffset(long localTime) {
return -TDate.getTimezoneOffset(time) * 1000 * 60; return getTimeZone().getOffset(localTime);
} }
@Override @Override

View File

@ -62,7 +62,7 @@ class TIANATimeZone extends TTimeZone {
@Override @Override
public boolean useDaylightTime() { public boolean useDaylightTime() {
return true; return underlyingZone.isFixed();
} }
@Override @Override