Added tests for timezone and calendar from Apache Harmony.

This commit is contained in:
Steve Hannah 2015-04-09 16:54:08 -07:00
parent c9819f3a86
commit 2bc1a99d53
7 changed files with 1700 additions and 61 deletions

View File

@ -321,6 +321,10 @@ public abstract class TCalendar implements TSerializable, TCloneable, TComparabl
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);
@ -392,6 +396,8 @@ public abstract class TCalendar implements TSerializable, TCloneable, TComparabl
lastTimeFieldSet = HOUR;
}
}
public final void set(int year, int month, int day) {
set(YEAR, year);

View File

@ -83,6 +83,11 @@ public class TGregorianCalendar extends TCalendar {
super(locale);
setTimeInMillis(System.currentTimeMillis());
}
public TGregorianCalendar(TTimeZone zone, TLocale locale){
this(locale);
setTimeZone(zone);
}
TGregorianCalendar(@SuppressWarnings("unused") boolean ignored) {
setFirstDayOfWeek(SUNDAY);

View File

@ -15,7 +15,11 @@
*/
package org.teavm.classlib.java.util;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.teavm.jso.JSBody;
import org.teavm.platform.PlatformTimezone;
/**
* TimeZone represents a time zone offset, and also figures out daylight savings.
@ -28,6 +32,76 @@ import org.teavm.jso.JSBody;
*/
public abstract class TTimeZone {
public static class GMT extends PlatformTimezone {
@Override
public String getTimezoneId() {
return "GMT";
}
@Override
public int getTimezoneOffset(int year, int month, int day, int timeOfDayMillis) {
return 0;
}
@Override
public int getTimezoneRawOffset() {
return 0;
}
@Override
public boolean isTimezoneDST(long millis) {
return false;
}
}
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;
TDate d = new TDate(year, month, day, hours, minutes, seconds);
return -TDate.getTimezoneOffset(d.getTime()) * 1000 * 60;
}
@Override
public int getTimezoneRawOffset() {
TDate now = new TDate();
TDate jan = new TDate(now.getYear(), 0, 1);
TDate jul = new TDate(now.getYear(), 6, 1);
if (isTimezoneDST(jan.getTime())){
return jul.getTimezoneOffset();
} else {
return jan.getTimezoneOffset();
}
}
@Override
public boolean isTimezoneDST(long millis) {
TDate now = new TDate();
TDate jan = new TDate(now.getYear(), 0, 1);
TDate jul = new TDate(now.getYear(), 6, 1);
int maxOffset = Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset());
return new Date(millis).getTimezoneOffset()<maxOffset;
}
}
static {
PlatformTimezone.addTimezone("GMT", new GMT());
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}.
@ -57,28 +131,47 @@ public abstract class TTimeZone {
* Gets all the available IDs supported.
*/
public static java.lang.String[] getAvailableIDs(){
String i = getTimezoneId();
if(i.equals("GMT")) {
return new String[] {"GMT"};//ZoneInfoDB.getAvailableIDs();
} else {
return new String[] {"GMT", i};
}
return PlatformTimezone.getAvailableIds();
}
@JSBody(params={},
script="return $rt_getTimezoneId(name,year,month,day,timeOfDayMillis)"
)
private static native String getTimezoneId();
@JSBody(params={"name","year","month","day","timeOfDayMillis"},
script="return $rt_getTimezoneOffset(name,year,month,day,timeOfDayMillis)")
private static native int getTimezoneOffset(String name, int year, int month, int day, int timeOfDayMillis);
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();
}
@JSBody(params="name",
script="return $rt_getTimezoneRawOffset(name)")
private static native int getTimezoneRawOffset(String name);
@JSBody(params={"name","millis"}, script="return $rt_isTimezoneDST(name,millis)")
private static native boolean isTimezoneDST(String name, long millis);
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);
}
/**
* Gets the default TimeZone for this host. The source of the default TimeZone may vary with implementation.
@ -110,6 +203,10 @@ public abstract class TTimeZone {
}
return defaultTimeZone;
}
public void setDefault(TTimeZone tz){
defaultTimeZone=tz;
}
int getDSTSavings() {
return useDaylightTime() ? 3600000 : 0;
@ -127,6 +224,15 @@ public abstract class TTimeZone {
return ID;
}
public int getOffset(long millis){
Date d = new Date(millis);
d.setHours(0);
d.setMinutes(0);
d.setSeconds(0);
return getOffset(0, d.getYear(), 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).
*/

View File

