Implement Java time zone

This commit is contained in:
Alexey Andreev 2015-05-17 14:05:19 +03:00
parent c154a55ed5
commit 55212cbfe6
7 changed files with 739 additions and 24 deletions

View File

@ -0,0 +1,62 @@
/*
* 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.classlib.impl.tz;
import org.teavm.classlib.impl.Base46;
/**
*
* @author Alexey Andreev
*/
public class AliasDateTimeZone extends StorableDateTimeZone {
private DateTimeZone innerZone;
public AliasDateTimeZone(String id, DateTimeZone innerZone) {
super(id);
this.innerZone = innerZone;
}
@Override
public int getOffset(long instant) {
return innerZone.getOffset(instant);
}
@Override
public int getStandardOffset(long instant) {
return innerZone.getStandardOffset(instant);
}
@Override
public boolean isFixed() {
return innerZone.isFixed();
}
@Override
public long nextTransition(long instant) {
return innerZone.nextTransition(instant);
}
@Override
public long previousTransition(long instant) {
return innerZone.previousTransition(instant);
}
@Override
public void write(StringBuilder sb) {
Base46.encode(sb, ALIAS);
sb.append(innerZone.getID());
}
}

View File

@ -52,7 +52,7 @@ public class DateTimeZoneProvider {
CharFlow flow = new CharFlow(data.toCharArray()); CharFlow flow = new CharFlow(data.toCharArray());
if (Base46.decode(flow) == StorableDateTimeZone.ALIAS) { if (Base46.decode(flow) == StorableDateTimeZone.ALIAS) {
String aliasId = data.substring(flow.pointer); String aliasId = data.substring(flow.pointer);
return getTimeZone(aliasId); return new AliasDateTimeZone(id, getTimeZone(aliasId));
} else { } else {
return StorableDateTimeZone.read(id, data); return StorableDateTimeZone.read(id, data);
} }
@ -173,11 +173,11 @@ public class DateTimeZoneProvider {
areaName = ""; areaName = "";
locationName = id; locationName = id;
} }
ResourceMap<TimeZoneResource> area = getResource().get(areaName); if (!getResource().has(areaName)) {
if (area == null) {
return null; return null;
} }
return area.get(locationName); ResourceMap<TimeZoneResource> area = getResource().get(areaName);
return area.has(locationName) ? area.get(locationName) : null;
} }
@JSBody(params = "instant", script = "return new Date(instant).getTimezoneOffset();") @JSBody(params = "instant", script = "return new Date(instant).getTimezoneOffset();")

View File

@ -19,11 +19,9 @@ import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream; import java.util.zip.ZipInputStream;
import org.teavm.classlib.impl.Base46;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
import org.teavm.platform.metadata.MetadataGenerator; import org.teavm.platform.metadata.MetadataGenerator;
import org.teavm.platform.metadata.MetadataGeneratorContext; import org.teavm.platform.metadata.MetadataGeneratorContext;
@ -72,7 +70,6 @@ public class TimeZoneGenerator implements MetadataGenerator {
} }
Map<String, StorableDateTimeZone> zoneMap = compiler.compile(); Map<String, StorableDateTimeZone> zoneMap = compiler.compile();
Map<StorableDateTimeZone, String> zones = new HashMap<>();
for (String id : zoneMap.keySet()) { for (String id : zoneMap.keySet()) {
int sepIndex = id.indexOf('/'); int sepIndex = id.indexOf('/');
String areaName; String areaName;
@ -93,14 +90,7 @@ public class TimeZoneGenerator implements MetadataGenerator {
StorableDateTimeZone tz = zoneMap.get(id); StorableDateTimeZone tz = zoneMap.get(id);
TimeZoneResource tzRes = context.createResource(TimeZoneResource.class); TimeZoneResource tzRes = context.createResource(TimeZoneResource.class);
StringBuilder data = new StringBuilder(); StringBuilder data = new StringBuilder();
String knownId = zones.get(tz); tz.write(data);
if (knownId == null) {
tz.write(data);
zones.put(tz, id);
} else {
Base46.encode(data, StorableDateTimeZone.ALIAS);
data.append(knownId);
}
tzRes.setData(data.toString()); tzRes.setData(data.toString());
area.put(locationName, tzRes); area.put(locationName, tzRes);
} }

View File

@ -262,7 +262,7 @@ public class ZoneInfoCompiler {
alias + "' to"); alias + "' to");
}*/ }*/
} else { } else {
map.put(alias, tz); map.put(alias, new AliasDateTimeZone(alias, tz));
} }
} }
} }

