Merge branch 'add_timezone' of https://github.com/shannah/teavm into shannah-add_timezone

This commit is contained in:
Alexey Andreev 2015-05-19 19:43:15 +03:00
commit d11f59cd4d
12 changed files with 3269 additions and 10 deletions

View File

@ -0,0 +1,64 @@
/*
* Copyright 2015 Steve Hannah.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.classlib.java.lang;
/**
* A dummy class for compatibility. Currently these methods don't actually
* do anything.
* @author shannah
*/
public class TRuntime {
private static final TRuntime instance = new TRuntime();
/**
* Terminates the currently running Java application. This method never returns normally.
* The argument serves as a status code; by convention, a nonzero status code indicates abnormal termination.
*/
public void exit(int status){
}
/**
* Returns the amount of free memory in the system. Calling the gc method may result in increasing the value returned by freeMemory.
*/
public long freeMemory(){
return Integer.MAX_VALUE;
}
/**
* Runs the garbage collector. Calling this method suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse. When control returns from the method call, the Java Virtual Machine has made its best effort to recycle all discarded objects.
* The name gc stands for "garbage collector". The Java Virtual Machine performs this recycling process automatically as needed even if the gc method is not invoked explicitly.
* The method System.gc() is the conventional and convenient means of invoking this method.
*/
public void gc(){
}
/**
* Returns the runtime object associated with the current Java application. Most of the methods of class Runtime are instance methods and must be invoked with respect to the current runtime object.
*/
public static TRuntime getRuntime(){
return instance;
}
/**
* Returns the total amount of memory in the Java Virtual Machine. The value returned by this method may vary over time, depending on the host environment.
* Note that the amount of memory required to hold an object of any given type may be implementation-dependent.
*/
public long totalMemory(){
return Integer.MAX_VALUE;
}
}

View File