@ -529,49 +529,6 @@ function $rt_nativeThread() {
function $rt_invalidPointer() {
throw new Error("Invalid recorded state");
}
function $rt_getTimezoneId(){
return "LOCAL";
}
function $rt_getTimezoneOffset(name, year, month, day, timeOfDayMillis){
if ($rt_getTimezoneId()===name){
var hours = Math.floor(timeOfDayMillis/1000/60/60);
var minutes = Math.floor(timeOfDayMillis/1000/60)%60;
var seconds = Math.floor(timeOfDayMillis/1000)%60;
var millis = timeOfDayMillis % 1000;
return -(new Date(year, month, day, hours, minutes, seconds, millis).getTimezoneOffset()*1000*60);
} else if ("UTC"===name || "GMT"===name){
return 0;
} else {
throw new Error("Unsupported Timezone: "+name);
}
}
function $rt_getTimezoneRawOffset(name){
if ($rt_getTimezoneId()===name){
var millis = new Date().getTime();
var i=0;
var addDays = 1000 * 60 *60 * 24 * 200; // Check 200 days later
while ($rt_isTimezoneDST(name, millis) && i++<4){
millis += addDays;
}
return -(new Date(millis).getTimezoneOffset()*1000*60);
} else if (name==='GMT' || name==='UTC'){
return 0;
} else {
throw new Error("Unsupported Timezone: "+name);
}
}
function $rt_isTimezoneDST(name, millis){
if ($rt_getTimezoneId()===name){
var jan = new Date(this.getFullYear(), 0, 1);
var jul = new Date(this.getFullYear(), 6, 1);
var maxOff = Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset());
return new Date(millis).getTimezoneOffset()<maxOff;
} else if (name==='GMT' || name=='UTC'){
return false;
} else {
throw new Error("Unsupported Timezone: "+name);
}
}
function $dbg_repr(obj) {
return obj.toString ? obj.toString() : "";
}

View File

@ -0,0 +1,64 @@
/*
* Copyright 2015 Alexey Andreev.
*
* 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 {
private static String platformTimezoneId;
private static Map<String, PlatformTimezone> timezones;
private static Map<String, PlatformTimezone> timezones(){
if (timezones==null){
timezones = new HashMap<String, PlatformTimezone>();
}
return timezones;
}
public static PlatformTimezone getTimezone(String id){
return timezones().get(id);
}
public static void addTimezone(String id, PlatformTimezone tz){
timezones().put(id, tz);
}
public static String[] getAvailableIds(){
Set<String> keys = timezones().keySet();
return keys.toArray(new String[keys.size()]);
}
public static void setPlatformTimezoneId(String id){
platformTimezoneId=id;
}
public static String getPlatformTimezoneId(){
return platformTimezoneId;
}
public abstract String getTimezoneId();
public abstract int getTimezoneOffset(int year, int month, int day, int timeOfDayMillis);
public abstract int getTimezoneRawOffset();
public abstract boolean isTimezoneDST(long millis);
}

File diff suppressed because it is too large Load Diff

View File

@ -15,10 +15,393 @@
*/
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.Locale;
import java.util.SimpleTimeZone;
import java.util.TimeZone;
import org.junit.Test;
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;
}
}
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) {
return (int)(offset + (dst?ONE_HOUR:0));
}
@Override
public int getTimezoneRawOffset() {
return (int)offset;
}
@Override
public boolean isTimezoneDST(long millis) {
return dst;
}
}
private static class Support_TimeZone extends TimeZone {
int rawOffset;
boolean useDaylightTime;
public Support_TimeZone(int rawOffset, boolean useDaylightTime) {
this.rawOffset = rawOffset;
this.useDaylightTime = useDaylightTime;
}
@Override
public int getRawOffset() {
return rawOffset;
}
/**
* let's assume this timezone has daylight savings from the 4th month till
* the 10th month of the year to ame things simple.
*/
@Override
public boolean inDaylightTime(java.util.Date p1) {
if (!useDaylightTime) {
return false;
}
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(p1);
int month = cal.get(Calendar.MONTH);
if (month > 4 && month < 10) {
return true;
}
return false;
}
@Override
public boolean useDaylightTime() {
return useDaylightTime;
}
/*
* return 0 to keep it simple, since this subclass is not used to test this
* method..
*/
@Override
public int getOffset(int p1, int p2, int p3, int p4, int p5, int p6) {
return 0;
}
@Override
public void setRawOffset(int p1) {
rawOffset = p1;
}
}
static {
if (PlatformTimezone.getTimezone("EST")==null){
PlatformTimezone.addTimezone("EST", new EST());
}
}
/**
* @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 = new Support_TimeZone(-5 * ONE_HOUR, true);
assertEquals("T2. Incorrect daylight savings returned",
ONE_HOUR, tz1.getDSTSavings());
// an instance without daylight savings
tz1 = new Support_TimeZone(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 = new Support_TimeZone(-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 = new Support_TimeZone(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)
*/
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() {
}
protected void tearDown() {
}
/**
* @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));
//}
}