View File

@ -0,0 +1,75 @@
/*
* 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.classlib.java.util;
import org.teavm.classlib.impl.tz.DateTimeZone;
/**
*
* @author Alexey Andreev
*/
class TIANATimeZone extends TTimeZone {
private static final long serialVersionUID = -8196006595542230951L;
private DateTimeZone underlyingZone;
private int rawOffset;
public TIANATimeZone(DateTimeZone underlyingZone) {
super(underlyingZone.getID());
this.underlyingZone = underlyingZone;
}
@Override
public int getOffset(int era, int year, int month, int day, int dayOfWeek, int time) {
TCalendar calendar = new TGregorianCalendar(year, month, day);
calendar.set(TCalendar.ERA, era);
calendar.set(TCalendar.DAY_OF_WEEK, dayOfWeek);
calendar.add(TCalendar.MILLISECOND, time);
return getOffset(calendar.getTimeInMillis());
}
@Override
public int getOffset(long time) {
return rawOffset + underlyingZone.getOffset(time);
}
@Override
public int getRawOffset() {
return rawOffset;
}
@Override
public boolean inDaylightTime(TDate time) {
return underlyingZone.getOffset(time.getTime()) != underlyingZone.getStandardOffset(time.getTime());
}
@Override
public void setRawOffset(int offset) {
this.rawOffset = offset;
}
@Override
public boolean useDaylightTime() {
return true;
}
@Override
public TIANATimeZone clone() {
TIANATimeZone copy = (TIANATimeZone)super.clone();
copy.rawOffset = rawOffset;
copy.underlyingZone = underlyingZone;
return copy;
}
}

View File