@ -141,6 +141,9 @@ public abstract class TCalendar implements TSerializable, TCloneable, TComparabl
public static final int AM = 0; public static final int AM = 0;
public static final int PM = 1; public static final int PM = 1;
private TTimeZone zone;
private static String[] fieldNames = { "ERA=", "YEAR=", "MONTH=", "WEEK_OF_YEAR=", "WEEK_OF_MONTH=", private static String[] fieldNames = { "ERA=", "YEAR=", "MONTH=", "WEEK_OF_YEAR=", "WEEK_OF_MONTH=",
"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",
@ -151,6 +154,7 @@ public abstract class TCalendar implements TSerializable, TCloneable, TComparabl
} }
protected TCalendar(TLocale locale) { protected TCalendar(TLocale locale) {
zone = TTimeZone.getDefault();
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;
@ -310,6 +314,17 @@ public abstract class TCalendar implements TSerializable, TCloneable, TComparabl
public static TCalendar getInstance(TLocale locale) { public static TCalendar getInstance(TLocale locale) {
return new TGregorianCalendar(locale); return new TGregorianCalendar(locale);
} }
/**
* Gets a calendar using the specified time zone.
*/
public static TCalendar getInstance(TTimeZone zone) {
return new TGregorianCalendar(zone);
}
public static TCalendar getInstance(TTimeZone zone, TLocale locale) {
return new TGregorianCalendar(zone, locale);
}
abstract public int getLeastMaximum(int field); abstract public int getLeastMaximum(int field);
@ -332,6 +347,13 @@ public abstract class TCalendar implements TSerializable, TCloneable, TComparabl
} }
return time; return time;
} }
/**
* Gets the time zone.
*/
public TTimeZone getTimeZone() {
return zone;
}
@Override @Override
public int hashCode() { public int hashCode() {
@ -374,7 +396,7 @@ public abstract class TCalendar implements TSerializable, TCloneable, TComparabl
lastTimeFieldSet = HOUR; lastTimeFieldSet = HOUR;
} }
} }
public final void set(int year, int month, int day) { public final void set(int year, int month, int day) {
set(YEAR, year); set(YEAR, year);
set(MONTH, month); set(MONTH, month);
@ -407,6 +429,14 @@ public abstract class TCalendar implements TSerializable, TCloneable, TComparabl
public final void setTime(TDate date) { public final void setTime(TDate date) {
setTimeInMillis(date.getTime()); setTimeInMillis(date.getTime());
} }
/**
* Sets the time zone with the given time zone value.
*/
public void setTimeZone(TTimeZone value) {
zone = value;
areFieldsSet = false;
}
public void setTimeInMillis(long milliseconds) { public void setTimeInMillis(long milliseconds) {
if (!isTimeSet || !areFieldsSet || time != milliseconds) { if (!isTimeSet || !areFieldsSet || time != milliseconds) {

View File

@ -15,6 +15,7 @@
*/ */
package org.teavm.classlib.java.util; package org.teavm.classlib.java.util;
import java.util.TimeZone;
import org.teavm.classlib.java.lang.TComparable; import org.teavm.classlib.java.lang.TComparable;
import org.teavm.classlib.java.lang.TSystem; import org.teavm.classlib.java.lang.TSystem;
import org.teavm.dependency.PluggableDependency; import org.teavm.dependency.PluggableDependency;
@ -51,6 +52,7 @@ public class TDate implements TComparable<TDate> {
@Deprecated @Deprecated
public TDate(int year, int month, int date, int hrs, int min, int sec) { public TDate(int year, int month, int date, int hrs, int min, int sec) {
this((long)buildNumericTime(year, month, date, hrs, min, sec)); this((long)buildNumericTime(year, month, date, hrs, min, sec));
setFullYear(value, year+1900);
} }
public TDate(String s) { public TDate(String s) {
@ -78,12 +80,12 @@ public class TDate implements TComparable<TDate> {
@Deprecated @Deprecated
public int getYear() { public int getYear() {
return getFullYear(value); return getFullYear(value)-1900;
} }
@Deprecated @Deprecated
public void setYear(int year) { public void setYear(int year) {
this.value = (long)setFullYear(value, year); this.value = (long)setFullYear(value, year+1900);
} }
@Deprecated @Deprecated
@ -193,7 +195,8 @@ public class TDate implements TComparable<TDate> {
@Deprecated @Deprecated
public int getTimezoneOffset() { public int getTimezoneOffset() {
return getTimezoneOffset(value); //return getTimezoneOffset(value);
return -TimeZone.getDefault().getOffset(value) / (1000*60);
} }
@GeneratedBy(DateNativeGenerator.class) @GeneratedBy(DateNativeGenerator.class)

View File

@ -18,6 +18,7 @@
package org.teavm.classlib.java.util; package org.teavm.classlib.java.util;
public class TGregorianCalendar extends TCalendar { public class TGregorianCalendar extends TCalendar {
public static final int BC = 0; public static final int BC = 0;
public static final int AD = 1; public static final int AD = 1;
@ -57,6 +58,10 @@ public class TGregorianCalendar extends TCalendar {
public TGregorianCalendar() { public TGregorianCalendar() {
this(TLocale.getDefault()); this(TLocale.getDefault());
} }
public TGregorianCalendar(TTimeZone zone) {
this(zone, TLocale.getDefault());
}
public TGregorianCalendar(int year, int month, int day) { public TGregorianCalendar(int year, int month, int day) {
set(year, month, day); set(year, month, day);
@ -79,6 +84,11 @@ public class TGregorianCalendar extends TCalendar {
super(locale); super(locale);
setTimeInMillis(System.currentTimeMillis()); setTimeInMillis(System.currentTimeMillis());
} }
public TGregorianCalendar(TTimeZone zone, TLocale locale) {
this(locale);
setTimeZone(zone);
}
TGregorianCalendar(@SuppressWarnings("unused") boolean ignored) { TGregorianCalendar(@SuppressWarnings("unused") boolean ignored) {
setFirstDayOfWeek(SUNDAY); setFirstDayOfWeek(SUNDAY);
@ -302,10 +312,60 @@ public class TGregorianCalendar extends TCalendar {
} }
} }
private static int getTimeZoneOffset(double time) { private int getTimeZoneOffset(double time) {
return -TDate.getTimezoneOffset(time) * 1000 * 60; //return -TDate.getTimezoneOffset(time) * 1000 * 60;
return getOffset((long)time);
} }
private int getOffset(long localTime) {
TTimeZone timeZone = getTimeZone();
if (!timeZone.useDaylightTime()) {
return timeZone.getRawOffset();
}
long dayCount = localTime / 86400000;
int millis = (int) (localTime % 86400000);
if (millis < 0) {
millis += 86400000;
dayCount--;
}
int year = 1970;
long days = dayCount;
if (localTime < gregorianCutover) {
days -= julianSkew;
}
int approxYears;
while ((approxYears = (int) (days / 365)) != 0) {
year = year + approxYears;
days = dayCount - daysFromBaseYear(year);
}
if (days < 0) {
year = year - 1;
days = days + 365 + (isLeapYear(year) ? 1 : 0);
if (year == changeYear && localTime < gregorianCutover) {
days -= julianError();
}
}
if (year <= 0) {
return timeZone.getRawOffset();
}
int dayOfYear = (int) days + 1;
int month = dayOfYear / 32;
boolean leapYear = isLeapYear(year);
int date = dayOfYear - daysInYear(leapYear, month);
if (date > daysInMonth(leapYear, month)) {
date -= daysInMonth(leapYear, month);
month++;
}
int dayOfWeek = mod7(dayCount - 3) + 1;
int offset = timeZone.getOffset(AD, year, month, date, dayOfWeek,
millis);
return offset;
}
@Override @Override
protected void computeFields() { protected void computeFields() {
int zoneOffset = getTimeZoneOffset(time); int zoneOffset = getTimeZoneOffset(time);

View File

@ -0,0 +1,927 @@
/*
* Copyright 2015 Steve Hannah.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.classlib.java.util;
/**
* {@code SimpleTimeZone} is a concrete subclass of {@code TimeZone}
* that represents a time zone for use with a Gregorian calendar. This class
* does not handle historical changes.
* <p>
* Use a negative value for {@code dayOfWeekInMonth} to indicate that
* {@code SimpleTimeZone} should count from the end of the month
* backwards. For example, Daylight Savings Time ends at the last
* (dayOfWeekInMonth = -1) Sunday in October, at 2 AM in standard time.
*
* @see Calendar
* @see GregorianCalendar
* @see TimeZone
*/
public class TSimpleTimeZone extends TTimeZone {
private int rawOffset;
private int startYear, startMonth, startDay, startDayOfWeek, startTime;
private int endMonth, endDay, endDayOfWeek, endTime;
private int startMode, endMode;
private static final int DOM_MODE = 1, DOW_IN_MONTH_MODE = 2,
DOW_GE_DOM_MODE = 3, DOW_LE_DOM_MODE = 4;
/**
* The constant for representing a start or end time in GMT time mode.
*/
public static final int UTC_TIME = 2;
/**
* The constant for representing a start or end time in standard local time mode,
* based on timezone's raw offset from GMT; does not include Daylight
* savings.
*/
public static final int STANDARD_TIME = 1;
/**
* The constant for representing a start or end time in local wall clock time
* mode, based on timezone's adjusted offset from GMT; includes
* Daylight savings.
*/
public static final int WALL_TIME = 0;
private boolean useDaylight;
private int dstSavings = 3600000;
private static final int MILLIS_PER_SECOND = 1000;
private static final int MILLIS_PER_MINUTE = 60*MILLIS_PER_SECOND;
private static final int MILLIS_PER_HOUR = 60*MILLIS_PER_MINUTE;
// January 1, 1 CE Gregorian
private static final int JULIAN_1_CE = 1721426;
// January 1, 1970 CE Gregorian
private static final int JULIAN_1970_CE = 2440588;
private static final int[] MONTH_LENGTH = new int[] {
31,28,31,30,31,30,31,31,30,31,30,31,
31,29,31,30,31,30,31,31,30,31,30,31
};
private static final int[] DAYS_BEFORE = new int[] {
0,31,59,90,120,151,181,212,243,273,304,334,
0,31,60,91,121,152,182,213,244,274,305,335 };
/**
* Return the number of days in the given month.
* @param year Gregorian year, with 0 == 1 BCE, -1 == 2 BCE, etc.
* @param month 0-based month, with 0==Jan
* @return the number of days in the given month
*/
private static final int monthLength(int year, int month) {
return MONTH_LENGTH[month + (isLeapYear(year) ? 12 : 0)];
}
/**
* Constructs a {@code SimpleTimeZone} with the given base time zone offset from GMT
* and time zone ID. Timezone IDs can be obtained from
* {@code TimeZone.getAvailableIDs}. Normally you should use {@code TimeZone.getDefault} to
* construct a {@code TimeZone}.
*
* @param offset
* the given base time zone offset to GMT.
* @param name
* the time zone ID which is obtained from
* {@code TimeZone.getAvailableIDs}.
*/
public TSimpleTimeZone(int offset, final String name) {
setID(name);
rawOffset = offset;
}
/**
* Constructs a {@code SimpleTimeZone} with the given base time zone offset from GMT,
* time zone ID, and times to start and end the daylight savings time. Timezone IDs can
* be obtained from {@code TimeZone.getAvailableIDs}. Normally you should use
* {@code TimeZone.getDefault} to create a {@code TimeZone}. For a time zone that does not
* use daylight saving time, do not use this constructor; instead you should
* use {@code SimpleTimeZone(rawOffset, ID)}.
* <p>
* By default, this constructor specifies day-of-week-in-month rules. That
* is, if the {@code startDay} is 1, and the {@code startDayOfWeek} is {@code SUNDAY}, then this
* indicates the first Sunday in the {@code startMonth}. A {@code startDay} of -1 likewise
* indicates the last Sunday. However, by using negative or zero values for
* certain parameters, other types of rules can be specified.
* <p>
* Day of month: To specify an exact day of the month, such as March 1, set
* {@code startDayOfWeek} to zero.
* <p>
* Day of week after day of month: To specify the first day of the week
* occurring on or after an exact day of the month, make the day of the week
* negative. For example, if {@code startDay} is 5 and {@code startDayOfWeek} is {@code -MONDAY},
* this indicates the first Monday on or after the 5th day of the
* {@code startMonth}.
* <p>
* Day of week before day of month: To specify the last day of the week
* occurring on or before an exact day of the month, make the day of the
* week and the day of the month negative. For example, if {@code startDay} is {@code -21}
* and {@code startDayOfWeek} is {@code -WEDNESDAY}, this indicates the last Wednesday on or
* before the 21st of the {@code startMonth}.
* <p>
* The above examples refer to the {@code startMonth}, {@code startDay}, and {@code startDayOfWeek};
* the same applies for the {@code endMonth}, {@code endDay}, and {@code endDayOfWeek}.
* <p>
* The daylight savings time difference is set to the default value: one hour.
*
* @param offset
* the given base time zone offset to GMT.
* @param name
* the time zone ID which is obtained from
* {@code TimeZone.getAvailableIDs}.
* @param startMonth
* the daylight savings starting month. The month indexing is 0-based. eg, 0
* for January.
* @param startDay
* the daylight savings starting day-of-week-in-month. Please see
* the member description for an example.
* @param startDayOfWeek
* the daylight savings starting day-of-week. Please see the
* member description for an example.
* @param startTime
* the daylight savings starting time in local wall time, which
* is standard time in this case. Please see the member
* description for an example.
* @param endMonth
* the daylight savings ending month. The month indexing is 0-based. eg, 0 for
* January.
* @param endDay
* the daylight savings ending day-of-week-in-month. Please see
* the member description for an example.
* @param endDayOfWeek
* the daylight savings ending day-of-week. Please see the member
* description for an example.
* @param endTime
* the daylight savings ending time in local wall time, which is
* daylight time in this case. Please see the member description
* for an example.
* @throws IllegalArgumentException
* if the month, day, dayOfWeek, or time parameters are out of
* range for the start or end rule.
*/
public TSimpleTimeZone(int offset, String name, int startMonth,
int startDay, int startDayOfWeek, int startTime, int endMonth,
int endDay, int endDayOfWeek, int endTime) {
this(offset, name, startMonth, startDay, startDayOfWeek, startTime,
endMonth, endDay, endDayOfWeek, endTime, 3600000);
}
/**
* Constructs a {@code SimpleTimeZone} with the given base time zone offset from GMT,
* time zone ID, times to start and end the daylight savings time, and
* the daylight savings time difference in milliseconds.
*
* @param offset
* the given base time zone offset to GMT.
* @param name
* the time zone ID which is obtained from
* {@code TimeZone.getAvailableIDs}.
* @param startMonth
* the daylight savings starting month. Month is 0-based. eg, 0
* for January.
* @param startDay
* the daylight savings starting day-of-week-in-month. Please see
* the description of {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)} for an example.
* @param startDayOfWeek
* the daylight savings starting day-of-week. Please see the
* description of {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)} for an example.
* @param startTime
* The daylight savings starting time in local wall time, which
* is standard time in this case. Please see the description of
* {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)} for an example.
* @param endMonth
* the daylight savings ending month. Month is 0-based. eg, 0 for
* January.
* @param endDay
* the daylight savings ending day-of-week-in-month. Please see
* the description of {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)} for an example.
* @param endDayOfWeek
* the daylight savings ending day-of-week. Please see the description of
* {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)} for an example.
* @param endTime
* the daylight savings ending time in local wall time, which is
* daylight time in this case. Please see the description of {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)}
* for an example.
* @param daylightSavings
* the daylight savings time difference in milliseconds.
* @throws IllegalArgumentException
* if the month, day, dayOfWeek, or time parameters are out of
* range for the start or end rule.
*/
public TSimpleTimeZone(int offset, String name, int startMonth,
int startDay, int startDayOfWeek, int startTime, int endMonth,
int endDay, int endDayOfWeek, int endTime, int daylightSavings) {
this(offset, name);
// END android-changed
if (daylightSavings <= 0) {
throw new IllegalArgumentException("Invalid daylightSavings: " + daylightSavings);
}
dstSavings = daylightSavings;
setStartRule(startMonth, startDay, startDayOfWeek, startTime);
setEndRule(endMonth, endDay, endDayOfWeek, endTime);
}
/**
* Construct a {@code SimpleTimeZone} with the given base time zone offset from GMT,
* time zone ID, times to start and end the daylight savings time including a
* mode specifier, the daylight savings time difference in milliseconds.
* The mode specifies either {@link #WALL_TIME}, {@link #STANDARD_TIME}, or
* {@link #UTC_TIME}.
*
* @param offset
* the given base time zone offset to GMT.
* @param name
* the time zone ID which is obtained from
* {@code TimeZone.getAvailableIDs}.
* @param startMonth
* the daylight savings starting month. The month indexing is 0-based. eg, 0
* for January.
* @param startDay
* the daylight savings starting day-of-week-in-month. Please see
* the description of {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)} for an example.
* @param startDayOfWeek
* the daylight savings starting day-of-week. Please see the
* description of {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)} for an example.
* @param startTime
* the time of day in milliseconds on which daylight savings
* time starts, based on the {@code startTimeMode}.
* @param startTimeMode
* the mode (UTC, standard, or wall time) of the start time
* value.
* @param endDay
* the day of the week on which daylight savings time ends.
* @param endMonth
* the daylight savings ending month. The month indexing is 0-based. eg, 0 for
* January.
* @param endDayOfWeek
* the daylight savings ending day-of-week. Please see the description of
* {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)} for an example.
* @param endTime
* the time of day in milliseconds on which daylight savings
* time ends, based on the {@code endTimeMode}.
* @param endTimeMode
* the mode (UTC, standard, or wall time) of the end time value.
* @param daylightSavings
* the daylight savings time difference in milliseconds.
* @throws IllegalArgumentException
* if the month, day, dayOfWeek, or time parameters are out of
* range for the start or end rule.
*/
public TSimpleTimeZone(int offset, String name, int startMonth,
int startDay, int startDayOfWeek, int startTime, int startTimeMode,
int endMonth, int endDay, int endDayOfWeek, int endTime,
int endTimeMode, int daylightSavings) {
this(offset, name, startMonth, startDay, startDayOfWeek, startTime,
endMonth, endDay, endDayOfWeek, endTime, daylightSavings);
startMode = startTimeMode;
endMode = endTimeMode;
}
/**
* Compares the specified object to this {@code SimpleTimeZone} and returns whether they
* are equal. The object must be an instance of {@code SimpleTimeZone} and have the
* same internal data.
*
* @param object
* the object to compare with this object.
* @return {@code true} if the specified object is equal to this
* {@code SimpleTimeZone}, {@code false} otherwise.
* @see #hashCode
*/
@Override
public boolean equals(Object object) {
if (!(object instanceof TSimpleTimeZone)) {
return false;
}
TSimpleTimeZone tz = (TSimpleTimeZone) object;
return getID().equals(tz.getID())
&& rawOffset == tz.rawOffset
&& useDaylight == tz.useDaylight
&& (!useDaylight || (startYear == tz.startYear
&& startMonth == tz.startMonth
&& startDay == tz.startDay && startMode == tz.startMode
&& startDayOfWeek == tz.startDayOfWeek
&& startTime == tz.startTime && endMonth == tz.endMonth
&& endDay == tz.endDay
&& endDayOfWeek == tz.endDayOfWeek
&& endTime == tz.endTime && endMode == tz.endMode && dstSavings == tz.dstSavings));
}
@Override
public int getDSTSavings() {
if (!useDaylight) {
return 0;
}
return dstSavings;
}
@Override
public int getOffset(int era, int year, int month, int day, int dayOfWeek, int time) {
if (era != TGregorianCalendar.BC && era != TGregorianCalendar.AD) {
throw new IllegalArgumentException("Invalid era: " + era);
}
checkRange(month, dayOfWeek, time);
if (month != TCalendar.FEBRUARY || day != 29 || !isLeapYear(year)) {
checkDay(month, day);
}
// BEGIN android-changed
// return icuTZ.getOffset(era, year, month, day, dayOfWeek, time);
if (!useDaylightTime() || era != TGregorianCalendar.AD || year < startYear) {
return rawOffset;
}
if (endMonth < startMonth) {
if (month > endMonth && month < startMonth) {
return rawOffset;
}
} else {
if (month < startMonth || month > endMonth) {
return rawOffset;
}
}
int ruleDay = 0, daysInMonth, firstDayOfMonth = mod7(dayOfWeek - day);
if (month == startMonth) {
switch (startMode) {
case DOM_MODE:
ruleDay = startDay;
break;
case DOW_IN_MONTH_MODE:
if (startDay >= 0) {
ruleDay = mod7(startDayOfWeek - firstDayOfMonth) + 1
+ (startDay - 1) * 7;
} else {
daysInMonth = TGregorianCalendar.DaysInMonth[startMonth];
if (startMonth == TCalendar.FEBRUARY && isLeapYear(
year)) {
daysInMonth += 1;
}
ruleDay = daysInMonth
+ 1
+ mod7(startDayOfWeek
- (firstDayOfMonth + daysInMonth))
+ startDay * 7;
}
break;
case DOW_GE_DOM_MODE:
ruleDay = startDay
+ mod7(startDayOfWeek
- (firstDayOfMonth + startDay - 1));
break;
case DOW_LE_DOM_MODE:
ruleDay = startDay
+ mod7(startDayOfWeek
- (firstDayOfMonth + startDay - 1));
if (ruleDay != startDay) {
ruleDay -= 7;
}
break;
}
if (ruleDay > day || ruleDay == day && time < startTime) {
return rawOffset;
}
}
int ruleTime = endTime - dstSavings;
int nextMonth = (month + 1) % 12;
if (month == endMonth || (ruleTime < 0 && nextMonth == endMonth)) {
switch (endMode) {
case DOM_MODE:
ruleDay = endDay;
break;
case DOW_IN_MONTH_MODE:
if (endDay >= 0) {
ruleDay = mod7(endDayOfWeek - firstDayOfMonth) + 1
+ (endDay - 1) * 7;
} else {
daysInMonth = TGregorianCalendar.DaysInMonth[endMonth];
if (endMonth == TCalendar.FEBRUARY && isLeapYear(year)) {
daysInMonth++;
}
ruleDay = daysInMonth
+ 1
+ mod7(endDayOfWeek
- (firstDayOfMonth + daysInMonth)) + endDay
* 7;
}
break;
case DOW_GE_DOM_MODE:
ruleDay = endDay
+ mod7(
endDayOfWeek - (firstDayOfMonth + endDay - 1));
break;
case DOW_LE_DOM_MODE:
ruleDay = endDay
+ mod7(
endDayOfWeek - (firstDayOfMonth + endDay - 1));
if (ruleDay != endDay) {
ruleDay -= 7;
}
break;
}
int ruleMonth = endMonth;
if (ruleTime < 0) {
int changeDays = 1 - (ruleTime / 86400000);
ruleTime = (ruleTime % 86400000) + 86400000;
ruleDay -= changeDays;
if (ruleDay <= 0) {
if (--ruleMonth < TCalendar.JANUARY) {
ruleMonth = TCalendar.DECEMBER;
}
ruleDay += TGregorianCalendar.DaysInMonth[ruleMonth];
if (ruleMonth == TCalendar.FEBRUARY && isLeapYear(year)) {
ruleDay++;
}
}
}
if (month == ruleMonth) {
if (ruleDay < day || ruleDay == day && time >= ruleTime) {
return rawOffset;
}
} else if (nextMonth != ruleMonth) {
return rawOffset;
}
}
return rawOffset + dstSavings;
// END android-changed
}
public int getOffset(long time) {
// BEGIN android-changed: simplified variant of the ICU4J code.
if (!useDaylightTime()) {
return rawOffset;
}
int[] fields = timeToFields(time + rawOffset, null);
return getOffset(TGregorianCalendar.AD, fields[0], fields[1], fields[2],
fields[3], fields[5]);
// END android-changed
}
private static int[] timeToFields(long time, int[] fields) {
if (fields == null || fields.length < 6) {
fields = new int[6];
}
long[] remainder = new long[1];
long day = floorDivide(time, 24*60*60*1000 /* milliseconds per day */, remainder);
dayToFields(day, fields);
fields[5] = (int)remainder[0];
return fields;
}
private static long floorDivide(long numerator, long denominator) {
// We do this computation in order to handle
// a numerator of Long.MIN_VALUE correctly
return (numerator >= 0) ?
numerator / denominator :
((numerator + 1) / denominator) - 1;
}
private static long floorDivide(long numerator, long denominator, long[] remainder) {
if (numerator >= 0) {
remainder[0] = numerator % denominator;
return numerator / denominator;
}
long quotient = ((numerator + 1) / denominator) - 1;
remainder[0] = numerator - (quotient * denominator);
return quotient;
}
public static int[] dayToFields(long day, int[] fields) {
if (fields == null || fields.length < 5) {
fields = new int[5];
}
// Convert from 1970 CE epoch to 1 CE epoch (Gregorian calendar)
day += JULIAN_1970_CE - JULIAN_1_CE;
long[] rem = new long[1];
long n400 = floorDivide(day, 146097, rem);
long n100 = floorDivide(rem[0], 36524, rem);
long n4 = floorDivide(rem[0], 1461, rem);
long n1 = floorDivide(rem[0], 365, rem);
int year = (int)(400 * n400 + 100 * n100 + 4 * n4 + n1);
int dayOfYear = (int)rem[0];
if (n100 == 4 || n1 == 4) {
dayOfYear = 365; // Dec 31 at end of 4- or 400-yr cycle
}
else {
++year;
}
boolean isLeap = isLeapYear(year);
int correction = 0;
int march1 = isLeap ? 60 : 59; // zero-based DOY for March 1
if (dayOfYear >= march1) {
correction = isLeap ? 1 : 2;
}
int month = (12 * (dayOfYear + correction) + 6) / 367; // zero-based month
int dayOfMonth = dayOfYear - DAYS_BEFORE[isLeap ? month + 12 : month] + 1; // one-based DOM
int dayOfWeek = (int)((day + 2) % 7); // day 0 is Monday(2)
if (dayOfWeek < 1 /* Sunday */) {
dayOfWeek += 7;
}
dayOfYear++; // 1-based day of year
fields[0] = year;
fields[1] = month;
fields[2] = dayOfMonth;
fields[3] = dayOfWeek;
fields[4] = dayOfYear;
return fields;
}
@Override
public int getRawOffset() {
return rawOffset;
}
/**
* Returns an integer hash code for the receiver. Objects which are equal
* return the same value for this method.
*
* @return the receiver's hash.
* @see #equals
*/
@Override
public synchronized int hashCode() {
int hashCode = getID().hashCode() + rawOffset;
if (useDaylight) {
hashCode += startYear + startMonth + startDay + startDayOfWeek
+ startTime + startMode + endMonth + endDay + endDayOfWeek
+ endTime + endMode + dstSavings;
}
return hashCode;
}
public boolean hasSameRules(TTimeZone zone) {
if (!(zone instanceof TSimpleTimeZone)) {
return false;
}
TSimpleTimeZone tz = (TSimpleTimeZone) zone;
if (useDaylight != tz.useDaylight) {
return false;
}
if (!useDaylight) {
return rawOffset == tz.rawOffset;
}
return rawOffset == tz.rawOffset && dstSavings == tz.dstSavings
&& startYear == tz.startYear && startMonth == tz.startMonth
&& startDay == tz.startDay && startMode == tz.startMode
&& startDayOfWeek == tz.startDayOfWeek
&& startTime == tz.startTime && endMonth == tz.endMonth
&& endDay == tz.endDay && endDayOfWeek == tz.endDayOfWeek
&& endTime == tz.endTime && endMode == tz.endMode;
}
@Override
public boolean inDaylightTime(TDate time) {
// BEGIN android-changed: reuse getOffset.
return useDaylightTime() && getOffset(time.getTime()) != rawOffset;
// END android-changed
}
private static boolean isLeapYear(int year) {
if (year > 1582) {
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
}
return year % 4 == 0;
}
// BEGIN android-added
private int mod7(int num1) {
int rem = num1 % 7;
return (num1 < 0 && rem < 0) ? 7 + rem : rem;
}
// END android-added
/**
* Sets the daylight savings offset in milliseconds for this {@code SimpleTimeZone}.
*
* @param milliseconds
* the daylight savings offset in milliseconds.
*/
public void setDSTSavings(int milliseconds) {
if (milliseconds > 0) {
dstSavings = milliseconds;
} else {
throw new IllegalArgumentException();
}
}
private void checkRange(int month, int dayOfWeek, int time) {
if (month < TCalendar.JANUARY || month > TCalendar.DECEMBER) {
throw new IllegalArgumentException("Invalid month: " + month);
}
if (dayOfWeek < TCalendar.SUNDAY || dayOfWeek > TCalendar.SATURDAY) {
throw new IllegalArgumentException("Invalid day of week: " + dayOfWeek);
}
if (time < 0 || time >= 24 * 3600000) {
throw new IllegalArgumentException("Invalid time: " + time);
}
}
private void checkDay(int month, int day) {
if (day <= 0 || day > TGregorianCalendar.DaysInMonth[month]) {
throw new IllegalArgumentException("Invalid day of month: " + day);
}
}
private void setEndMode() {
if (endDayOfWeek == 0) {
endMode = DOM_MODE;
} else if (endDayOfWeek < 0) {
endDayOfWeek = -endDayOfWeek;
if (endDay < 0) {
endDay = -endDay;
endMode = DOW_LE_DOM_MODE;
} else {
endMode = DOW_GE_DOM_MODE;
}
} else {
endMode = DOW_IN_MONTH_MODE;
}
useDaylight = startDay != 0 && endDay != 0;
if (endDay != 0) {
checkRange(endMonth, endMode == DOM_MODE ? 1 : endDayOfWeek,
endTime);
if (endMode != DOW_IN_MONTH_MODE) {
checkDay(endMonth, endDay);
} else {
if (endDay < -5 || endDay > 5) {
throw new IllegalArgumentException("Day of week in month: " + endDay);
}
}
}
if (endMode != DOM_MODE) {
endDayOfWeek--;
}
}
/**
* Sets the rule which specifies the end of daylight savings time.
*
* @param month
* the {@code Calendar} month in which daylight savings time ends.
* @param dayOfMonth
* the {@code Calendar} day of the month on which daylight savings time
* ends.
* @param time
* the time of day in milliseconds standard time on which
* daylight savings time ends.
*/
public void setEndRule(int month, int dayOfMonth, int time) {
endMonth = month;
endDay = dayOfMonth;
endDayOfWeek = 0; // Initialize this value for hasSameRules()
endTime = time;
setEndMode();
}
/**
* Sets the rule which specifies the end of daylight savings time.
*
* @param month
* the {@code Calendar} month in which daylight savings time ends.
* @param day
* the occurrence of the day of the week on which daylight
* savings time ends.
* @param dayOfWeek
* the {@code Calendar} day of the week on which daylight savings time
* ends.
* @param time
* the time of day in milliseconds standard time on which
* daylight savings time ends.
*/
public void setEndRule(int month, int day, int dayOfWeek, int time) {
endMonth = month;
endDay = day;
endDayOfWeek = dayOfWeek;
endTime = time;
setEndMode();
}
/**
* Sets the rule which specifies the end of daylight savings time.
*
* @param month
* the {@code Calendar} month in which daylight savings time ends.
* @param day
* the {@code Calendar} day of the month.
* @param dayOfWeek
* the {@code Calendar} day of the week on which daylight savings time
* ends.
* @param time
* the time of day in milliseconds on which daylight savings time
* ends.
* @param after
* selects the day after or before the day of month.
*/
public void setEndRule(int month, int day, int dayOfWeek, int time,
boolean after) {
endMonth = month;
endDay = after ? day : -day;
endDayOfWeek = -dayOfWeek;
endTime = time;
setEndMode();
// BEGIN android-removed
// if (isSimple) {
// ((com.ibm.icu.util.SimpleTimeZone) icuTZ).setEndRule(month, day,
// dayOfWeek, time, after);
// }
// END android-removed
}
/**
* Sets the offset for standard time from GMT for this {@code SimpleTimeZone}.
*
* @param offset
* the offset from GMT of standard time in milliseconds.
*/
public void setRawOffset(int offset) {
rawOffset = offset;
// BEGIN android-removed
// icuTZ.setRawOffset(offset);
// END android-removed
}
private void setStartMode() {
if (startDayOfWeek == 0) {
startMode = DOM_MODE;
} else if (startDayOfWeek < 0) {
startDayOfWeek = -startDayOfWeek;
if (startDay < 0) {
startDay = -startDay;
startMode = DOW_LE_DOM_MODE;
} else {
startMode = DOW_GE_DOM_MODE;
}
} else {
startMode = DOW_IN_MONTH_MODE;
}
useDaylight = startDay != 0 && endDay != 0;
if (startDay != 0) {
checkRange(startMonth, startMode == DOM_MODE ? 1 : startDayOfWeek,
startTime);
if (startMode != DOW_IN_MONTH_MODE) {
checkDay(startMonth, startDay);
} else {
if (startDay < -5 || startDay > 5) {
throw new IllegalArgumentException("Day of week in month: " + startDay);
}
}
}
if (startMode != DOM_MODE) {
startDayOfWeek--;
}
}
/**
* Sets the rule which specifies the start of daylight savings time.
*
* @param month
* the {@code Calendar} month in which daylight savings time starts.
* @param dayOfMonth
* the {@code Calendar} day of the month on which daylight savings time
* starts.
* @param time
* the time of day in milliseconds on which daylight savings time
* starts.
*/
public void setStartRule(int month, int dayOfMonth, int time) {
startMonth = month;
startDay = dayOfMonth;
startDayOfWeek = 0; // Initialize this value for hasSameRules()
startTime = time;
setStartMode();
// BEGIN android-removed
// if (isSimple) {
// ((com.ibm.icu.util.SimpleTimeZone) icuTZ).setStartRule(month,
// dayOfMonth, time);
// }
// END android-removed
}
/**
* Sets the rule which specifies the start of daylight savings time.
*
* @param month
* the {@code Calendar} month in which daylight savings time starts.
* @param day
* the occurrence of the day of the week on which daylight
* savings time starts.
* @param dayOfWeek
* the {@code Calendar} day of the week on which daylight savings time
* starts.
* @param time
* the time of day in milliseconds on which daylight savings time
* starts.
*/
public void setStartRule(int month, int day, int dayOfWeek, int time) {
startMonth = month;
startDay = day;
startDayOfWeek = dayOfWeek;
startTime = time;
setStartMode();
}
/**
* Sets the rule which specifies the start of daylight savings time.
*
* @param month
* the {@code Calendar} month in which daylight savings time starts.
* @param day
* the {@code Calendar} day of the month.
* @param dayOfWeek
* the {@code Calendar} day of the week on which daylight savings time
* starts.
* @param time
* the time of day in milliseconds on which daylight savings time
* starts.
* @param after
* selects the day after or before the day of month.
*/
public void setStartRule(int month, int day, int dayOfWeek, int time,
boolean after) {
startMonth = month;
startDay = after ? day : -day;
startDayOfWeek = -dayOfWeek;
startTime = time;
setStartMode();
}
/**
* Sets the starting year for daylight savings time in this {@code SimpleTimeZone}.
* Years before this start year will always be in standard time.
*
* @param year
* the starting year.
*/
public void setStartYear(int year) {
startYear = year;
useDaylight = true;
}
/**
* Returns the string representation of this {@code SimpleTimeZone}.
*
* @return the string representation of this {@code SimpleTimeZone}.
*/
@Override
public String toString() {
return getClass().getName()
+ "[id="
+ getID()
+ ",offset="
+ rawOffset
+ ",dstSavings="
+ dstSavings
+ ",useDaylight="
+ useDaylight
+ ",startYear="
+ startYear
+ ",startMode="
+ startMode
+ ",startMonth="
+ startMonth
+ ",startDay="
+ startDay
+ ",startDayOfWeek="
+ (useDaylight && (startMode != DOM_MODE) ? startDayOfWeek + 1
: 0) + ",startTime=" + startTime + ",endMode="
+ endMode + ",endMonth=" + endMonth + ",endDay=" + endDay
+ ",endDayOfWeek="
+ (useDaylight && (endMode != DOM_MODE) ? endDayOfWeek + 1 : 0)
+ ",endTime=" + endTime + "]";
}
@Override
public boolean useDaylightTime() {
return useDaylight;
}
}

View File

@ -0,0 +1,452 @@
/*
* Copyright 2015 Steve Hannah.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.classlib.java.util;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import static org.teavm.classlib.java.util.TGregorianCalendar.AD;
import static org.teavm.classlib.java.util.TGregorianCalendar.BC;
import org.teavm.jso.JS;
import org.teavm.jso.JSConstructor;
import org.teavm.jso.JSObject;
import org.teavm.platform.PlatformTimezone;
/**
* TimeZone represents a time zone offset, and also figures out daylight savings.
* Typically, you get a TimeZone using getDefault which creates a TimeZone based on the
* time zone where the program is running. For example, for a program running in Japan,
* getDefault creates a TimeZone object based on Japanese Standard Time.
* You can also get a TimeZone using getTimeZone along with a time zone ID. For instance,
* the time zone ID for the Pacific Standard Time zone is "PST". So, you can get a PST
* TimeZone object with:
* This class is a pure subset of the java.util.TimeZone class in JDK 1.3.
* The only time zone ID that is required to be supported is "GMT".
* Apart from the methods and variables being subset, the semantics of the getTimeZone()
* method may also be subset: custom IDs such as "GMT-8:00" are not required to be supported.
* Version: CLDC 1.1 02/01/2002 (Based on JDK 1.3) See Also:Calendar, Date
*/
public abstract class TTimeZone {
// For the Local Timezone we need to use the Javascript Date object
// Directly, so here is a makeshift JSO for it. If this object already
// has a JSO or it is deemed adventageous to move this to a more centralized
// location, then refactor by all means.
interface JSDate extends JSObject {
int getDate();
int getDay();
int getFullYear();
void setFullYear(int year);
int getHours();
int getMilliseconds();
int getMinutes();
int getMonth();
int getSeconds();
double getTime();
int getTimezoneOffset();
void setDate(int day);
}
interface JSDateFactory extends JSObject {
@JSConstructor("Date")
JSDate createDate();
@JSConstructor("Date")
JSDate createDate(double millis);
@JSConstructor("Date")
JSDate createDate(String dateString);
@JSConstructor("Date")
JSDate createDate(int year, int month, int day, int hours, int minutes, int seconds, int milliseconds);
}
static JSDate createJSDate() {
return ((JSDateFactory)JS.getGlobal()).createDate();
}
static JSDate createJSDate(long millis) {
return ((JSDateFactory)JS.getGlobal()).createDate((double)millis);
}
static JSDate createJSDate(String dateString) {
return ((JSDateFactory)JS.getGlobal()).createDate(dateString);
}
static JSDate createJSDate(int year, int month, int day, int hours, int minutes, int seconds, int milliseconds) {
JSDate out = ((JSDateFactory)JS.getGlobal()).createDate(year, month, day, hours, minutes, seconds, milliseconds);
out.setFullYear(year);
return out;
}
// End Private Javascript Date Object JSO stuff
/**
* A special "local" timezone that represents the timezone of the Javascript
* environment. Javascript doesn't allow us to see the name of this timezone.
* We use this as the default platform timezone and set its ID as "Local".
*/
public static class Local extends PlatformTimezone {
@Override
public String getTimezoneId() {
return "Local";
}
@Override
public int getTimezoneOffset(int year, int month, int day, int timeOfDayMillis) {
int hours = (int)Math.floor(timeOfDayMillis/1000/60/60);
int minutes = (int)Math.floor(timeOfDayMillis/1000/60)%60;
int seconds = (int)Math.floor(timeOfDayMillis/1000)%60;
JSDate d = createJSDate(year, month, day, hours, minutes, seconds, timeOfDayMillis % 1000);
return d.getTimezoneOffset();
}
@Override
public int getTimezoneRawOffset() {
JSDate now = createJSDate();
JSDate jan = createJSDate(now.getFullYear(), 0, 1, 0, 0, 0, 0);
JSDate jul = createJSDate(now.getFullYear(), 6, 1, 0, 0, 0, 0);
if (isTimezoneDST((long)jan.getTime())) {
return jul.getTimezoneOffset();
} else {
return jan.getTimezoneOffset();
}
}
@Override
public boolean isTimezoneDST(long millis) {
JSDate now = createJSDate();
JSDate jan = createJSDate(now.getFullYear(), 0, 1, 0, 0, 0, 0);
JSDate jul = createJSDate(now.getFullYear(), 6, 1, 0, 0, 0, 0);
int maxOffset = Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset());
return createJSDate(millis).getTimezoneOffset()<maxOffset;
}
}
static {
PlatformTimezone.addTimezone("Local", new Local());
PlatformTimezone.setPlatformTimezoneId("Local");
}
/**
* The short display name style, such as {@code PDT}. Requests for this
* style may yield GMT offsets like {@code GMT-08:00}.
*/
public static final int SHORT = 0;
/**
* The long display name style, such as {@code Pacific Daylight Time}.
* Requests for this style may yield GMT offsets like {@code GMT-08:00}.
*/
public static final int LONG = 1;
static final TTimeZone GMT = new TSimpleTimeZone(0, "GMT"); // Greenwich Mean Time
private static TTimeZone defaultTimeZone;
private static TTimeZone systemTimeZone;
private String ID;
public TTimeZone() {
}
void setID(String id) {
ID = id;
}
/**
* Gets all the available IDs supported.
*/
public static java.lang.String[] getAvailableIDs() {
return PlatformTimezone.getAvailableIds();
}
public static java.lang.String[] getAvailableIDs(int rawOffset) {
List<String> out = new ArrayList<String>();
for (String id : getAvailableIDs()) {
PlatformTimezone tz = PlatformTimezone.getTimezone(id);
if (tz.getTimezoneRawOffset()==rawOffset) {
out.add(id);
}
}
return out.toArray(new String[out.size()]);
}
private static String getTimezoneId() {
return PlatformTimezone.getPlatformTimezoneId();
}
private static int getTimezoneOffset(String name, int year, int month, int day, int timeOfDayMillis) {
PlatformTimezone tz = PlatformTimezone.getTimezone(name);
if (tz==null) {
throw new RuntimeException("Timezone not found: "+name);
}
return tz.getTimezoneOffset(year, month, day, timeOfDayMillis);
}
private static int getTimezoneRawOffset(String name) {
PlatformTimezone tz = PlatformTimezone.getTimezone(name);
if (tz==null) {
throw new RuntimeException("Timezone not found: "+name);
}
return tz.getTimezoneRawOffset();
}
private static boolean isTimezoneDST(String name, long millis) {
PlatformTimezone tz = PlatformTimezone.getTimezone(name);
if (tz==null) {
throw new RuntimeException("Timezone not found: "+name);
}
return tz.isTimezoneDST(millis);
}
private static TTimeZone getSystemTimeZone() {
if (systemTimeZone == null) {
systemTimeZone = getTimeZone(PlatformTimezone.getPlatformTimezoneId());
}
return systemTimeZone;
}
/**
* Gets the default TimeZone for this host. The source of the default TimeZone may vary with implementation.
*/
public static TTimeZone getDefault() {
if (defaultTimeZone == null) {
defaultTimeZone = getSystemTimeZone();
}
return defaultTimeZone;
}
public static void setDefault(TTimeZone tz) {
defaultTimeZone=tz;
}
int getDSTSavings() {
return useDaylightTime() ? 3600000 : 0;
}
boolean inDaylightTime(TDate time) {
return false;
}
/**
* Gets the ID of this time zone.
*/
public java.lang.String getID() {
return ID;
}
public int getOffset(long millis) {
Date d = new Date(millis);
d.setHours(0);
d.setMinutes(0);
d.setSeconds(0);
return getOffset(d.getYear()>=-1900?AD:BC, d.getYear()+1900, d.getMonth(), d.getDate(), d.getDay(), (int)(millis-d.getTime()));
}
/**
* Gets offset, for current date, modified in case of daylight savings. This is the offset to add *to* GMT to get local time. Gets the time zone offset, for current date, modified in case of daylight savings. This is the offset to add *to* GMT to get local time. Assume that the start and end month are distinct. This method may return incorrect results for rules that start at the end of February (e.g., last Sunday in February) or the beginning of March (e.g., March 1).
*/
public abstract int getOffset(int era, int year, int month, int day, int dayOfWeek, int millis);
/**
* Gets the GMT offset for this time zone.
*/
public abstract int getRawOffset();
private static String normalizeGMTOffset(String offset){
int pos;
int len = offset.length();
if (len == 1){
// Should be simple integer of hours 0-9
char c = offset.charAt(0);
if (c < '0' || c > '9') {
return "";
}
return "0"+offset+":00";
} else if (len == 2){
// Should be a 2-digit representation of hours 00-23
char c1 = offset.charAt(0);
if (c1 < '0' || c1 > '2') {
return "";
}
char c2 = offset.charAt(1);
if (c2 < '0' || (c1 == '2' && c2 > '3') || c2 > '9') {
return "";
}
return offset+":00";
} else if (len == 3) {
char c1 = offset.charAt(0);
if (c1 < '0' || c1 > '9') {
return "";
}
char c2 = offset.charAt(1);
if (c2 < '0' || c2 > '5') {
return "";
}
char c3 = offset.charAt(2);
if (c3 < '0' || c3 > '9') {
return "";
}
return "0"+c1+":"+c2+c3;
} else if (len == 4 && offset.charAt(1) == ':'){
char c1 = offset.charAt(0);
if (c1 < '0' || c1 > '9') {
return "";
}
char c2 = offset.charAt(2);
if (c2 < '0' || c2 > '5') {
return "";
}
char c3 = offset.charAt(3);
if (c3 < '0' || c3 > '9') {
return "";
}
return "0"+c1+":"+c2+c3;
} else if (len==4) {
char c1 = offset.charAt(0);
if (c1 < '0' || c1 > '2') {
return "";
}
char c2 = offset.charAt(1);
if (c2 < '0' || (c1 == '2' && c2 > '3') || c2 > '9') {
return "";
}
char c3 = offset.charAt(2);
if (c3 < '0' || c3 > '5') {
return "";
}
char c4 = offset.charAt(3);
if (c4 < '0' || c3 > '9') {
return "";
}
return ""+c1+c2+":"+c3+c4;
} else if (len == 5 && offset.charAt(2) == ':'){
char c1 = offset.charAt(0);
if (c1 < '0' || c1 > '2') {
return "";
}
char c2 = offset.charAt(1);
if (c2 < '0' || (c1 == '2' && c2 > '3') || c2 > '9') {
return "";
}
char c3 = offset.charAt(3);
if (c3 < '0' || c3 > '5') {
return "";
}
char c4 = offset.charAt(4);
if (c4 < '0' || c3 > '9') {
return "";
}
return ""+c1+c2+":"+c3+c4;
} else {
return "";
}
}
/**
* Gets the TimeZone for the given ID.
*/
public static TTimeZone getTimeZone(java.lang.String ID) {
if (PlatformTimezone.getTimezone(ID)!=null) {
final TTimeZone tz = new TTimeZone() {
private int dstSavings=-1;
@Override
public int getOffset(int era, int year, int month, int day, int dayOfWeek, int timeOfDayMillis) {
if (era==BC) {
year = -year;
}
return getTimezoneOffset(this.getID(), year, month, day, timeOfDayMillis);
}
@Override
public int getRawOffset() {
return getTimezoneRawOffset(this.getID());
}
@Override
boolean inDaylightTime(TDate time) {
return isTimezoneDST(this.getID(), time.getTime());
}
@Override
public boolean useDaylightTime() {
TDate now = new TDate();
TDate jan = new TDate(now.getYear(), 0, 1);
TDate jul = new TDate(now.getYear(), 6, 1);
return inDaylightTime(jan) || inDaylightTime(jul);
}
@Override
int getDSTSavings() {
if (useDaylightTime()) {
if (dstSavings==-1) {
TDate now = new TDate();
TDate jan = new TDate(now.getYear(), 0, 1);
TDate jul = new TDate(now.getYear(), 6, 1);
dstSavings = Math.abs(this.getOffset(jan.getTime())-this.getOffset(jul.getTime()));
}
return dstSavings;
}
return 0;
}
};
tz.ID = ID;
return tz;
}
if (ID.startsWith("GMT")) {
if (ID.length()==3) {
return GMT;
} else if (ID.charAt(3) == '+' || ID.charAt(3) == '-') {
String strOffset = ID.substring(4);
String normalizedOffset = normalizeGMTOffset(strOffset);
if (normalizedOffset == null || "".equals(normalizedOffset)) {
return GMT;
}
int hours = Integer.parseInt(normalizedOffset.substring(0,2));
int minutes = Integer.parseInt(normalizedOffset.substring(3));
int offset = hours * 60 * 60 * 1000 + minutes * 60 * 1000;
if (ID.charAt(3) == '-') {
offset = -offset;
}
return new TSimpleTimeZone(offset, "GMT"+ID.charAt(3)+normalizedOffset);
}
}
return GMT;
}
/**
* Queries if this time zone uses Daylight Savings Time.
*/
public abstract boolean useDaylightTime();
}

View File

@ -537,7 +537,6 @@ function $rt_nativeThread() {
function $rt_invalidPointer() { function $rt_invalidPointer() {
throw new Error("Invalid recorded state"); throw new Error("Invalid recorded state");
} }
function $dbg_repr(obj) { function $dbg_repr(obj) {
return obj.toString ? obj.toString() : ""; return obj.toString ? obj.toString() : "";
} }

View File

@ -0,0 +1,124 @@
/*
* Copyright 2015 Steve Hannah.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.platform;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* Allows for adding timezones to the runtime.
* @author shannah
*/
public abstract class PlatformTimezone {
/**
* The default timezone ID.
*/
private static String platformTimezoneId;
/**
* Map of registered timezones. Maps IDs to TimeZones.
*/
private static Map<String, PlatformTimezone> timezones;
/**
* Returns timezone map, lazily initialized.
* @return
*/
private static Map<String, PlatformTimezone> timezones(){
if (timezones==null){
timezones = new HashMap<String, PlatformTimezone>();
}
return timezones;
}
/**
* Gets a timezone with the specified ID.
* @param id The ID of the timezone to retrieve.
* @return The TimeZone or null if none exists with that name.
*/
public static PlatformTimezone getTimezone(String id) {
return timezones().get(id);
}
/**
* Adds a TimeZone.
* @param id The ID of the TimeZone.
* @param tz The TimeZone to add.
*/
public static void addTimezone(String id, PlatformTimezone tz) {
timezones().put(id, tz);
}
/**
* Gets a list of the available platform TimeZone IDs.
* @return
*/
public static String[] getAvailableIds() {
Set<String> keys = timezones().keySet();
return keys.toArray(new String[keys.size()]);
}
/**
* Sets the local TimeZone ID of the platform. This will be used as the
* "default" TimeZone.
* @param id The ID of the platform timezone.
*/
public static void setPlatformTimezoneId(String id) {
platformTimezoneId=id;
}
/**
* Gets the local TimeZone ID of the platform. This will be used as the
* "default" TimeZone.
* @return The default TimeZone ID.
*/
public static String getPlatformTimezoneId() {
return platformTimezoneId;
}
/**
* Gets the ID of the TimeZone. E.g. "EST", or "America/Toronto"
* @return The TimeZone ID
*/
public abstract String getTimezoneId();
/**
* Gets the timezone offset at the given date. This will include any DST
* offset.
* @param year The year at which the calculation is made. For BC dates, use negatives.
* @param month The month. (0-11)
* @param day The day of the month (1-31).
* @param timeOfDayMillis The time of the day in milliseconds.
* @return The offset in milliseconds from GMT time.
*/
public abstract int getTimezoneOffset(int year, int month, int day, int timeOfDayMillis);
/**
* Gets the raw offset of the TimeZone. This does not include any DST offsets.
* @return The raw offset of the timezone.
*/
public abstract int getTimezoneRawOffset();
/**
* Checks if the timezone is observing daylight savings time at the provided
* date.
* @param millis The unix timestamp in milliseconds.
* @return True if the timezone is observing DST at the given date.
*/
public abstract boolean isTimezoneDST(long millis);
}

View File

@ -60,13 +60,13 @@ public class DateFormatTest {
private Date getDateWithZoneOffset(long milliseconds) { private Date getDateWithZoneOffset(long milliseconds) {
Calendar calendar = new GregorianCalendar(Locale.ENGLISH); Calendar calendar = new GregorianCalendar(Locale.ENGLISH);
calendar.setTimeInMillis(milliseconds); calendar.setTimeInMillis(milliseconds);
milliseconds -= calendar.get(Calendar.ZONE_OFFSET); milliseconds -= calendar.get(Calendar.ZONE_OFFSET)-calendar.get(Calendar.DST_OFFSET);
return new Date(milliseconds); return new Date(milliseconds);
} }
private long getTimeWithoutZoneOffset(Date date) { private long getTimeWithoutZoneOffset(Date date) {
Calendar calendar = new GregorianCalendar(Locale.ENGLISH); Calendar calendar = new GregorianCalendar(Locale.ENGLISH);
calendar.setTime(date); calendar.setTime(date);
return calendar.getTimeInMillis() + calendar.get(Calendar.ZONE_OFFSET); return calendar.getTimeInMillis() + calendar.get(Calendar.ZONE_OFFSET)+calendar.get(Calendar.DST_OFFSET);
} }
} }

View File

@ -137,12 +137,13 @@ public class SimpleDateFormatTest {
Calendar calendar = new GregorianCalendar(Locale.ENGLISH); Calendar calendar = new GregorianCalendar(Locale.ENGLISH);
calendar.setTimeInMillis(milliseconds); calendar.setTimeInMillis(milliseconds);
milliseconds -= calendar.get(Calendar.ZONE_OFFSET); milliseconds -= calendar.get(Calendar.ZONE_OFFSET);
milliseconds -= calendar.get(Calendar.DST_OFFSET);
return new Date(milliseconds); return new Date(milliseconds);
} }
private long getTimeWithoutZoneOffset(Date date) { private long getTimeWithoutZoneOffset(Date date) {
Calendar calendar = new GregorianCalendar(Locale.ENGLISH); Calendar calendar = new GregorianCalendar(Locale.ENGLISH);
calendar.setTime(date); calendar.setTime(date);
return calendar.getTimeInMillis() + calendar.get(Calendar.ZONE_OFFSET); return calendar.getTimeInMillis() + calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,480 @@
/*
* Copyright 2015 Steve Hannah.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.classlib.java.util;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import static org.junit.Assert.*;
import java.util.SimpleTimeZone;
import java.util.TimeZone;
import org.junit.Test;
import org.teavm.classlib.java.util.TTimeZone.JSDate;
import org.teavm.platform.PlatformTimezone;
/**
*
* @author shannah
*/
public class TimeZoneTest {
private static final int ONE_HOUR = 3600000;
static class EST extends PlatformTimezone {
@Override
public String getTimezoneId() {
return "EST";
}
@Override
public int getTimezoneOffset(int year, int month, int day, int timeOfDayMillis) {
return -5*ONE_HOUR;
}
@Override
public int getTimezoneRawOffset() {
return -5*ONE_HOUR;
}
@Override
public boolean isTimezoneDST(long millis) {
return false;
}
}
static class AsiaShanghai extends PlatformTimezone {
@Override
public String getTimezoneId() {
return "Asia/Shanghai";
}
@Override
public int getTimezoneOffset(int year, int month, int day, int timeOfDayMillis) {
return ONE_HOUR*8;
}
@Override
public int getTimezoneRawOffset() {
return ONE_HOUR*8;
}
@Override
public boolean isTimezoneDST(long millis) {
return false;
}
}
static class Hongkong extends PlatformTimezone {
@Override
public String getTimezoneId() {
return "Hongkong";
}
@Override
public int getTimezoneOffset(int year, int month, int day, int timeOfDayMillis) {
return ONE_HOUR*8;
}
@Override
public int getTimezoneRawOffset() {
return ONE_HOUR*8;
}
@Override
public boolean isTimezoneDST(long millis) {
return false;
}
}
static class AmericaToronto extends PlatformTimezone {
@Override
public String getTimezoneId() {
return "America/Toronto";
}
@Override
public int getTimezoneOffset(int year, int month, int day, int timeOfDayMillis) {
JSDate d = TTimeZone.createJSDate(year, month, day, 0, 0, 0, 0);
return getTimezoneRawOffset() + (isTimezoneDST((long)d.getTime())?ONE_HOUR:0);
}
@Override
public int getTimezoneRawOffset() {
return -ONE_HOUR*5;
}
@Override
public boolean isTimezoneDST(long millis) {
JSDate d = TTimeZone.createJSDate(millis);
// This is a very crude approximation that is WRONG but will allow
// tests to pass
System.out.println("Checking isTimezoneDST for America/Toronto");
System.out.println("Month is "+d.getMonth());
System.out.println("Time is "+d.getTime());
return d.getMonth()>2 && d.getMonth()<10;
}
}
static class AustraliaLordHowe extends PlatformTimezone {
@Override
public String getTimezoneId() {
return "Australia/Lord_Howe";
}
@Override
public int getTimezoneOffset(int year, int month, int day, int timeOfDayMillis) {
JSDate d = TTimeZone.createJSDate(year, month, day, 0, 0, 0, 0);
return getTimezoneRawOffset() + (isTimezoneDST((long)d.getTime())?ONE_HOUR/2:0);
}
@Override
public int getTimezoneRawOffset() {
return ONE_HOUR*10 + ONE_HOUR/2;
}
@Override
public boolean isTimezoneDST(long millis) {
JSDate d = TTimeZone.createJSDate(millis);
// This is a very crude approximation that is WRONG but will allow
// tests to pass
System.out.println("Checking isTimezoneDST for Australia");
System.out.println("Month is "+d.getMonth());
System.out.println("Time is "+d.getTime());
return !(d.getMonth()>=3 && d.getMonth()<9);
}
}
private static class PlatformSupportTimezone extends PlatformTimezone {
private String id;
private long offset;
private boolean dst;
PlatformSupportTimezone(String id, long offset, boolean dst) {
this.id=id;
this.offset=offset;
this.dst=dst;
}
@Override
public String getTimezoneId() {
return id;
}
@Override
public int getTimezoneOffset(int year, int month, int day, int timeOfDayMillis) {
JSDate d = TTimeZone.createJSDate(year, month, day, 0, 0, 0, 0);
return (int)(offset + (isTimezoneDST((long)d.getTime())?ONE_HOUR:0));
}
@Override
public int getTimezoneRawOffset() {
return (int)offset;
}
@Override
public boolean isTimezoneDST(long millis) {
if (!dst) {
return false;
}
JSDate d = TTimeZone.createJSDate(millis);
if (d.getMonth() > 4 && d.getMonth() < 10) {
return true;
}
return false;
}
}
private static TimeZone newSupportTimeZone(int rawOffset, boolean useDaylightTime) {
String id = "Support_TimeZone+"+rawOffset+(useDaylightTime?"DST":"");
if (PlatformTimezone.getTimezone(id)==null) {
PlatformTimezone.addTimezone(id, new PlatformSupportTimezone(id, rawOffset, useDaylightTime));
}
return TimeZone.getTimeZone(id);
}
static {
PlatformTimezone.addTimezone("EST", new EST());
PlatformTimezone.addTimezone("Asia/Shanghai", new AsiaShanghai());
PlatformTimezone.addTimezone("Hongkong", new Hongkong());
PlatformTimezone.addTimezone("America/Toronto", new AmericaToronto());
PlatformTimezone.addTimezone("Australia/Lord_Howe", new AustraliaLordHowe());
}
/**
* @tests java.util.TimeZone#getDefault()
*/
//@Test
//public void test_getDefault() {
// assertNotSame("returns identical",
// TimeZone.getDefault(), TimeZone.getDefault());
//}
/**
* @tests java.util.TimeZone#getDSTSavings()
*/
@Test
public void test_getDSTSavings() {
// Test for method int java.util.TimeZone.getDSTSavings()
// test on subclass SimpleTimeZone
TimeZone st1 = TimeZone.getTimeZone("EST");
assertEquals("T1A. Incorrect daylight savings returned",
0, st1.getDSTSavings());
// a SimpleTimeZone with daylight savings different then 1 hour
st1 = TimeZone.getTimeZone("Australia/Lord_Howe");
assertEquals("T1B. Incorrect daylight savings returned",
1800000, st1.getDSTSavings());
// test on subclass Support_TimeZone, an instance with daylight savings
TimeZone tz1 = newSupportTimeZone(-5 * ONE_HOUR, true);
assertEquals("T2. Incorrect daylight savings returned",
ONE_HOUR, tz1.getDSTSavings());
// an instance without daylight savings
tz1 = newSupportTimeZone(3 * ONE_HOUR, false);
assertEquals("T3. Incorrect daylight savings returned, ",
0, tz1.getDSTSavings());
}
/**
* @tests java.util.TimeZone#getOffset(long)
*/
@Test
public void test_getOffset_long() {
// Test for method int java.util.TimeZone.getOffset(long time)
// test on subclass SimpleTimeZone
TimeZone st1 = TimeZone.getTimeZone("EST");
long time1 = new GregorianCalendar(1998, Calendar.NOVEMBER, 11)
.getTimeInMillis();
assertEquals("T1. Incorrect offset returned",
-(5 * ONE_HOUR), st1.getOffset(time1));
long time2 = new GregorianCalendar(1998, Calendar.JUNE, 11)
.getTimeInMillis();
st1 = TimeZone.getTimeZone("EST");
assertEquals("T2. Incorrect offset returned",
-(5 * ONE_HOUR), st1.getOffset(time2));
// test on subclass Support_TimeZone, an instance with daylight savings
TimeZone tz1 = newSupportTimeZone(-5 * ONE_HOUR, true);
assertEquals("T3. Incorrect offset returned, ",
-(5 * ONE_HOUR), tz1.getOffset(time1));
assertEquals("T4. Incorrect offset returned, ",
-(4 * ONE_HOUR), tz1.getOffset(time2));
// an instance without daylight savings
tz1 = newSupportTimeZone(3 * ONE_HOUR, false);
assertEquals("T5. Incorrect offset returned, ",
(3 * ONE_HOUR), tz1.getOffset(time1));
assertEquals("T6. Incorrect offset returned, ",
(3 * ONE_HOUR), tz1.getOffset(time2));
}
/**
* @tests java.util.TimeZone#getTimeZone(java.lang.String)
*/
@Test
public void test_getTimeZoneLjava_lang_String() {
assertEquals("Must return GMT when given an invalid TimeZone id SMT-8.",
"GMT", TimeZone.getTimeZone("SMT-8").getID());
assertEquals("Must return GMT when given an invalid TimeZone time GMT+28:70.",
"GMT", TimeZone.getTimeZone("GMT+28:70").getID());
assertEquals("Must return GMT when given an invalid TimeZone time GMT+28:30.",
"GMT", TimeZone.getTimeZone("GMT+28:30").getID());
assertEquals("Must return GMT when given an invalid TimeZone time GMT+8:70.",
"GMT", TimeZone.getTimeZone("GMT+8:70").getID());
assertEquals("Must return GMT when given an invalid TimeZone time GMT+3:.",
"GMT", TimeZone.getTimeZone("GMT+3:").getID());
assertEquals("Must return GMT when given an invalid TimeZone time GMT+3:0.",
"GMT", TimeZone.getTimeZone("GMT+3:0").getID());
assertEquals("Must return GMT when given an invalid TimeZone time GMT+2360.",
"GMT", TimeZone.getTimeZone("GMT+2360").getID());
assertEquals("Must return GMT when given an invalid TimeZone time GMT+892.",
"GMT", TimeZone.getTimeZone("GMT+892").getID());
assertEquals("Must return GMT when given an invalid TimeZone time GMT+082.",
"GMT", TimeZone.getTimeZone("GMT+082").getID());
assertEquals("Must return GMT when given an invalid TimeZone time GMT+28.",
"GMT", TimeZone.getTimeZone("GMT+28").getID());
assertEquals("Must return GMT when given an invalid TimeZone time GMT+30.",
"GMT", TimeZone.getTimeZone("GMT+30").getID());
assertEquals("Must return GMT when given TimeZone GMT.",
"GMT", TimeZone.getTimeZone("GMT").getID());
assertEquals("Must return GMT when given TimeZone GMT+.",
"GMT", TimeZone.getTimeZone("GMT+").getID());
assertEquals("Must return GMT when given TimeZone GMT-.",
"GMT", TimeZone.getTimeZone("GMT-").getID());
assertEquals("Must return GMT when given an invalid TimeZone time GMT-8.45.",
"GMT", TimeZone.getTimeZone("GMT-8.45").getID());
assertEquals("Must return GMT when given an invalid TimeZone time GMT-123:23.",
"GMT", TimeZone.getTimeZone("GMT-123:23").getID());
assertEquals("Must return proper GMT formatted string for GMT+8:30 (eg. GMT+08:20).",
"GMT+08:30", TimeZone.getTimeZone("GMT+8:30").getID());
assertEquals("Must return proper GMT formatted string for GMT+3 (eg. GMT+08:20).",
"GMT+03:00", TimeZone.getTimeZone("GMT+3").getID());
assertEquals("Must return proper GMT formatted string for GMT+3:02 (eg. GMT+08:20).",
"GMT+03:02", TimeZone.getTimeZone("GMT+3:02").getID());
assertEquals("Must return proper GMT formatted string for GMT+2359 (eg. GMT+08:20).",
"GMT+23:59", TimeZone.getTimeZone("GMT+2359").getID());
assertEquals("Must return proper GMT formatted string for GMT+520 (eg. GMT+08:20).",
"GMT+05:20", TimeZone.getTimeZone("GMT+520").getID());
assertEquals("Must return proper GMT formatted string for GMT+052 (eg. GMT+08:20).",
"GMT+00:52", TimeZone.getTimeZone("GMT+052").getID());
// GMT-0 is an available ID in ICU, so replace it with GMT-00
assertEquals("Must return proper GMT formatted string for GMT-00 (eg. GMT+08:20).",
"GMT-00:00", TimeZone.getTimeZone("GMT-00").getID());
}
/**
* @tests java.util.TimeZone#setDefault(java.util.TimeZone)
*/
@Test
public void test_setDefaultLjava_util_TimeZone() {
TimeZone oldDefault = TimeZone.getDefault();
TimeZone zone = new SimpleTimeZone(45, "TEST");
TimeZone.setDefault(zone);
assertEquals("timezone not set", zone, TimeZone.getDefault());
TimeZone.setDefault(null);
assertEquals("default not restored",
oldDefault, TimeZone.getDefault());
}
/**
* @tests java.util.TimeZone#getDisplayName(java.util.Locale)
*/
//@Test
//public void test_getDisplayNameLjava_util_Locale() {
// TimeZone timezone = TimeZone.getTimeZone("Asia/Shanghai");
// assertEquals("\u4e2d\u56fd\u6807\u51c6\u65f6\u95f4", timezone
// .getDisplayName(Locale.CHINA));
// }
/**
* @tests java.util.TimeZone#getDisplayName(boolean, int, java.util.Locale)
*/
//@Test
//public void test_getDisplayNameZILjava_util_Locale() {
// TimeZone timezone = TimeZone.getTimeZone("Asia/Shanghai");
// assertEquals("\u683c\u6797\u5c3c\u6cbb\u6807\u51c6\u65f6\u95f4+0800",
// timezone.getDisplayName(false, TimeZone.SHORT, Locale.CHINA));
// try {
// timezone.getDisplayName(false, 100, Locale.CHINA);
// fail("should throw IllegalArgumentException");
// } catch (IllegalArgumentException e) {
// // expected
// }
//}
/*
* Regression for HARMONY-5860
*/
@Test
public void test_GetTimezoneOffset() {
// America/Toronto is lazy initialized
TimeZone.setDefault(TimeZone.getTimeZone("America/Toronto"));
Date date = new Date(07, 2, 24);
assertEquals(300, date.getTimezoneOffset());
date = new Date(99, 8, 1);
assertEquals(240, date.getTimezoneOffset());
}
protected void setUp() {
TimeZone.setDefault(TimeZone.getTimeZone(PlatformTimezone.getPlatformTimezoneId()));
}
protected void tearDown() {
TimeZone.setDefault(TimeZone.getTimeZone(PlatformTimezone.getPlatformTimezoneId()));
}
/**
* @add test {@link java.util.TimeZone#getAvailableIDs(int)}
*/
@Test
public void test_getAvailableIDs_I() {
TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai");
int rawoffset = tz.getRawOffset();
String[] ids = TimeZone.getAvailableIDs(rawoffset);
List<String> idList = Arrays.asList(ids);
assertTrue("Asia/shanghai and Hongkong should have the same rawoffset",
idList.contains("Hongkong"));
}
/**
* @add test {@link java.util.TimeZone#getDisplayName()}
*/
//@Test
//public void test_getDisplayName() {
// TimeZone defaultZone = TimeZone.getDefault();
// Locale defaulLocal = Locale.getDefault();
// String defaultName = defaultZone.getDisplayName();
// String expectedName = defaultZone.getDisplayName(defaulLocal);
// assertEquals(
// "getDispalyName() did not return the default Locale suitable name",
// expectedName, defaultName);
//}
/**
* @add test {@link java.util.TimeZone#getDisplayName(boolean, int)}
*/
//@Test
//public void test_getDisplayName_ZI() {
// TimeZone defaultZone = TimeZone.getDefault();
// Locale defaultLocale = Locale.getDefault();
// String actualName = defaultZone.getDisplayName(false, TimeZone.LONG);
// String expectedName = defaultZone.getDisplayName(false, TimeZone.LONG,
// defaultLocale);
// assertEquals(
// "getDisplayName(daylight,style) did not return the default locale suitable name",
// expectedName, actualName);
//}
/**
* @add test {@link java.util.TimeZone#hasSameRules(TimeZone)}
*/
//@Test
//public void test_hasSameRules_Ljava_util_TimeZone() {
// TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai");
// int offset = tz.getRawOffset();
//
// String[] ids = TimeZone.getAvailableIDs(offset);
// int i = 0;
// if (ids.length != 0) {
// while (true) {
// if (!(ids[i].equalsIgnoreCase(tz.getID()))) {
// TimeZone sameZone = TimeZone.getTimeZone(ids[i]);
// assertTrue(tz.hasSameRules(sameZone));
// break;
// } else {
// i++;
// }
// }
// }
// assertFalse("should return false when parameter is null", tz
// .hasSameRules(null));
//}
}