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;
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;

View File

@ -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 {

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",
"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();

View File

@ -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

View File

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