@ -0,0 +1,473 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.io.Serializable;
import java.util.Arrays;
import org.teavm.classlib.impl.tz.DateTimeZone;
import org.teavm.classlib.impl.tz.DateTimeZoneProvider;
import org.teavm.classlib.impl.tz.FixedDateTimeZone;
/**
* {@code TimeZone} represents a time zone offset, taking into account
* daylight savings.
* <p>
* Typically, you get a {@code TimeZone} using {@code getDefault}
* which creates a {@code TimeZone} based on the time zone where the
* program is running. For example, for a program running in Japan,
* {@code getDefault} creates a {@code TimeZone} object based on
* Japanese Standard Time.
* <p>
* You can also get a {@code TimeZone} using {@code getTimeZone}
* along with a time zone ID. For instance, the time zone ID for the U.S.
* Pacific Time zone is "America/Los_Angeles". So, you can get a U.S. Pacific
* Time {@code TimeZone} object with the following: <blockquote>
*
* <pre>
* TimeZone tz = TimeZone.getTimeZone(&quot;America/Los_Angeles&quot;);
* </pre>
*
* </blockquote> You can use the {@code getAvailableIDs} method to iterate
* through all the supported time zone IDs. You can then choose a supported ID
* to get a {@code TimeZone}. If the time zone you want is not
* represented by one of the supported IDs, then you can create a custom time
* zone ID with the following syntax: <blockquote>
*
* <pre>
* GMT[+|-]hh[[:]mm]
* </pre>
*
* </blockquote> For example, you might specify GMT+14:00 as a custom time zone
* ID. The {@code TimeZone} that is returned when you specify a custom
* time zone ID does not include daylight savings time.
* <p>
* For compatibility with JDK 1.1.x, some other three-letter time zone IDs (such
* as "PST", "CTT", "AST") are also supported. However, <strong>their use is
* deprecated</strong> because the same abbreviation is often used for multiple
* time zones (for example, "CST" could be U.S. "Central Standard Time" and
* "China Standard Time"), and the Java platform can then only recognize one of
* them.
* <p>
* Please note the type returned by factory methods, i.e. {@code getDefault()}
* and {@code getTimeZone(String)}, is implementation dependent, so it may
* introduce serialization incompatibility issues between different
* implementations.
*
* @see GregorianCalendar
* @see TSimpleTimeZone
*/
public abstract class TTimeZone implements Serializable, Cloneable {
private static final long serialVersionUID = 3581463369166924961L;
/**
* The SHORT display name style.
*/
public static final int SHORT = 0;
/**
* The LONG display name style.
*/
public static final int LONG = 1;
private static TTimeZone Default;
static TTimeZone GMT = new TIANATimeZone(new FixedDateTimeZone("GMT", 0, 0));
private String ID;
/**
* Constructs a new instance of this class.
*/
public TTimeZone() {
}
TTimeZone(String id) {
this.ID = id;
}
/**
* Returns a new {@code TimeZone} with the same ID, {@code rawOffset} and daylight savings
* time rules as this {@code TimeZone}.
*
* @return a shallow copy of this {@code TimeZone}.
* @see java.lang.Cloneable
*/
@Override
public Object clone() {
try {
TTimeZone zone = (TTimeZone) super.clone();
return zone;
} catch (CloneNotSupportedException e) {
return null;
}
}
/**
* Gets the available time zone IDs. Any one of these IDs can be passed to
* {@code get()} to create the corresponding {@code TimeZone} instance.
*
* @return an array of time zone ID strings.
*/
public static String[] getAvailableIDs() {
return DateTimeZoneProvider.getIds();
}
/**
* Gets the available time zone IDs which match the specified offset from
* GMT. Any one of these IDs can be passed to {@code get()} to create the corresponding
* {@code TimeZone} instance.
*
* @param offset
* the offset from GMT in milliseconds.
* @return an array of time zone ID strings.
*/
public static String[] getAvailableIDs(int offset) {
String[] all = DateTimeZoneProvider.getIds();
String[] result = new String[all.length];
int i = 0;
for (String id : all) {
DateTimeZone jodaTz = DateTimeZoneProvider.getTimeZone(id);
if (jodaTz.getStandardOffset(System.currentTimeMillis()) == offset) {
result[i++] = id;
}
}
return Arrays.copyOf(result, i);
}
/**
* Gets the default time zone.
*
* @return the default time zone.
*/
public static TTimeZone getDefault() {
if (Default == null) {
Default = new TIANATimeZone(DateTimeZoneProvider.detectTimezone());
}
return (TTimeZone) Default.clone();
}
/**
* Gets the LONG name for this {@code TimeZone} for the default {@code Locale} in standard
* time. If the name is not available, the result is in the format
* {@code GMT[+-]hh:mm}.
*
* @return the {@code TimeZone} name.
*/
public final String getDisplayName() {
return getDisplayName(false, LONG, TLocale.getDefault());
}
/**
* Gets the LONG name for this {@code TimeZone} for the specified {@code Locale} in standard
* time. If the name is not available, the result is in the format
* {@code GMT[+-]hh:mm}.
*
* @param locale
* the {@code Locale}.
* @return the {@code TimeZone} name.
*/
public final String getDisplayName(TLocale locale) {
return getDisplayName(false, LONG, locale);
}
/**
* Gets the specified style of name ({@code LONG} or {@code SHORT}) for this {@code TimeZone} for
* the default {@code Locale} in either standard or daylight time as specified. If
* the name is not available, the result is in the format {@code GMT[+-]hh:mm}.
*
* @param daylightTime
* {@code true} for daylight time, {@code false} for standard
* time.
* @param style
* either {@code LONG} or {@code SHORT}.
* @return the {@code TimeZone} name.
*/
public final String getDisplayName(boolean daylightTime, int style) {
return getDisplayName(daylightTime, style, TLocale.getDefault());
}
/**
* Gets the specified style of name ({@code LONG} or {@code SHORT}) for this {@code TimeZone} for
* the specified {@code Locale} in either standard or daylight time as specified. If
* the name is not available, the result is in the format {@code GMT[+-]hh:mm}.
*
* @param daylightTime
* {@code true} for daylight time, {@code false} for standard
* time.
* @param style
* either LONG or SHORT.
* @param locale
* either {@code LONG} or {@code SHORT}.
* @return the {@code TimeZone} name.
*/
public String getDisplayName(boolean daylightTime, int style, TLocale locale) {
// TODO: implement via CLDR
return null;
}
/**
* Gets the ID of this {@code TimeZone}.
*
* @return the time zone ID string.
*/
public String getID() {
return ID;
}
/**
* Gets the daylight savings offset in milliseconds for this {@code TimeZone}.
* <p>
* This implementation returns 3600000 (1 hour), or 0 if the time zone does
* not observe daylight savings.
* <p>
* Subclasses may override to return daylight savings values other than 1
* hour.
* <p>
*
* @return the daylight savings offset in milliseconds if this {@code TimeZone}
* observes daylight savings, zero otherwise.
*/
public int getDSTSavings() {
if (useDaylightTime()) {
return 3600000;
}
return 0;
}
/**
* Gets the offset from GMT of this {@code TimeZone} for the specified date. The
* offset includes daylight savings time if the specified date is within the
* daylight savings time period.
*
* @param time
* the date in milliseconds since January 1, 1970 00:00:00 GMT
* @return the offset from GMT in milliseconds.
*/
public int getOffset(long time) {
return inDaylightTime(new TDate(time)) ? getRawOffset() + getDSTSavings() : getRawOffset();
}
/**
* Gets the offset from GMT of this {@code TimeZone} for the specified date and
* time. The offset includes daylight savings time if the specified date and
* time are within the daylight savings time period.
*
* @param era
* the {@code GregorianCalendar} era, either {@code GregorianCalendar.BC} or
* {@code GregorianCalendar.AD}.
* @param year
* the year.
* @param month
* the {@code Calendar} month.
* @param day
* the day of the month.
* @param dayOfWeek
* the {@code Calendar} day of the week.
* @param time
* the time of day in milliseconds.
* @return the offset from GMT in milliseconds.
*/
abstract public int getOffset(int era, int year, int month, int day,
int dayOfWeek, int time);
/**
* Gets the offset for standard time from GMT for this {@code TimeZone}.
*
* @return the offset from GMT in milliseconds.
*/
abstract public int getRawOffset();
/**
* Gets the {@code TimeZone} with the specified ID.
*
* @param name
* a time zone string ID.
* @return the {@code TimeZone} with the specified ID or null if no {@code TimeZone} with
* the specified ID exists.
*/
public static TTimeZone getTimeZone(String name) {
DateTimeZone jodaZone = DateTimeZoneProvider.getTimeZone(name);
if (jodaZone != null) {
return new TIANATimeZone(jodaZone);
}
if (name.startsWith("GMT") && name.length() > 3) {
char sign = name.charAt(3);
if (sign == '+' || sign == '-') {
int[] position = new int[1];
String formattedName = formatTimeZoneName(name, 4);
int hour = parseNumber(formattedName, 4, position);
if (hour < 0 || hour > 23) {
return (TTimeZone) GMT.clone();
}
int index = position[0];
if (index != -1) {
int raw = hour * 3600000;
if (index < formattedName.length()
&& formattedName.charAt(index) == ':') {
int minute = parseNumber(formattedName, index + 1,
position);
if (position[0] == -1 || minute < 0 || minute > 59) {
return (TTimeZone) GMT.clone();
}
raw += minute * 60000;
} else if (hour >= 30 || index > 6) {
raw = (hour / 100 * 3600000) + (hour % 100 * 60000);
}
if (sign == '-') {
raw = -raw;
}
return new TIANATimeZone(new FixedDateTimeZone(formattedName, raw, raw));
}
}
}
return (TTimeZone) GMT.clone();
}
private static String formatTimeZoneName(String name, int offset) {
StringBuilder buf = new StringBuilder();
int index = offset, length = name.length();
buf.append(name.substring(0, offset));
while (index < length) {
if (Character.digit(name.charAt(index), 10) != -1) {
buf.append(name.charAt(index));
if ((length - (index + 1)) == 2) {
buf.append(':');
}
} else if (name.charAt(index) == ':') {
buf.append(':');
}
index++;
}
if (buf.toString().indexOf(":") == -1) {
buf.append(':');
buf.append("00");
}
if (buf.toString().indexOf(":") == 5) {
buf.insert(4, '0');
}
return buf.toString();
}
/**
* Returns whether the specified {@code TimeZone} has the same raw offset as this
* {@code TimeZone}.
*
* @param zone
* a {@code TimeZone}.
* @return {@code true} when the {@code TimeZone} have the same raw offset, {@code false}
* otherwise.
*/
public boolean hasSameRules(TTimeZone zone) {
if (zone == null) {
return false;
}
return getRawOffset() == zone.getRawOffset();
}
/**
* Returns whether the specified {@code Date} is in the daylight savings time period for
* this {@code TimeZone}.
*
* @param time
* a {@code Date}.
* @return {@code true} when the {@code Date} is in the daylight savings time period, {@code false}
* otherwise.
*/
abstract public boolean inDaylightTime(TDate time);
private static int parseNumber(String string, int offset, int[] position) {
int index = offset, length = string.length(), digit, result = 0;
while (index < length
&& (digit = Character.digit(string.charAt(index), 10)) != -1) {
index++;
result = result * 10 + digit;
}
position[0] = index == offset ? -1 : index;
return result;
}
/**
* Sets the default time zone. If passed {@code null}, then the next
* time {@link #getDefault} is called, the default time zone will be
* determined. This behavior is slightly different than the canonical
* description of this method, but it follows the spirit of it.
*
* @param timezone
* a {@code TimeZone} object.
*/
public static void setDefault(TTimeZone timezone) {
Default = timezone != null ? (TTimeZone)timezone.clone() : null;
}
/**
* Sets the ID of this {@code TimeZone}.
*
* @param name
* a string which is the time zone ID.
*/
public void setID(String name) {
if (name == null) {
throw new NullPointerException();
}
ID = name;
}
/**
* Sets the offset for standard time from GMT for this {@code TimeZone}.
*
* @param offset
* the offset from GMT in milliseconds.
*/
abstract public void setRawOffset(int offset);
/**
* Returns whether this {@code TimeZone} has a daylight savings time period.
*
* @return {@code true} if this {@code TimeZone} has a daylight savings time period, {@code false}
* otherwise.
*/
abstract public boolean useDaylightTime();
/**
* Gets the name and the details of the user-selected TimeZone on the
* device.
*
* @param tzinfo
* int array of 10 elements to be filled with the TimeZone
* information. Once filled, the contents of the array are
* formatted as follows: tzinfo[0] -> the timezone offset;
* tzinfo[1] -> the dst adjustment; tzinfo[2] -> the dst start
* hour; tzinfo[3] -> the dst start day of week; tzinfo[4] -> the
* dst start week of month; tzinfo[5] -> the dst start month;
* tzinfo[6] -> the dst end hour; tzinfo[7] -> the dst end day of
* week; tzinfo[8] -> the dst end week of month; tzinfo[9] -> the
* dst end month;
* @param isCustomTimeZone
* boolean array of size 1 that indicates if a timezone match is
* found
* @return the name of the TimeZone or null if error occurs in native
* method.
*/
private static native String getCustomTimeZone(int[] tzinfo,
boolean[] isCustomTimeZone);
}

View File

@ -1,21 +1,136 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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; package org.teavm.classlib.java.util;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import org.junit.Test; import org.junit.Test;
import org.teavm.classlib.impl.tz.DateTimeZone;
import org.teavm.classlib.impl.tz.DateTimeZoneProvider;
/** /**
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
public class TimeZoneTest { public class TimeZoneTest {
private static final int ONE_HOUR = 3600000;
@Test @Test
public void resourceProvided() { public void test_getDefault() {
DateTimeZone tz = DateTimeZoneProvider.getTimeZone("Europe/Moscow"); assertNotSame("returns identical", TimeZone.getDefault(), TimeZone.getDefault());
assertEquals(1414274399999L, tz.previousTransition(1431781727159L)); }
assertEquals(1301183999999L, tz.previousTransition(1414274399999L));
assertEquals(1288479599999L, tz.previousTransition(1301183999999L)); @Test
System.out.println(DateTimeZoneProvider.detectTimezone().getID()); 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
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());
}
@Test
public void test_getDisplayNameLjava_util_Locale() {
TimeZone timezone = TimeZone.getTimeZone("Asia/Shanghai");
assertEquals("\u4e2d\u56fd\u6807\u51c6\u65f6\u95f4", timezone.getDisplayName(Locale.CHINA));
}
@Test
public void test_GetTimezoneOffset() {
TimeZone tz = TimeZone.getTimeZone("America/Toronto");
Date date = new GregorianCalendar(2006, 2, 24).getTime();
assertEquals(-300 * 60_000, tz.getOffset(date.getTime()));
date = new GregorianCalendar(1999, 8, 1).getTime();
assertEquals(-240 * 60_000, tz.getOffset(date.getTime()));
}
@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);
}
@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);
} }
} }