diff --git a/jre_emul/Classes/com/google/j2objc/util/NativeTimeZone.java b/jre_emul/Classes/com/google/j2objc/util/NativeTimeZone.java new file mode 100644 index 0000000000..11fdd15218 --- /dev/null +++ b/jre_emul/Classes/com/google/j2objc/util/NativeTimeZone.java @@ -0,0 +1,243 @@ +/* + * 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 com.google.j2objc.util; + +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +/*-[ +#import "IOSClass.h" +#import "java/lang/IllegalArgumentException.h" +#import "java/util/GregorianCalendar.h" +#import "java/util/GregorianCalendar.h" +]-*/ + +/** + * An NSTimeZone-backed concrete TimeZone implementation that provides daylight saving time (DST) + * and historical time zone offsets from the native iOS/OS X time zone database. + * + * @author Lukhnos Liu + */ +public final class NativeTimeZone extends TimeZone { + + private final Object nativeTimeZone; + private final int rawOffset; + private final int dstSavings; + private final boolean useDaylightTime; + + public static native String[] getAvailableNativeTimeZoneNames() /*-[ + NSArray *timeZones = [NSTimeZone knownTimeZoneNames]; + return [IOSObjectArray arrayWithNSArray:timeZones type:NSString_class_()]; + ]-*/; + + + public static native NativeTimeZone get(String name) /*-[ + NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:name]; + if (timeZone == nil) { + return nil; + } + return [ComGoogleJ2objcUtilNativeTimeZone getWithNativeTimeZoneWithId:timeZone]; + ]-*/; + + public static native NativeTimeZone getDefaultNativeTimeZone() /*-[ + NSTimeZone *timeZone = [NSTimeZone defaultTimeZone]; + if (timeZone == nil) { // Unlikely, but just to be defensive. + return nil; + } + return [ComGoogleJ2objcUtilNativeTimeZone getWithNativeTimeZoneWithId:timeZone]; + ]-*/; + + public static native NativeTimeZone getWithNativeTimeZone(Object nativeTimeZone) /*-[ + NSTimeZone *tz = (NSTimeZone *)nativeTimeZone; + NSDate *now = [NSDate date]; + NSInteger offset = [tz secondsFromGMTForDate:now]; + NSTimeInterval dstOffset = [tz daylightSavingTimeOffsetForDate:now]; + + // The DST offset is relative to the current offset, and hence the math here. + jint rawOffset = (jint)(offset * 1000) - (jint)(dstOffset * 1000.0); + + NSDate *nextTransition = [tz nextDaylightSavingTimeTransitionAfterDate:now]; + jint dstSavings; + jboolean useDaylightTime; + if (nextTransition) { + NSTimeInterval nextDstOffset = [tz daylightSavingTimeOffsetForDate:nextTransition]; + + // This is a simplified assumption. Technically, there's nothing in the TZ rules + // that says you can't have a +1 transition tomorrow, and a +2 the day after. This + // is why in more modern time libraries, there is no longer the notion of a fixed + // DST offset. + NSTimeInterval fixedDstOffset = (dstOffset != 0) ? dstOffset : nextDstOffset; + + // And the offset is always positive regardless the hemisphere the TZ is in. + dstSavings = fabs(fixedDstOffset) * 1000; + useDaylightTime = true; + } else { + dstSavings = 0; + useDaylightTime = false; + } + + return + create_ComGoogleJ2objcUtilNativeTimeZone_initWithId_withNSString_withInt_withInt_withBoolean_( + nativeTimeZone, tz.name, rawOffset, dstSavings, useDaylightTime); + ]-*/; + + /** + * Create an NSTimeZone-backed TimeZone instance. + * + * @param nativeTimeZone the NSTimeZone instance. + * @param name the native time zone's name. + * @param rawOffset the pre-calculated raw offset (in millis) from UTC. When TimeZone was + * designed, the assumption was that the rawOffset would be a constant at + * all times. We pre-compute this offset using the instant when the + * instance is created. + * @param useDaylightTime whether this time zone observes DST at the moment this instance + * is created. + */ + private NativeTimeZone(Object nativeTimeZone, String name, int rawOffset, int dstSavings, + boolean useDaylightTime) { + setID(name); + this.nativeTimeZone = nativeTimeZone; + this.rawOffset = rawOffset; + this.dstSavings = dstSavings; + this.useDaylightTime = useDaylightTime; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof NativeTimeZone)) { + return false; + } + + return nativeTimeZone.equals(((NativeTimeZone) obj).nativeTimeZone); + } + + @Override + public native int hashCode() /*-[ + return [nativeTimeZone_ hash]; + ]-*/; + + @Override + public boolean hasSameRules(TimeZone other) { + if (other instanceof NativeTimeZone) { + return compareNativeTimeZoneRules(((NativeTimeZone) other).nativeTimeZone); + } + return super.hasSameRules(other); + } + + @Override + public native int getOffset(long time) /*-[ + double interval = (double)time / 1000.0; + NSDate *date = [NSDate dateWithTimeIntervalSince1970:interval]; + return (jint)[(NSTimeZone *)nativeTimeZone_ secondsFromGMTForDate:date] * 1000; + ]-*/; + + @Override + public native int getOffset(int era, int year, int month, int day, int dayOfWeek, + int milliseconds) /*-[ + if (era != JavaUtilGregorianCalendar_BC && era != JavaUtilGregorianCalendar_AD) { + @throw [[[JavaLangIllegalArgumentException alloc] + initWithNSString:@"Only GregorianCalendar.BCE or GregorianCalendar.AD allowed"] + autorelease]; + } + + // The local datetime used here is always in the non-DST time zone, i.e. the time zone + // with the "raw" offset, as evidenced by actual JDK and Android implementations. This + // means it's possible to getOffset from a practically non-existent date time, such as + // 2:30 AM, March 13, 2016, which does not exist in US Pacific Time -- it falls in the + // DST gap of that day. The accommodation here is for quirk-compatibility. + NSCalendar *calendar = [[[NSCalendar alloc] + initWithCalendarIdentifier:NSCalendarIdentifierGregorian] autorelease]; + calendar.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:rawOffset_ / 1000]; + + NSInteger nano = (milliseconds % 1000) * 1000000; + NSInteger sec = (milliseconds / 1000) % 60; + NSInteger min = (milliseconds / 60000) % 60; + NSInteger hour = milliseconds / 3600000; + + // Recall JDK Calendar uses 0-based month. dayOfWeek is ignored here. + NSDate *date = [calendar dateWithEra:era year:year month:(month + 1) day:day hour:hour + minute:min second:sec nanosecond:nano]; + return (jint)[(NSTimeZone *)nativeTimeZone_ secondsFromGMTForDate:date] * 1000; + ]-*/; + + @Override + public int getRawOffset() { + return rawOffset; + } + + @Override + public void setRawOffset(int offsetMillis) { + throw new UnsupportedOperationException("Cannot set raw offset on a native TimeZone"); + } + + @Override + public int getDSTSavings() { + return dstSavings; + } + + @Override + public boolean useDaylightTime() { + return useDaylightTime; + } + + @Override + public boolean inDaylightTime(Date date) { + return getOffset(date.getTime()) != rawOffset; + } + + @Override + public native String getDisplayName(boolean daylight, int style, Locale locale) /*-[ + if (style != JavaUtilTimeZone_SHORT && style != JavaUtilTimeZone_LONG) { + @throw [[[JavaLangIllegalArgumentException alloc] init] autorelease]; + } + + NSTimeZoneNameStyle zoneStyle; + + // "daylight" is defined in , hence the renaming. + if (daylight_ && useDaylightTime_) { + zoneStyle = (style == JavaUtilTimeZone_SHORT) ? + NSTimeZoneNameStyleShortDaylightSaving : NSTimeZoneNameStyleDaylightSaving; + } else { + zoneStyle = (style == JavaUtilTimeZone_SHORT) ? + NSTimeZoneNameStyleShortStandard : NSTimeZoneNameStyleStandard; + } + + // Find native locale. + NSLocale *nativeLocale; + if (locale) { + NSMutableDictionary *components = [NSMutableDictionary dictionary]; + [components setObject:[locale getLanguage] forKey:NSLocaleLanguageCode]; + [components setObject:[locale getCountry] forKey:NSLocaleCountryCode]; + [components setObject:[locale getVariant] forKey:NSLocaleVariantCode]; + NSString *localeId = [NSLocale localeIdentifierFromComponents:components]; + nativeLocale = AUTORELEASE([[NSLocale alloc] initWithLocaleIdentifier:localeId]); + } else { + nativeLocale = [NSLocale currentLocale]; + } + return [(NSTimeZone *) nativeTimeZone_ localizedName:zoneStyle locale:nativeLocale]; + ]-*/; + + private native boolean compareNativeTimeZoneRules(Object otherNativeTimeZone) /*-[ + // [NSTimeZone isEqualToTimeZone:] also compares names, which we don't want. Since we + // only deal with native time zones that can be obtained with known names, we'll just + // compare the underlying data. + NSTimeZone *other = (NSTimeZone *)otherNativeTimeZone; + return [((NSTimeZone *)self->nativeTimeZone_).data isEqualToData:other.data]; + ]-*/; +} diff --git a/jre_emul/JreEmulation.xcodeproj/project.pbxproj b/jre_emul/JreEmulation.xcodeproj/project.pbxproj index fdd23f268f..e606b19e82 100644 --- a/jre_emul/JreEmulation.xcodeproj/project.pbxproj +++ b/jre_emul/JreEmulation.xcodeproj/project.pbxproj @@ -638,6 +638,9 @@ 514171471BED5CAE0044F0FD /* MockHomonymySubjectBeanInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 514171461BED5CAE0044F0FD /* MockHomonymySubjectBeanInfo.m */; }; 514171491BED5CD70044F0FD /* MockHomonymySubjectBeanInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 514171481BED5CD70044F0FD /* MockHomonymySubjectBeanInfo.m */; }; 6AC258CB1CB4CE1F00AF82C9 /* LinkedListTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6AC258CA1CB4CDA200AF82C9 /* LinkedListTest.m */; }; + 6AF8A35D1D07763800B4CA82 /* NativeTimeZoneTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6AF8A35C1D07761D00B4CA82 /* NativeTimeZoneTest.m */; }; + 6AF8A3621D0776D000B4CA82 /* StringTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6AF8A3611D07769100B4CA82 /* StringTest.m */; }; + 6AF8A3631D0776D900B4CA82 /* RetainedWithTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6AF8A35F1D07769100B4CA82 /* RetainedWithTest.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -4041,6 +4044,14 @@ 51719E5318EEDDCE006DEEB7 /* IOSPrimitiveArray.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IOSPrimitiveArray.h; sourceTree = ""; }; 51719E5418EEDDCE006DEEB7 /* IOSPrimitiveArray.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IOSPrimitiveArray.m; sourceTree = ""; }; 6AC258CA1CB4CDA200AF82C9 /* LinkedListTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LinkedListTest.m; path = com/google/j2objc/LinkedListTest.m; sourceTree = ""; }; + 6AF8A35B1D07761D00B4CA82 /* NativeTimeZoneTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeTimeZoneTest.h; path = com/google/j2objc/util/NativeTimeZoneTest.h; sourceTree = ""; }; + 6AF8A35C1D07761D00B4CA82 /* NativeTimeZoneTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NativeTimeZoneTest.m; path = com/google/j2objc/util/NativeTimeZoneTest.m; sourceTree = ""; }; + 6AF8A35E1D07769100B4CA82 /* RetainedWithTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RetainedWithTest.h; path = com/google/j2objc/RetainedWithTest.h; sourceTree = ""; }; + 6AF8A35F1D07769100B4CA82 /* RetainedWithTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RetainedWithTest.m; path = com/google/j2objc/RetainedWithTest.m; sourceTree = ""; }; + 6AF8A3601D07769100B4CA82 /* StringTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringTest.h; path = com/google/j2objc/StringTest.h; sourceTree = ""; }; + 6AF8A3611D07769100B4CA82 /* StringTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StringTest.m; path = com/google/j2objc/StringTest.m; sourceTree = ""; }; + 6AF8A60A1D08B42F00B4CA82 /* NativeTimeZone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeTimeZone.h; path = build_result/Classes/com/google/j2objc/util/NativeTimeZone.h; sourceTree = ""; }; + 6AF8A60B1D08B42F00B4CA82 /* NativeTimeZone.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NativeTimeZone.m; path = build_result/Classes/com/google/j2objc/util/NativeTimeZone.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -5521,6 +5532,8 @@ 068677D3166C342C005A5AD7 /* NavigableMap.m */, 068677D4166C342C005A5AD7 /* NavigableSet.h */, 068677D5166C342C005A5AD7 /* NavigableSet.m */, + 6AF8A60A1D08B42F00B4CA82 /* NativeTimeZone.h */, + 6AF8A60B1D08B42F00B4CA82 /* NativeTimeZone.m */, 0649A69C1AE0780500DE2494 /* NClob.h */, 0649A69D1AE0780500DE2494 /* NClob.m */, 06721B4D1559CC0300645E1B /* NegativeArraySizeException.h */, @@ -6712,6 +6725,8 @@ 06574A301A8EB04A000A3616 /* MyMessageDigest1.m */, 06574A311A8EB04A000A3616 /* MySignature1.m */, 06979BA31C220A0C00803967 /* NativeDecimalFormatTest.m */, + 6AF8A35B1D07761D00B4CA82 /* NativeTimeZoneTest.h */, + 6AF8A35C1D07761D00B4CA82 /* NativeTimeZoneTest.m */, 06E4844E1C99EB1B00ABD06B /* NativeUtil.m */, 06FADA7C1B3B29B300A9579E /* NoPackageTest.h */, 06FADA7D1B3B29B300A9579E /* NoPackageTest.m */, @@ -6762,6 +6777,8 @@ 06C54AD71A40C897004B3ACD /* ReflectionTest.m */, 06DCD8C81CD7CAE100B855AF /* ReflectionTests.h */, 06DCD8C91CD7CAE100B855AF /* ReflectionTests.m */, + 6AF8A35E1D07769100B4CA82 /* RetainedWithTest.h */, + 6AF8A35F1D07769100B4CA82 /* RetainedWithTest.m */, 06574A761A8EB150000A3616 /* RSAKeyGenParameterSpecTest.m */, 06574A651A8EB150000A3616 /* RSAKeyTest.m */, 06574A771A8EB150000A3616 /* RSAMultiPrimePrivateCrtKeySpecTest.m */, @@ -6801,6 +6818,8 @@ 06C54ACA1A40C0D8004B3ACD /* StrictMathTest.m */, 06E685D71A2FC550006F8791 /* StringBuilderTest.h */, 06E685D81A2FC550006F8791 /* StringBuilderTest.m */, + 6AF8A3601D07769100B4CA82 /* StringTest.h */, + 6AF8A3611D07769100B4CA82 /* StringTest.m */, 0600C00E1B715CB4005FDEF9 /* SuperMethodReferenceTest.h */, 0600C00F1B715CB4005FDEF9 /* SuperMethodReferenceTest.m */, 06574A7E1A8EB150000A3616 /* Support_Configuration.m */, @@ -8588,7 +8607,9 @@ 06E4E7C5197F1D48005DDE69 /* NoSuchElementExceptionTest.m in Sources */, 061AA0D519FEF2E700457D2B /* TestAnnotation.m in Sources */, 0615D3EE1BD83E7300132067 /* FakeFox01.m in Sources */, + 6AF8A3631D0776D900B4CA82 /* RetainedWithTest.m in Sources */, 06574A621A8EB081000A3616 /* package-info.m in Sources */, + 6AF8A3621D0776D000B4CA82 /* StringTest.m in Sources */, 0696811A1BA8E3D3007AFADF /* Third.m in Sources */, 0615D3E21BD83E7300132067 /* FeatureDescriptorTest.m in Sources */, 06E4E6FA197F1D47005DDE69 /* OldAndroidStreamTokenizerTest.m in Sources */, @@ -8663,6 +8684,7 @@ 06E4E73A197F1D47005DDE69 /* SmallTests.m in Sources */, 06E4E6E6197F1D47005DDE69 /* FileTest.m in Sources */, 06E4E715197F1D47005DDE69 /* OldObjectInputStreamGetFieldTest.m in Sources */, + 6AF8A35D1D07763800B4CA82 /* NativeTimeZoneTest.m in Sources */, 06E4E75C197F1D47005DDE69 /* GZIPOutputStreamTest.m in Sources */, 06E4E6E9197F1D47005DDE69 /* OldAndroidBufferedInputStreamTest.m in Sources */, 06C54AE11A40CA75004B3ACD /* AttributedCharacterIteratorAttributeTest.m in Sources */, diff --git a/jre_emul/Tests/com/google/j2objc/util/NativeTimeZoneTest.java b/jre_emul/Tests/com/google/j2objc/util/NativeTimeZoneTest.java new file mode 100644 index 0000000000..82c24f5859 --- /dev/null +++ b/jre_emul/Tests/com/google/j2objc/util/NativeTimeZoneTest.java @@ -0,0 +1,446 @@ +/* + * 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 com.google.j2objc.util; + +import junit.framework.TestCase; + +import java.util.Arrays; +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.List; +import java.util.Locale; +import java.util.TimeZone; + +/** + * Test the NSTimeZone-backed TimeZone implementation class. + * + * The testing strategy here is by no means comprehensive, but suffices for catching regressions: + * if the underlying concrete TimeZone subclass is not based on a time zone database, it will not be + * able to handle US time zone changes in 2005 as well as the historical transitions in Australia. + * + * @author Lukhnos Liu + */ +public class NativeTimeZoneTest extends TestCase { + + /** + * Test that the TimeZone instance returns accurate offsets for instants in America/Los_Angeles + * (commonly known as PT, which includes PST and PDT). This also accounts for the daylight + * saving time (DST) change due to Energy Policy Act of 2005. + */ + public void testUSPacificTimeZoneTransitionsSince1970() { + TimeZone la = TimeZone.getTimeZone("America/Los_Angeles"); + assertEquals(-25200000, la.getOffset(1457863200000L)); // 2016-03-13T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(1446368400000L)); // 2015-11-01T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(1425808800000L)); // 2015-03-08T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(1414918800000L)); // 2014-11-02T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(1394359200000L)); // 2014-03-09T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(1383469200000L)); // 2013-11-03T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(1362909600000L)); // 2013-03-10T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(1352019600000L)); // 2012-11-04T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(1331460000000L)); // 2012-03-11T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(1320570000000L)); // 2011-11-06T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(1300010400000L)); // 2011-03-13T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(1289120400000L)); // 2010-11-07T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(1268560800000L)); // 2010-03-14T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(1257066000000L)); // 2009-11-01T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(1236506400000L)); // 2009-03-08T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(1225616400000L)); // 2008-11-02T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(1205056800000L)); // 2008-03-09T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(1194166800000L)); // 2007-11-04T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(1173607200000L)); // 2007-03-11T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(1162112400000L)); // 2006-10-29T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(1143972000000L)); // 2006-04-02T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(1130662800000L)); // 2005-10-30T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(1112522400000L)); // 2005-04-03T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(1099213200000L)); // 2004-10-31T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(1081072800000L)); // 2004-04-04T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(1067158800000L)); // 2003-10-26T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(1049623200000L)); // 2003-04-06T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(1035709200000L)); // 2002-10-27T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(1018173600000L)); // 2002-04-07T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(1004259600000L)); // 2001-10-28T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(986119200000L)); // 2001-04-01T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(972810000000L)); // 2000-10-29T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(954669600000L)); // 2000-04-02T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(941360400000L)); // 1999-10-31T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(923220000000L)); // 1999-04-04T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(909306000000L)); // 1998-10-25T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(891770400000L)); // 1998-04-05T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(877856400000L)); // 1997-10-26T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(860320800000L)); // 1997-04-06T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(846406800000L)); // 1996-10-27T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(828871200000L)); // 1996-04-07T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(814957200000L)); // 1995-10-29T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(796816800000L)); // 1995-04-02T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(783507600000L)); // 1994-10-30T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(765367200000L)); // 1994-04-03T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(752058000000L)); // 1993-10-31T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(733917600000L)); // 1993-04-04T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(720003600000L)); // 1992-10-25T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(702468000000L)); // 1992-04-05T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(688554000000L)); // 1991-10-27T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(671018400000L)); // 1991-04-07T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(657104400000L)); // 1990-10-28T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(638964000000L)); // 1990-04-01T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(625654800000L)); // 1989-10-29T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(607514400000L)); // 1989-04-02T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(594205200000L)); // 1988-10-30T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(576064800000L)); // 1988-04-03T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(562150800000L)); // 1987-10-25T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(544615200000L)); // 1987-04-05T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(530701200000L)); // 1986-10-26T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(514980000000L)); // 1986-04-27T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(499251600000L)); // 1985-10-27T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(483530400000L)); // 1985-04-28T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(467802000000L)); // 1984-10-28T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(452080800000L)); // 1984-04-29T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(436352400000L)); // 1983-10-30T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(420026400000L)); // 1983-04-24T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(404902800000L)); // 1982-10-31T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(388576800000L)); // 1982-04-25T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(372848400000L)); // 1981-10-25T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(357127200000L)); // 1981-04-26T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(341398800000L)); // 1980-10-26T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(325677600000L)); // 1980-04-27T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(309949200000L)); // 1979-10-28T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(294228000000L)); // 1979-04-29T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(278499600000L)); // 1978-10-29T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(262778400000L)); // 1978-04-30T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(247050000000L)); // 1977-10-30T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(230724000000L)); // 1977-04-24T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(215600400000L)); // 1976-10-31T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(199274400000L)); // 1976-04-25T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(183546000000L)); // 1975-10-26T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(162381600000L)); // 1975-02-23T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(152096400000L)); // 1974-10-27T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(126698400000L)); // 1974-01-06T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(120646800000L)); // 1973-10-28T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(104925600000L)); // 1973-04-29T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(89197200000L)); // 1972-10-29T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(73476000000L)); // 1972-04-30T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(57747600000L)); // 1971-10-31T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(41421600000L)); // 1971-04-25T03:00:00.000-07:00 + assertEquals(-28800000, la.getOffset(25693200000L)); // 1970-10-25T01:00:00.000-08:00 + assertEquals(-25200000, la.getOffset(9972000000L)); // 1970-04-26T03:00:00.000-07:00 + } + + /** + * New South Wales observed DST during World War I and World War II, and has been observing DST + * since 1971. + */ + public void testAustraliaEasternTimeZoneTransitions() { + TimeZone sydney = TimeZone.getTimeZone("Australia/Sydney"); + assertEquals(36000000, sydney.getOffset(1459612800000L)); // 2016-04-03T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(1443888000000L)); // 2015-10-04T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(1428163200000L)); // 2015-04-05T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(1412438400000L)); // 2014-10-05T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(1396713600000L)); // 2014-04-06T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(1380988800000L)); // 2013-10-06T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(1365264000000L)); // 2013-04-07T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(1349539200000L)); // 2012-10-07T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(1333209600000L)); // 2012-04-01T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(1317484800000L)); // 2011-10-02T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(1301760000000L)); // 2011-04-03T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(1286035200000L)); // 2010-10-03T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(1270310400000L)); // 2010-04-04T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(1254585600000L)); // 2009-10-04T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(1238860800000L)); // 2009-04-05T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(1223136000000L)); // 2008-10-05T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(1207411200000L)); // 2008-04-06T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(1193500800000L)); // 2007-10-28T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(1174752000000L)); // 2007-03-25T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(1162051200000L)); // 2006-10-29T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(1143907200000L)); // 2006-04-02T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(1130601600000L)); // 2005-10-30T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(1111852800000L)); // 2005-03-27T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(1099152000000L)); // 2004-10-31T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(1080403200000L)); // 2004-03-28T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(1067097600000L)); // 2003-10-26T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(1048953600000L)); // 2003-03-30T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(1035648000000L)); // 2002-10-27T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(1017504000000L)); // 2002-03-31T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(1004198400000L)); // 2001-10-28T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(985449600000L)); // 2001-03-25T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(967305600000L)); // 2000-08-27T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(954000000000L)); // 2000-03-26T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(941299200000L)); // 1999-10-31T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(922550400000L)); // 1999-03-28T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(909244800000L)); // 1998-10-25T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(891100800000L)); // 1998-03-29T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(877795200000L)); // 1997-10-26T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(859651200000L)); // 1997-03-30T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(846345600000L)); // 1996-10-27T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(828201600000L)); // 1996-03-31T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(814896000000L)); // 1995-10-29T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(794332800000L)); // 1995-03-05T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(783446400000L)); // 1994-10-30T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(762883200000L)); // 1994-03-06T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(751996800000L)); // 1993-10-31T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(731433600000L)); // 1993-03-07T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(719942400000L)); // 1992-10-25T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(699379200000L)); // 1992-03-01T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(688492800000L)); // 1991-10-27T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(667929600000L)); // 1991-03-03T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(657043200000L)); // 1990-10-28T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(636480000000L)); // 1990-03-04T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(625593600000L)); // 1989-10-29T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(606240000000L)); // 1989-03-19T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(594144000000L)); // 1988-10-30T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(574790400000L)); // 1988-03-20T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(562089600000L)); // 1987-10-25T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(542736000000L)); // 1987-03-15T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(530035200000L)); // 1986-10-19T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(511286400000L)); // 1986-03-16T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(499190400000L)); // 1985-10-27T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(478627200000L)); // 1985-03-03T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(467740800000L)); // 1984-10-28T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(447177600000L)); // 1984-03-04T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(436291200000L)); // 1983-10-30T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(415728000000L)); // 1983-03-06T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(404841600000L)); // 1982-10-31T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(386697600000L)); // 1982-04-04T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(372787200000L)); // 1981-10-25T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(352224000000L)); // 1981-03-01T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(341337600000L)); // 1980-10-26T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(320774400000L)); // 1980-03-02T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(309888000000L)); // 1979-10-28T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(289324800000L)); // 1979-03-04T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(278438400000L)); // 1978-10-29T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(257875200000L)); // 1978-03-05T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(246988800000L)); // 1977-10-30T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(226425600000L)); // 1977-03-06T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(215539200000L)); // 1976-10-31T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(194976000000L)); // 1976-03-07T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(183484800000L)); // 1975-10-26T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(162921600000L)); // 1975-03-02T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(152035200000L)); // 1974-10-27T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(131472000000L)); // 1974-03-03T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(120585600000L)); // 1973-10-28T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(100022400000L)); // 1973-03-04T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(89136000000L)); // 1972-10-29T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(67968000000L)); // 1972-02-27T02:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(57686400000L)); // 1971-10-31T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(-813229200000L)); // 1944-03-26T01:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(-828345600000L)); // 1943-10-03T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(-844678800000L)); // 1943-03-28T01:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(-860400000000L)); // 1942-09-27T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(-876128400000L)); // 1942-03-29T01:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(-883641600000L)); // 1942-01-01T03:00:00.000+11:00 + assertEquals(36000000, sydney.getOffset(-1665392400000L)); // 1917-03-25T01:00:00.000+10:00 + assertEquals(39600000, sydney.getOffset(-1672567140000L)); // 1917-01-01T01:01:00.000+11:00 + assertEquals(36000000, sydney.getOffset(-1672567140001L)); // 1917-01-01T01:00:59.999+10:00 + } + + /** + * Test the local date-based offset getter. + */ + public void testGetOffsetWithLocalDates() { + TimeZone la = TimeZone.getTimeZone("America/Los_Angeles"); + + // Recall Java calendar month is 0-based, and the dayOfWeek, parameter is actually ignored by + // some implementations. + + // 2016-03-12T03:00:00.000-08:00 + assertEquals( + -28800000, la.getOffset(GregorianCalendar.AD, 2016, 2, 12, Calendar.SATURDAY, 10800000)); + + // 2016-03-13T01:59:59.999-08:00 + assertEquals( + -28800000, la.getOffset(GregorianCalendar.AD, 2016, 2, 13, Calendar.SUNDAY, 7200000 - 1)); + + // 2016-03-13T02:00:00.000-08:00 (but 2 AM that day local time in America/Los_Angeles does not + // exist, even though TimeZone returns something that is after the DST transition) + assertEquals( + -25200000, la.getOffset(GregorianCalendar.AD, 2016, 2, 13, Calendar.SUNDAY, 7200000)); + + // 2016-03-13T02:30:00.000-08:00 (but 2:30 AM is a non-existent local time) + assertEquals( + -25200000, la.getOffset(GregorianCalendar.AD, 2016, 2, 13, Calendar.SUNDAY, 9000000)); + + // 2016-03-13T02:59:59.999-08:00 (but 2:59:59.999 AM is a non-existent local time) + assertEquals( + -25200000, la.getOffset(GregorianCalendar.AD, 2016, 2, 13, Calendar.SUNDAY, 10800000 - 1)); + + // 2016-03-13T03:00:00.000-07:00 + assertEquals( + -25200000, la.getOffset(GregorianCalendar.AD, 2016, 2, 13, Calendar.SUNDAY, 10800000)); + + // 2016-03-13T03:00:00.001-07:00 + assertEquals( + -25200000, la.getOffset(GregorianCalendar.AD, 2016, 2, 13, Calendar.SUNDAY, 10800000 + 1)); + + // 2015-10-31T01:00:00.000-07:00 + assertEquals( + -25200000, la.getOffset(GregorianCalendar.AD, 2015, 9, 31, Calendar.SATURDAY, 3600000)); + + // 2015-11-01T00:00:00.000-07:00 + assertEquals(-25200000, la.getOffset(GregorianCalendar.AD, 2015, 10, 1, Calendar.SUNDAY, 0)); + + // 2015-11-01T00:59:59.000-07:00 + assertEquals( + -25200000, la.getOffset(GregorianCalendar.AD, 2015, 10, 1, Calendar.SUNDAY, 3600000 - 1)); + + // 2015-11-01T01:00:00.000-08:00 (this is the evidence that TimeZone implementations always + // prefer the local datetime in terms of the raw offset). + assertEquals( + -28800000, la.getOffset(GregorianCalendar.AD, 2015, 10, 1, Calendar.SUNDAY, 3600000)); + + // 2015-11-01T01:59:59.999-08:00 + assertEquals( + -28800000, la.getOffset(GregorianCalendar.AD, 2015, 10, 1, Calendar.SUNDAY, 7200000 - 1)); + + // 2015-11-01T02:00:00.000-08:00 + assertEquals( + -28800000, la.getOffset(GregorianCalendar.AD, 2015, 10, 1, Calendar.SUNDAY, 7200000)); + + // Don't test any BC dates as it's meaningless. + } + + /** + * Test the locale-dependent display name of a time zone. + * + * JVM and iOS/OS X don't agree on the localized names, nor do they have the same localization + * coverage, and so we are just testing a few shared traits here. + */ + public void testGetDisplayName() { + TimeZone tz = TimeZone.getTimeZone("Europe/Paris"); + + // JVM says Central European (Summer) Time, OS X/iOS uses Central European Standard/Summer Time. + // Short names also differ and are not tested here. + assertTrue( + tz.getDisplayName(true, TimeZone.LONG, Locale.ENGLISH).startsWith("Central European")); + assertTrue(tz.getDisplayName(true, TimeZone.LONG, Locale.ENGLISH).contains("Summer")); + assertTrue( + tz.getDisplayName(false, TimeZone.LONG, Locale.ENGLISH).startsWith("Central European")); + assertFalse(tz.getDisplayName(false, TimeZone.LONG, Locale.ENGLISH).startsWith("Summer")); + + // JVM says Heure (d'été) d'Europe central, OS X/iOS uses heure normal/d’été d’Europe central + // (note the case difference in the first letter h and the Unicode apostrophe). + assertTrue(tz.getDisplayName(true, TimeZone.LONG, Locale.FRENCH).contains("Europe central")); + assertTrue(tz.getDisplayName(true, TimeZone.LONG, Locale.FRENCH).contains("été")); + assertTrue(tz.getDisplayName(false, TimeZone.LONG, Locale.FRENCH).contains("Europe central")); + assertFalse(tz.getDisplayName(false, TimeZone.LONG, Locale.FRENCH).startsWith("été")); + + // Similarly for German, though they finally agree on the DST name. + assertTrue( + tz.getDisplayName(true, TimeZone.LONG, Locale.GERMAN) + .equals("Mitteleuropäische Sommerzeit")); + assertTrue( + tz.getDisplayName(false, TimeZone.LONG, Locale.GERMAN).startsWith("Mitteleuropäische")); + assertFalse(tz.getDisplayName(false, TimeZone.LONG, Locale.GERMAN).contains("Sommer")); + } + + public void testIsTimeZoneUsingDaylightSavingTime() { + assertTrue(TimeZone.getTimeZone("America/Los_Angeles").useDaylightTime()); + assertFalse(TimeZone.getTimeZone("America/Phonenix").useDaylightTime()); // No DST in Arizona. + assertTrue(TimeZone.getTimeZone("America/Denver").useDaylightTime()); + assertTrue(TimeZone.getTimeZone("Europe/Paris").useDaylightTime()); + assertTrue(TimeZone.getTimeZone("Australia/Sydney").useDaylightTime()); + assertFalse(TimeZone.getTimeZone("Asia/Tokyo").useDaylightTime()); + assertFalse(TimeZone.getTimeZone("Asia/Kolkata").useDaylightTime()); + } + + public void testCommonRawOffsets() { + assertEquals(-8 * 3600000, TimeZone.getTimeZone("America/Los_Angeles").getRawOffset()); + assertEquals(-7 * 3600000, TimeZone.getTimeZone("America/Phoenix").getRawOffset()); + assertEquals(-7 * 3600000, TimeZone.getTimeZone("America/Denver").getRawOffset()); + assertEquals(-5 * 3600000, TimeZone.getTimeZone("America/New_York").getRawOffset()); + assertEquals(19800000, TimeZone.getTimeZone("Asia/Kolkata").getRawOffset()); // UTC+5.54 + assertEquals(9 * 3600000, TimeZone.getTimeZone("Asia/Tokyo").getRawOffset()); + assertEquals(10 * 3600000, TimeZone.getTimeZone("Australia/Sydney").getRawOffset()); + } + + public void testGetAvailableIds() { + List availableIds = Arrays.asList(TimeZone.getAvailableIDs(-7 * 3600000)); + assertTrue(availableIds.contains("America/Phoenix")); + assertTrue(availableIds.contains("America/Denver")); + assertFalse(availableIds.contains("America/Los_Angeles")); + } + + public void testIds() { + assertEquals("GMT", TimeZone.getTimeZone("GMT").getID()); + assertEquals("UTC", TimeZone.getTimeZone("UTC").getID()); + + String vmName = System.getProperty("java.vendor"); + if (vmName != null && vmName.startsWith("J2ObjC")) { + // NSTimeZone handles this custom time zone format and normalizes it. + assertEquals("GMT+0530", TimeZone.getTimeZone("GMT+05:30").getID()); + } else { + assertEquals("GMT+05:30", TimeZone.getTimeZone("GMT+05:30").getID()); + } + assertEquals("America/New_York", TimeZone.getTimeZone("America/New_York").getID()); + assertEquals(TimeZone.getTimeZone("GMT").getID(), TimeZone.getTimeZone("").getID()); // WIP + assertEquals(TimeZone.getTimeZone("GMT"), TimeZone.getTimeZone("america/new_york")); + } + + /** + * getTimeZone(String) always give you a new instance. + */ + public void testEqualityAndSameness() { + TimeZone a; + TimeZone b; + + a = TimeZone.getTimeZone("GMT"); + b = TimeZone.getTimeZone("GMT"); + assertEquals(a, b); + assertNotSame(a, b); + + a = TimeZone.getTimeZone("UTC"); + b = TimeZone.getTimeZone("UTC"); + assertEquals(a, b); + assertNotSame(a, b); + + a = TimeZone.getTimeZone("UTC"); + b = TimeZone.getTimeZone("GMT"); + assertFalse(a.equals(b)); + assertNotSame(a, b); + + a = TimeZone.getTimeZone("America/New_York"); + b = TimeZone.getTimeZone("America/New_York"); + assertEquals(a, b); + assertNotSame(a, b); + } + + public void testHasSameRules() { + TimeZone a; + TimeZone b; + + a = TimeZone.getTimeZone("America/New_York"); + b = TimeZone.getTimeZone("US/Eastern"); + assertTrue(a.hasSameRules(b)); + assertFalse(a.hasSameRules(null)); + + // Arizona does not observe DST, so even Phoenix and Denver have the same rawOffest, they have + // different rules. + a = TimeZone.getTimeZone("America/Phoenix"); + b = TimeZone.getTimeZone("America/Denver"); + assertEquals(a.getRawOffset(), b.getRawOffset()); + assertFalse(a.hasSameRules(b)); + } + + /** + * Although Android SDK documentation says three-letter time zone IDs other than UTC and GMT are + * not supported, actual implementations may still support them. The time zone "EST" is in + * practice UTC-5 with the following properties. + */ + public void testEST() { + TimeZone tz = TimeZone.getTimeZone("EST"); + + assertEquals("EST", tz.getID()); + assertFalse(tz.useDaylightTime()); + assertEquals(-5 * 3600000, tz.getRawOffset()); + assertEquals(0, tz.getDSTSavings()); + } +} diff --git a/jre_emul/android/libcore/luni/src/main/java/java/util/TimeZone.java b/jre_emul/android/libcore/luni/src/main/java/java/util/TimeZone.java index 2dc92f9e59..1ec6848832 100644 --- a/jre_emul/android/libcore/luni/src/main/java/java/util/TimeZone.java +++ b/jre_emul/android/libcore/luni/src/main/java/java/util/TimeZone.java @@ -17,16 +17,13 @@ package java.util; +import com.google.j2objc.util.NativeTimeZone; + import java.io.Serializable; import java.text.SimpleDateFormat; import java.util.regex.Matcher; import java.util.regex.Pattern; -/*-[ -#import "IOSClass.h" -#import "java/util/SimpleTimeZone.h" -]-*/ - /** * {@code TimeZone} represents a time zone, primarily used for configuring a {@link Calendar} or * {@link java.text.SimpleDateFormat} instance. @@ -94,14 +91,8 @@ public abstract class TimeZone implements Serializable, Cloneable { private String ID; - private Object nativeTimeZone; - public TimeZone() {} - private TimeZone(Object nativeTimeZone) { - this.nativeTimeZone = nativeTimeZone; - } - /** * Returns a new time zone with the same ID, raw offset, and daylight * savings time rules as this time zone. @@ -119,10 +110,9 @@ private TimeZone(Object nativeTimeZone) { * passed to {@link #getTimeZone} to lookup the corresponding time zone * instance. */ - public static synchronized native String[] getAvailableIDs() /*-[ - NSArray *timeZones = [NSTimeZone knownTimeZoneNames]; - return [IOSObjectArray arrayWithNSArray:timeZones type:NSString_class_()]; - ]-*/; + public static synchronized String[] getAvailableIDs() { + return NativeTimeZone.getAvailableNativeTimeZoneNames(); + } /** * Returns the IDs of the time zones whose offset from UTC is {@code @@ -131,18 +121,16 @@ public static synchronized native String[] getAvailableIDs() /*-[ * * @return a possibly-empty array. */ - public static synchronized native String[] getAvailableIDs(int offsetMillis) /*-[ - NSInteger secondsOffset = offsetMillis / 1000; - NSArray *timeZones = [NSTimeZone knownTimeZoneNames]; - NSMutableArray *results = [NSMutableArray array]; - for (NSString *id in timeZones) { - NSTimeZone *tz = [NSTimeZone timeZoneWithName:id]; - if ([tz secondsFromGMT] == secondsOffset) { - [results addObject:id]; + public static synchronized String[] getAvailableIDs(int offsetMillis) { + List ids = new ArrayList<>(); + for (String id : getAvailableIDs()) { + TimeZone tz = NativeTimeZone.get(id); + if (tz.getRawOffset() == offsetMillis) { + ids.add(id); + } } - } - return [IOSObjectArray arrayWithNSArray:results type:NSString_class_()]; - ]-*/; + return ids.toArray(new String[0]); + } /** * Returns the user's preferred time zone. This may have been overridden for @@ -153,19 +141,16 @@ public static synchronized native String[] getAvailableIDs(int offsetMillis) /*- */ public static synchronized TimeZone getDefault() { if (defaultTimeZone == null) { - defaultTimeZone = getDefaultNativeTimeZone(); + defaultTimeZone = NativeTimeZone.getDefaultNativeTimeZone(); } + + if (defaultTimeZone == null) { + defaultTimeZone = GMT; + } + return (TimeZone) defaultTimeZone.clone(); } - private static native TimeZone getDefaultNativeTimeZone() /*-[ - NSTimeZone *tz = [NSTimeZone defaultTimeZone]; - int offsetMillis = (int) ([tz secondsFromGMT] * 1000); - JavaUtilTimeZone *result = [[JavaUtilSimpleTimeZone alloc] initWithInt:offsetMillis - withNSString:[tz name]]; - return AUTORELEASE(result); - ]-*/; - /** * Equivalent to {@code getDisplayName(false, TimeZone.LONG, Locale.getDefault())}. * Be wary of the default locale. @@ -201,63 +186,17 @@ public final String getDisplayName(boolean daylightTime, int style) { */ public String getDisplayName(boolean daylightTime, int style, Locale locale) { if (style != SHORT && style != LONG) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("Bad style: " + style); } - boolean useDaylight = daylightTime && useDaylightTime(); - - String result = displayName(useDaylight, style == SHORT, locale); - if (result != null) { - return result; - } - - // TODO: do we ever get here? - - int offset = getRawOffset(); - if (useDaylight) { - offset += getDSTSavings(); + int offsetMillis = getRawOffset(); + if (daylightTime) { + offsetMillis += getDSTSavings(); } - offset /= 60000; - char sign = '+'; - if (offset < 0) { - sign = '-'; - offset = -offset; - } - StringBuilder builder = new StringBuilder(9); - builder.append("GMT"); - builder.append(sign); - appendNumber(builder, 2, offset / 60); - builder.append(':'); - appendNumber(builder, 2, offset % 60); - return builder.toString(); + return createGmtOffsetString(true /* includeGmt */, true /* includeMinuteSeparator */, + offsetMillis); } - private native String displayName(boolean daylightTime, boolean shortName, Locale locale) /*-[ - NSTimeZoneNameStyle zoneStyle; - if (daylightTime) { - zoneStyle = shortName ? - NSTimeZoneNameStyleShortDaylightSaving : NSTimeZoneNameStyleDaylightSaving; - } else { - zoneStyle = shortName ? - NSTimeZoneNameStyleShortStandard : NSTimeZoneNameStyleStandard; - } - - // Find native locale. - NSLocale *nativeLocale; - if (locale) { - NSMutableDictionary *components = [NSMutableDictionary dictionary]; - [components setObject:[locale getLanguage] forKey:NSLocaleLanguageCode]; - [components setObject:[locale getCountry] forKey:NSLocaleCountryCode]; - [components setObject:[locale getVariant] forKey:NSLocaleVariantCode]; - NSString *localeId = [NSLocale localeIdentifierFromComponents:components]; - nativeLocale = AUTORELEASE([[NSLocale alloc] initWithLocaleIdentifier:localeId]); - } else { - nativeLocale = [NSLocale currentLocale]; - } - - return [(NSTimeZone *) self->nativeTimeZone_ localizedName:zoneStyle locale:nativeLocale]; - ]-*/; - /** * Returns a string representation of an offset from UTC. * @@ -367,9 +306,7 @@ public abstract int getOffset(int era, int year, int month, int day, * Returns the offset in milliseconds from UTC of this time zone's standard * time. */ - public native int getRawOffset() /*-[ - return (int) [(NSTimeZone *) self->nativeTimeZone_ secondsFromGMT] * 1000; - ]-*/; + public abstract int getRawOffset(); /** * Returns a {@code TimeZone} corresponding to the given {@code id}, or {@code GMT} @@ -396,7 +333,6 @@ public static synchronized TimeZone getTimeZone(String id) { } // Special cases? These can clone an existing instance. - // TODO: should we just add a cache to ZoneInfoDB instead? if (id.length() == 3) { if (id.equals("GMT")) { return (TimeZone) GMT.clone(); @@ -413,7 +349,7 @@ public static synchronized TimeZone getTimeZone(String id) { } // Native time zone? - zone = getNativeTimeZone(id); + zone = NativeTimeZone.get(id); // Custom time zone? if (zone == null && id.length() > 3 && id.startsWith("GMT")) { @@ -428,79 +364,13 @@ public static synchronized TimeZone getTimeZone(String id) { return (zone != null) ? zone : (TimeZone) GMT.clone(); } - private static native TimeZone getNativeTimeZone(String id) /*-[ - NSTimeZone *tz = [NSTimeZone timeZoneWithAbbreviation:id_]; - if (!tz) { - tz = [NSTimeZone timeZoneWithName:id_]; - } - if (!tz) { - return nil; - } - int offset = (int) [tz secondsFromGMT] * 1000; // convert to milliseconds - - // Figure out the dates that daylight savings time starts and ends. - NSDate *toDaylightSaving, *toStandard; - if ([tz isDaylightSavingTime]) { - toStandard = [tz nextDaylightSavingTimeTransition]; - toDaylightSaving = - [tz nextDaylightSavingTimeTransitionAfterDate:toStandard]; - } else { - toDaylightSaving = [tz nextDaylightSavingTimeTransition]; - toStandard = [tz nextDaylightSavingTimeTransitionAfterDate:toDaylightSaving]; - } - if (toStandard && toDaylightSaving) { - NSUInteger savingsOffset = - [tz daylightSavingTimeOffsetForDate:toDaylightSaving] * 1000; - if ([tz isDaylightSavingTime]) { - // iOS returns current seconds, not the zone difference. - offset -= savingsOffset; - } - - // Fetch each date's components. - NSCalendar *calendar = [NSCalendar currentCalendar]; - NSUInteger units = NSCalendarUnitMonth | NSCalendarUnitDay | - NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond; - NSDateComponents *daylight = [calendar components:units - fromDate:toDaylightSaving]; - NSDateComponents *standard = [calendar components:units - fromDate:toStandard]; - - // Convert each day's date components to milliseconds since midnight. - int daylightTime = (int) (([daylight hour] * 60 * 60) + - ([daylight minute] * 60) + - [daylight second]) * 1000; - int standardTime = (int) (([standard hour] * 60 * 60) + - ([standard minute] * 60) + - [standard second]) * 1000; - - return AUTORELEASE([[JavaUtilSimpleTimeZone alloc] - initWithInt:offset - withNSString:[tz name] - withInt:(int) [daylight month] - 1 - withInt:(int) [daylight day] - withInt:0 - withInt:daylightTime - withInt:(int) [standard month] - 1 - withInt:(int) [standard day] - withInt:0 - withInt:standardTime - withInt:(int) savingsOffset]); - } else { - return AUTORELEASE([[JavaUtilSimpleTimeZone alloc] - initWithInt:offset withNSString:[tz name]]); - } - ]-*/; - /** * Returns a new SimpleTimeZone for an ID of the form "GMT[+|-]hh[[:]mm]", or null. */ private static TimeZone getCustomTimeZone(String id) { Matcher m = CUSTOM_ZONE_ID_PATTERN.matcher(id); if (!m.matches()) { - return GMT; // Expected result for invalid format. - } - if (id.equals("GMT-00")) { - return GMT; + return null; } int hour; @@ -548,9 +418,7 @@ public boolean hasSameRules(TimeZone timeZone) { * Returns true if {@code time} is in a daylight savings time period for * this time zone. */ - public native boolean inDaylightTime(Date time) /*-[ - return [(NSTimeZone *) self->nativeTimeZone_ isDaylightSavingTime]; - ]-*/; + public abstract boolean inDaylightTime(Date time); /** * Overrides the default time zone for the current process only. @@ -570,28 +438,18 @@ public static synchronized void setDefault(TimeZone timeZone) { /** * Sets the ID of this {@code TimeZone}. */ - public native void setID(String id) /*-[ - if (!id_) { - JavaLangNullPointerException *npe = [[JavaLangNullPointerException alloc] init]; - @throw AUTORELEASE(npe); - } - JavaUtilTimeZone_set_ID_(self, id_); - NSTimeZone *tz = [NSTimeZone timeZoneWithAbbreviation:id_]; - if (!tz) { - tz = [NSTimeZone timeZoneWithName:id_]; - } - if (tz) { - JavaUtilTimeZone_set_nativeTimeZone_(self, tz); - } - ]-*/; + public void setID(String id) { + if (id == null) { + throw new NullPointerException("id == null"); + } + ID = id; + } /** * Sets the offset in milliseconds from UTC of this time zone's standard * time. */ - public void setRawOffset(int offsetMillis) { - // Ignore for iOS. - } + public abstract void setRawOffset(int offsetMillis); /** * Returns true if this time zone has a future transition to or from @@ -610,9 +468,7 @@ public void setRawOffset(int offsetMillis) { * *

Most applications should not use this method. */ - public native boolean useDaylightTime() /*-[ - return [(NSTimeZone *) self->nativeTimeZone_ nextDaylightSavingTimeTransition] != nil; - ]-*/; + public abstract boolean useDaylightTime(); /** * Local LRU cache class, used to remove dependency on android.util.LruCache. diff --git a/jre_emul/android/libcore/luni/src/test/java/libcore/java/util/OldTimeZoneTest.java b/jre_emul/android/libcore/luni/src/test/java/libcore/java/util/OldTimeZoneTest.java index 9b0295b0d7..a6f87813c3 100644 --- a/jre_emul/android/libcore/luni/src/test/java/libcore/java/util/OldTimeZoneTest.java +++ b/jre_emul/android/libcore/luni/src/test/java/libcore/java/util/OldTimeZoneTest.java @@ -21,16 +21,10 @@ import java.util.Locale; import java.util.TimeZone; import junit.framework.TestCase; -import tests.support.Support_Locale; - -/*-[ -#include "java/lang/System.h" -#include -]-*/ public class OldTimeZoneTest extends TestCase { - class Mock_TimeZone extends TimeZone { + static class Mock_TimeZone extends TimeZone { @Override public int getOffset(int era, int year, int month, int day, int dayOfWeek, int milliseconds) { return 0; @@ -96,34 +90,45 @@ public void test_getDisplayName() { public void test_getDisplayNameLjava_util_Locale() { TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles"); - assertEquals("Pacific Standard Time", tz.getDisplayName(new Locale("US"))); - if (Support_Locale.isLocaleAvailable(Locale.FRANCE)) { - assertTrue(tz.getDisplayName(Locale.FRANCE).startsWith("heure normale du Pacifique")); - } + assertEquals("Pacific Standard Time", tz.getDisplayName(Locale.US)); + assertEquals("heure normale du Pacifique nord-américain", tz.getDisplayName(Locale.FRANCE)); } public void test_getDisplayNameZI() { Locale.setDefault(Locale.US); TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles"); - assertEquals("PST", tz.getDisplayName(false, 0)); - assertEquals("Pacific Daylight Time", tz.getDisplayName(true, 1)); - assertEquals("Pacific Standard Time", tz.getDisplayName(false, 1)); + assertEquals("PST", tz.getDisplayName(false, TimeZone.SHORT)); + assertEquals("Pacific Daylight Time", tz.getDisplayName(true, TimeZone.LONG)); + assertEquals("Pacific Standard Time", tz.getDisplayName(false, TimeZone.LONG)); } public void test_getDisplayNameZILjava_util_Locale() { TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles"); - assertEquals("PST", tz.getDisplayName(false, 0, Locale.US)); - assertEquals("Pacific Daylight Time", tz.getDisplayName(true, 1, Locale.US)); - if (Support_Locale.isLocaleAvailable(Locale.UK)) { - assertEquals("Pacific Standard Time", tz.getDisplayName(false, 1, Locale.UK)); - } - if (Support_Locale.isLocaleAvailable(Locale.FRANCE)) { - assertEquals("UTC−8", tz.getDisplayName(false, 0, Locale.FRANCE)); - String expected = preElCapitan() - ? "heure avancée du Pacifique" : "heure d’été du Pacifique"; - assertEquals(expected, tz.getDisplayName(true, 1, Locale.FRANCE)); - assertTrue(tz.getDisplayName(Locale.FRANCE).startsWith("heure normale du Pacifique")); - } + assertEquals("Pacific Daylight Time", tz.getDisplayName(true, TimeZone.LONG, Locale.US)); + assertEquals("Pacific Standard Time", tz.getDisplayName(false, TimeZone.LONG, Locale.UK)); + assertEquals("heure d’été du Pacifique", + tz.getDisplayName(true, TimeZone.LONG, Locale.FRANCE)); + assertEquals("heure normale du Pacifique nord-américain", + tz.getDisplayName(false, TimeZone.LONG, Locale.FRANCE)); + + assertEquals("PDT", tz.getDisplayName(true, TimeZone.SHORT, Locale.US)); + assertEquals("PST", tz.getDisplayName(false, TimeZone.SHORT, Locale.US)); + + // j2objc: disabled; the short time zone names for the following locales are not consistent + // across different platforms. NSTimeZone uses UTC-8/UTC-7 for the short names if the + // locale is "fr" but GMT-8/GMT-7 if it's "en-UK". But if you use "fr-CA" (Canadian French) + // the short names become HNP and HAP (heure normale du Pacifique and heure avencée du + // Pacifique). + /* + // RI fails on following lines. RI always returns short time zone name for + // "America/Los_Angeles" as "PST", Android only returns a string if ICU has a translation. + // There is no short time zone name for America/Los_Angeles in French or British English in + // ICU data so an offset is returned instead. + assertEquals("GMT-08:00", tz.getDisplayName(false, TimeZone.SHORT, Locale.FRANCE)); + assertEquals("GMT-07:00", tz.getDisplayName(true, TimeZone.SHORT, Locale.FRANCE)); + assertEquals("GMT-08:00", tz.getDisplayName(false, TimeZone.SHORT, Locale.UK)); + assertEquals("GMT-07:00", tz.getDisplayName(true, TimeZone.SHORT, Locale.UK)); + */ } public void test_getID() { @@ -154,16 +159,4 @@ public void test_setIDLjava_lang_String() { tz.setID("New ID for GMT-6"); assertEquals("New ID for GMT-6", tz.getID()); } - - // Running on an OS X version less than 10.11? - private static native boolean preElCapitan() /*-[ - if (![JavaLangSystem_getPropertyWithNSString_(@"os.name") isEqual:@"Mac OS X"]) { - return NO; - } - struct utsname uts; - if (uname(&uts) == 0) { - return atoi(uts.release) < 15; - } - return NO; - ]-*/; } diff --git a/jre_emul/apache_harmony/classlib/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/util/SimpleTimeZoneTest.java b/jre_emul/apache_harmony/classlib/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/util/SimpleTimeZoneTest.java index 1c905e4b7b..9bf02890c6 100644 --- a/jre_emul/apache_harmony/classlib/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/util/SimpleTimeZoneTest.java +++ b/jre_emul/apache_harmony/classlib/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/util/SimpleTimeZoneTest.java @@ -25,78 +25,150 @@ public class SimpleTimeZoneTest extends junit.framework.TestCase { - SimpleTimeZone st1; - - SimpleTimeZone st2; - - /** - * @tests java.util.SimpleTimeZone#SimpleTimeZone(int, java.lang.String) - */ - public void test_ConstructorILjava_lang_String() { - // Test for method java.util.SimpleTimeZone(int, java.lang.String) - - SimpleTimeZone st = new SimpleTimeZone(1000, "TEST"); - assertEquals("Incorrect TZ constructed", "TEST", st.getID()); - assertTrue("Incorrect TZ constructed: " + "returned wrong offset", st - .getRawOffset() == 1000); - assertTrue("Incorrect TZ constructed" + "using daylight savings", !st - .useDaylightTime()); - } - - /** - * @tests java.util.SimpleTimeZone#SimpleTimeZone(int, java.lang.String, - * int, int, int, int, int, int, int, int) - */ - public void test_ConstructorILjava_lang_StringIIIIIIII() { - // Test for method java.util.SimpleTimeZone(int, java.lang.String, int, - // int, int, int, int, int, int, int) - SimpleTimeZone st = new SimpleTimeZone(1000, "TEST", Calendar.NOVEMBER, - 1, Calendar.SUNDAY, 0, Calendar.NOVEMBER, -1, Calendar.SUNDAY, - 0); - assertTrue("Incorrect TZ constructed", st - .inDaylightTime(new GregorianCalendar(1998, Calendar.NOVEMBER, - 13).getTime())); - assertTrue("Incorrect TZ constructed", !(st - .inDaylightTime(new GregorianCalendar(1998, Calendar.OCTOBER, - 13).getTime()))); - assertEquals("Incorrect TZ constructed", "TEST", st.getID()); - assertEquals("Incorrect TZ constructed", 1000, st.getRawOffset()); - assertTrue("Incorrect TZ constructed", st.useDaylightTime()); - } - - /** - * @tests java.util.SimpleTimeZone#SimpleTimeZone(int, java.lang.String, - * int, int, int, int, int, int, int, int, int) - */ - public void test_ConstructorILjava_lang_StringIIIIIIIII() { - // Test for method java.util.SimpleTimeZone(int, java.lang.String, int, - // int, int, int, int, int, int, int, int) - SimpleTimeZone st = new SimpleTimeZone(1000, "TEST", Calendar.NOVEMBER, - 1, Calendar.SUNDAY, 0, Calendar.NOVEMBER, -1, Calendar.SUNDAY, - 0, 1000 * 60 * 60); - assertTrue("Incorrect TZ constructed", st - .inDaylightTime(new GregorianCalendar(1998, Calendar.NOVEMBER, - 13).getTime())); - assertTrue("Incorrect TZ constructed", !(st - .inDaylightTime(new GregorianCalendar(1998, Calendar.OCTOBER, - 13).getTime()))); - assertEquals("Incorrect TZ constructed", "TEST", st.getID()); - assertEquals("Incorrect TZ constructed", 1000, st.getRawOffset()); - assertTrue("Incorrect TZ constructed", st.useDaylightTime()); - assertTrue("Incorrect TZ constructed", - st.getDSTSavings() == 1000 * 60 * 60); - } - - /** - * @tests java.util.SimpleTimeZone#SimpleTimeZone(int, java.lang.String, - * int, int, int, int, int, int, int, int, int, int, int) - */ - public void test_ConstructorILjava_lang_StringIIIIIIIIIII() { - // Test for method java.util.SimpleTimeZone(int, java.lang.String, int, - // int, int, int, int, int, int, int, int, int, int) - // TODO : Implement test - //Regression for HARMONY-1241 - assertNotNull(new SimpleTimeZone( + SimpleTimeZone st1; + + SimpleTimeZone st2; + + /** + * java.util.SimpleTimeZone#SimpleTimeZone(int, java.lang.String) + */ + public void test_ConstructorILjava_lang_String() { + // Test for method java.util.SimpleTimeZone(int, java.lang.String) + + SimpleTimeZone st = new SimpleTimeZone(1000, "TEST"); + assertEquals("Incorrect TZ constructed", "TEST", st.getID()); + assertTrue("Incorrect TZ constructed: " + "returned wrong offset", st + .getRawOffset() == 1000); + assertTrue("Incorrect TZ constructed" + "using daylight savings", !st + .useDaylightTime()); + } + + /** + * java.util.SimpleTimeZone#SimpleTimeZone(int, java.lang.String, + * int, int, int, int, int, int, int, int) + */ + public void test_ConstructorILjava_lang_StringIIIIIIII() { + // Test for method java.util.SimpleTimeZone(int, java.lang.String, int, + // int, int, int, int, int, int, int) + SimpleTimeZone st = new SimpleTimeZone(1000, "TEST", Calendar.NOVEMBER, + 1, Calendar.SUNDAY, 0, Calendar.NOVEMBER, -1, Calendar.SUNDAY, + 0); + assertTrue("Incorrect TZ constructed", st + .inDaylightTime(new GregorianCalendar(1998, Calendar.NOVEMBER, + 13).getTime())); + assertTrue("Incorrect TZ constructed", !(st + .inDaylightTime(new GregorianCalendar(1998, Calendar.OCTOBER, + 13).getTime()))); + assertEquals("Incorrect TZ constructed", "TEST", st.getID()); + assertEquals("Incorrect TZ constructed", 1000, st.getRawOffset()); + assertTrue("Incorrect TZ constructed", st.useDaylightTime()); + + try { + new SimpleTimeZone(1000, "TEST", 12, + 1, Calendar.SUNDAY, 0, Calendar.NOVEMBER, -1, Calendar.SUNDAY, + 0); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + //expected + } + + try { + new SimpleTimeZone(1000, "TEST", Calendar.NOVEMBER, + 10, Calendar.SUNDAY, 0, Calendar.NOVEMBER, -1, Calendar.SUNDAY, + 0); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + //expected + } + + try { + new SimpleTimeZone(1000, "TEST", Calendar.NOVEMBER, + 1, 10, 0, Calendar.NOVEMBER, -1, Calendar.SUNDAY, + 0); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + //expected + } + + try { + new SimpleTimeZone(1000, "TEST", Calendar.DECEMBER, + 1, Calendar.SUNDAY, 0, Calendar.NOVEMBER, -10, Calendar.SUNDAY, + 0); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + //expected + } + } + + /** + * java.util.SimpleTimeZone#SimpleTimeZone(int, java.lang.String, + * int, int, int, int, int, int, int, int, int) + */ + public void test_ConstructorILjava_lang_StringIIIIIIIII() { + // Test for method java.util.SimpleTimeZone(int, java.lang.String, int, + // int, int, int, int, int, int, int, int) + SimpleTimeZone st = new SimpleTimeZone(1000, "TEST", Calendar.NOVEMBER, + 1, Calendar.SUNDAY, 0, Calendar.NOVEMBER, -1, Calendar.SUNDAY, + 0, 1000 * 60 * 60); + assertTrue("Incorrect TZ constructed", st + .inDaylightTime(new GregorianCalendar(1998, Calendar.NOVEMBER, + 13).getTime())); + assertTrue("Incorrect TZ constructed", !(st + .inDaylightTime(new GregorianCalendar(1998, Calendar.OCTOBER, + 13).getTime()))); + assertEquals("Incorrect TZ constructed", "TEST", st.getID()); + assertEquals("Incorrect TZ constructed", 1000, st.getRawOffset()); + assertTrue("Incorrect TZ constructed", st.useDaylightTime()); + assertTrue("Incorrect TZ constructed", + st.getDSTSavings() == 1000 * 60 * 60); + + try { + new SimpleTimeZone(1000, "TEST", 12, + 1, Calendar.SUNDAY, 0, Calendar.NOVEMBER, -1, Calendar.SUNDAY, + 0, 1000 * 60 * 60); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + //expected + } + + try { + new SimpleTimeZone(1000, "TEST", Calendar.NOVEMBER, + 10, Calendar.SUNDAY, 0, Calendar.NOVEMBER, -1, Calendar.SUNDAY, + 0, 1000 * 60 * 60); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + //expected + } + + try { + new SimpleTimeZone(1000, "TEST", Calendar.NOVEMBER, + 1, 10, 0, Calendar.NOVEMBER, -1, Calendar.SUNDAY, + 0, 1000 * 60 * 60); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + //expected + } + + try { + new SimpleTimeZone(1000, "TEST", Calendar.DECEMBER, + 1, Calendar.SUNDAY, 0, Calendar.NOVEMBER, -10, Calendar.SUNDAY, + 0, 1000 * 60 * 60); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + //expected + } + } + + /** + * java.util.SimpleTimeZone#SimpleTimeZone(int, java.lang.String, + * int, int, int, int, int, int, int, int, int, int, int) + */ + public void test_ConstructorILjava_lang_StringIIIIIIIIIII() { + // Test for method java.util.SimpleTimeZone(int, java.lang.String, int, + // int, int, int, int, int, int, int, int, int, int) + // TODO : Implement test + //Regression for HARMONY-1241 + assertNotNull(new SimpleTimeZone( TimeZone.LONG, "Europe/Paris", SimpleTimeZone.STANDARD_TIME, @@ -126,347 +198,641 @@ public void test_ConstructorILjava_lang_StringIIIIIIIIIII() { SimpleTimeZone.UTC_TIME, Integer.MIN_VALUE, TimeZone.LONG)); - } - - /** - * @tests java.util.SimpleTimeZone#clone() - */ - public void test_clone() { - // Test for method java.lang.Object java.util.SimpleTimeZone.clone() - SimpleTimeZone st1 = new SimpleTimeZone(1000, "TEST", - Calendar.NOVEMBER, 1, Calendar.SUNDAY, 0, Calendar.NOVEMBER, - -1, Calendar.SUNDAY, 0); - SimpleTimeZone stA = new SimpleTimeZone(1, "Gah"); - assertTrue("Clone resulted in same reference", st1.clone() != st1); - assertTrue("Clone resulted in unequal object", ((SimpleTimeZone) st1 - .clone()).equals(st1)); - assertTrue("Clone resulted in same reference", stA.clone() != stA); - assertTrue("Clone resulted in unequal object", ((SimpleTimeZone) stA - .clone()).equals(stA)); - } - - /** - * @tests java.util.SimpleTimeZone#getDSTSavings() - */ - public void test_getDSTSavings() { - // Test for method int java.util.SimpleTimeZone.getDSTSavings() - st1 = new SimpleTimeZone(0, "TEST"); - - assertEquals("Non-zero default daylight savings", - 0, st1.getDSTSavings()); - st1.setStartRule(0, 1, 1, 1); - st1.setEndRule(11, 1, 1, 1); - - assertEquals("Incorrect default daylight savings", - 3600000, st1.getDSTSavings()); - st1 = new SimpleTimeZone(-5 * 3600000, "EST", Calendar.APRIL, 1, - -Calendar.SUNDAY, 2 * 3600000, Calendar.OCTOBER, -1, - Calendar.SUNDAY, 2 * 3600000, 7200000); - assertEquals("Incorrect daylight savings from constructor", 7200000, st1 - .getDSTSavings()); - - } - - /** - * @tests java.util.SimpleTimeZone#getOffset(int, int, int, int, int, int) - * - TODO(tball): getOffset broken in second test - public void test_getOffsetIIIIII() { - // Test for method int java.util.SimpleTimeZone.getOffset(int, int, int, - // int, int, int) - TimeZone st1 = TimeZone.getTimeZone("EST"); - assertTrue("Incorrect offset returned", st1.getOffset( - GregorianCalendar.AD, 1998, Calendar.NOVEMBER, 11, - Calendar.WEDNESDAY, 0) == -(5 * 60 * 60 * 1000)); - - st1 = TimeZone.getTimeZone("EST"); + + try { + new SimpleTimeZone(1000, "TEST", 12, + 1, Calendar.SUNDAY, 0, Integer.MAX_VALUE, Calendar.NOVEMBER, -1, Calendar.SUNDAY, + 0, Integer.MAX_VALUE, 1000 * 60 * 60); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + //expected + } + + try { + new SimpleTimeZone(1000, "TEST", Calendar.NOVEMBER, + 10, Calendar.SUNDAY, 0, Integer.MAX_VALUE, Calendar.NOVEMBER, -1, Calendar.SUNDAY, + 0, Integer.MAX_VALUE, 1000 * 60 * 60); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + //expected + } + + try { + new SimpleTimeZone(1000, "TEST", Calendar.NOVEMBER, + 1, 10, 0, Calendar.NOVEMBER, Integer.MAX_VALUE, -1, Calendar.SUNDAY, + 0, Integer.MAX_VALUE, 1000 * 60 * 60); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + //expected + } + + try { + new SimpleTimeZone(1000, "TEST", Calendar.DECEMBER, + 1, Calendar.SUNDAY, 0, Calendar.NOVEMBER, Integer.MAX_VALUE, -10, Calendar.SUNDAY, + 0, Integer.MAX_VALUE, 1000 * 60 * 60); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + //expected + } + } + + /** + * java.util.SimpleTimeZone#clone() + */ + public void test_clone() { + // Test for method java.lang.Object java.util.SimpleTimeZone.clone() + SimpleTimeZone st1 = new SimpleTimeZone(1000, "TEST", + Calendar.NOVEMBER, 1, Calendar.SUNDAY, 0, Calendar.NOVEMBER, + -1, Calendar.SUNDAY, 0); + SimpleTimeZone stA = new SimpleTimeZone(1, "Gah"); + assertTrue("Clone resulted in same reference", st1.clone() != st1); + assertTrue("Clone resulted in unequal object", ((SimpleTimeZone) st1 + .clone()).equals(st1)); + assertTrue("Clone resulted in same reference", stA.clone() != stA); + assertTrue("Clone resulted in unequal object", ((SimpleTimeZone) stA + .clone()).equals(stA)); + } + + /** + * java.util.SimpleTimeZone#equals(java.lang.Object) + */ + public void test_equalsLjava_lang_Object() { + // Test for method boolean + // java.util.SimpleTimeZone.equals(java.lang.Object) + TimeZone tz = TimeZone.getTimeZone("EST"); + st1 = new SimpleTimeZone(tz.getRawOffset(), "EST"); + st2 = new SimpleTimeZone(0, "EST"); + assertFalse(st1.equals(st2)); + st1.setRawOffset(st2.getRawOffset()); + assertTrue(st1.equals(st2)); + } + + /** + * java.util.SimpleTimeZone#getDSTSavings() + */ + public void test_getDSTSavings() { + // Test for method int java.util.SimpleTimeZone.getDSTSavings() + st1 = new SimpleTimeZone(0, "TEST"); + + assertEquals("Non-zero default daylight savings", + 0, st1.getDSTSavings()); + st1.setStartRule(0, 1, 1, 1); + st1.setEndRule(11, 1, 1, 1); + + assertEquals("Incorrect default daylight savings", + 3600000, st1.getDSTSavings()); + st1 = new SimpleTimeZone(-5 * 3600000, "EST", Calendar.APRIL, 1, + -Calendar.SUNDAY, 2 * 3600000, Calendar.OCTOBER, -1, + Calendar.SUNDAY, 2 * 3600000, 7200000); + assertEquals("Incorrect daylight savings from constructor", 7200000, st1 + .getDSTSavings()); + + } + + /** + * java.util.SimpleTimeZone#getOffset(int, int, int, int, int, int) + */ + public void test_getOffsetIIIIII() { + // Test for method int java.util.SimpleTimeZone.getOffset(int, int, int, + // int, int, int) +// TimeZone st1 = TimeZone.getTimeZone("EST"); + st1 = new SimpleTimeZone(TimeZone.getTimeZone("EST").getRawOffset(), "EST"); + assertTrue("Incorrect offset returned", st1.getOffset( + GregorianCalendar.AD, 1998, Calendar.NOVEMBER, 11, + Calendar.WEDNESDAY, 0) == -(5 * 60 * 60 * 1000)); + + st1 = new SimpleTimeZone(TimeZone.getTimeZone("EST").getRawOffset(), "EST"); assertEquals("Incorrect offset returned", -(5 * 60 * 60 * 1000), st1 .getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 11, Calendar.THURSDAY, 0)); - + // Regression for HARMONY-5459 - st1 = (TimeZone)TimeZone.getDefault(); - int fourHours = 4*60*60*1000; - st1.setRawOffset(fourHours); + st1 = new SimpleTimeZone(TimeZone.getDefault().getRawOffset(), TimeZone.getDefault().getID()); + int fourHours = 4*60*60*1000; + st1.setRawOffset(fourHours); assertEquals(fourHours, st1.getOffset(1, 2099, 01, 1, 5, 0)); - } - - /** - * @tests java.util.SimpleTimeZone#getRawOffset() - */ - public void test_getRawOffset() { - // Test for method int java.util.SimpleTimeZone.getRawOffset() - st1 = (SimpleTimeZone) TimeZone.getTimeZone("EST"); - assertTrue("Incorrect offset returned", - st1.getRawOffset() == -(5 * 60 * 60 * 1000)); - - } - - /** - * @tests java.util.SimpleTimeZone#hasSameRules(java.util.TimeZone) - */ - public void test_hasSameRulesLjava_util_TimeZone() { - // Test for method boolean - // java.util.SimpleTimeZone.hasSameRules(java.util.TimeZone) - SimpleTimeZone st = new SimpleTimeZone(1000, "TEST", Calendar.NOVEMBER, - 1, Calendar.SUNDAY, 0, Calendar.NOVEMBER, -1, Calendar.SUNDAY, - 0); - SimpleTimeZone sameAsSt = new SimpleTimeZone(1000, "REST", - Calendar.NOVEMBER, 1, Calendar.SUNDAY, 0, Calendar.NOVEMBER, - -1, Calendar.SUNDAY, 0); - SimpleTimeZone notSameAsSt = new SimpleTimeZone(1000, "PEST", - Calendar.NOVEMBER, 2, Calendar.SUNDAY, 0, Calendar.NOVEMBER, - -1, Calendar.SUNDAY, 0); - assertTrue("Time zones have same rules but return false", st - .hasSameRules(sameAsSt)); - assertTrue("Time zones have different rules but return true", !st - .hasSameRules(notSameAsSt)); - } - - /** - * @tests java.util.SimpleTimeZone#inDaylightTime(java.util.Date) - * - TODO(tball): enable when in daylight time tables are added. - public void test_inDaylightTimeLjava_util_Date() { - // Test for method boolean - // java.util.SimpleTimeZone.inDaylightTime(java.util.Date) - TimeZone zone = TimeZone.getTimeZone("EST"); - GregorianCalendar gc = new GregorianCalendar(1998, Calendar.JUNE, 11); - assertFalse("Returned incorrect daylight value1", zone.inDaylightTime(gc - .getTime())); - gc = new GregorianCalendar(1998, Calendar.NOVEMBER, 11); - assertFalse("Returned incorrect daylight value1", zone.inDaylightTime(gc + try { + st1.getOffset(-1, 2099, 01, 1, 5, 0); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + //expected + } + + try { + st1.getOffset(1, 2099, 15, 1, 5, 0); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + //expected + } + + try { + st1.getOffset(1, 2099, 01, 100, 5, 0); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + //expected + } + + try { + st1.getOffset(1, 2099, 01, 1, 50, 0); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + //expected + } + + try { + st1.getOffset(1, 2099, 01, 1, 5, -10); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + //expected + } + } + + /** + * java.util.SimpleTimeZone#getRawOffset() + */ + public void test_getRawOffset() { + // Test for method int java.util.SimpleTimeZone.getRawOffset() + st1 = new SimpleTimeZone(TimeZone.getTimeZone("EST").getRawOffset(), "EST"); + assertTrue("Incorrect offset returned", + st1.getRawOffset() == -(5 * 60 * 60 * 1000)); + + } + + /** + * java.util.SimpleTimeZone#hashCode() + */ + public void test_hashCode() { + // Test for method int java.util.SimpleTimeZone.hashCode() + // For lack of a better test. + st1 = new SimpleTimeZone(-5 * 3600000, "EST", Calendar.APRIL, 1, + -Calendar.SUNDAY, 2 * 3600000, Calendar.OCTOBER, -1, + Calendar.SUNDAY, 2 * 3600000); + assertTrue(TimeZone.getTimeZone("EST").hashCode() != 0); + assertTrue(st1.hashCode() != 0); + } + + /** + * java.util.SimpleTimeZone#hasSameRules(java.util.TimeZone) + */ + public void test_hasSameRulesLjava_util_TimeZone() { + // Test for method boolean + // java.util.SimpleTimeZone.hasSameRules(java.util.TimeZone) + SimpleTimeZone st = new SimpleTimeZone(1000, "TEST", Calendar.NOVEMBER, + 1, Calendar.SUNDAY, 0, Calendar.NOVEMBER, -1, Calendar.SUNDAY, + 0); + SimpleTimeZone sameAsSt = new SimpleTimeZone(1000, "REST", + Calendar.NOVEMBER, 1, Calendar.SUNDAY, 0, Calendar.NOVEMBER, + -1, Calendar.SUNDAY, 0); + SimpleTimeZone notSameAsSt = new SimpleTimeZone(1000, "PEST", + Calendar.NOVEMBER, 2, Calendar.SUNDAY, 0, Calendar.NOVEMBER, + -1, Calendar.SUNDAY, 0); + assertTrue("Time zones have same rules but return false", st + .hasSameRules(sameAsSt)); + assertTrue("Time zones have different rules but return true", !st + .hasSameRules(notSameAsSt)); + } + + /** + * java.util.SimpleTimeZone#inDaylightTime(java.util.Date) + */ + public void test_inDaylightTimeLjava_util_Date() { + // Test for method boolean + // java.util.SimpleTimeZone.inDaylightTime(java.util.Date) + TimeZone tz = TimeZone.getTimeZone("EST"); + SimpleTimeZone zone = new SimpleTimeZone(tz.getRawOffset(), "EST", + Calendar.APRIL, 1, -Calendar.SUNDAY, 7200000, Calendar.OCTOBER, -1, Calendar.SUNDAY, 7200000, 3600000); + GregorianCalendar gc = new GregorianCalendar(1998, Calendar.JUNE, 11); + + assertTrue("Returned incorrect daylight value1", zone.inDaylightTime(gc .getTime())); - gc = new GregorianCalendar(zone); - gc.set(1999, Calendar.APRIL, 4, 1, 59, 59); - assertTrue("Returned incorrect daylight value3", !(zone - .inDaylightTime(gc.getTime()))); - Date date = new Date(gc.getTime().getTime() + 1000); - assertFalse("Returned incorrect daylight value4", zone - .inDaylightTime(date)); - gc.set(1999, Calendar.OCTOBER, 31, 1, 0, 0); - assertTrue("Returned incorrect daylight value5", !(zone - .inDaylightTime(gc.getTime()))); - date = new Date(gc.getTime().getTime() - 1000); - assertFalse("Returned incorrect daylight value6", zone - .inDaylightTime(date)); - - assertTrue("Returned incorrect daylight value7", !zone - .inDaylightTime(new Date(891752400000L + 7200000 - 1))); - assertFalse("Returned incorrect daylight value8", zone - .inDaylightTime(new Date(891752400000L + 7200000))); - assertFalse("Returned incorrect daylight value9", zone - .inDaylightTime(new Date(909288000000L + 7200000 - 1))); - assertTrue("Returned incorrect daylight value10", !zone - .inDaylightTime(new Date(909288000000L + 7200000))); - } - - /** - * @tests java.util.SimpleTimeZone#setDSTSavings(int) - */ - public void test_setDSTSavingsI() { - // Test for method void java.util.SimpleTimeZone.setDSTSavings(int) - SimpleTimeZone st = new SimpleTimeZone(1000, "Test_TZ"); - st.setStartRule(0, 1, 1, 1); - st.setEndRule(11, 1, 1, 1); - st.setDSTSavings(1); - assertEquals("Daylight savings amount not set", 1, st.getDSTSavings()); - } - - /** - * @tests java.util.SimpleTimeZone#setEndRule(int, int, int) - */ - public void test_setEndRuleIII() { - // Test for method void java.util.SimpleTimeZone.setEndRule(int, int, - // int) - assertTrue("Used to test", true); - } - - /** - * @tests java.util.SimpleTimeZone#setEndRule(int, int, int, int) - */ - public void test_setEndRuleIIII() { - // Test for method void java.util.SimpleTimeZone.setEndRule(int, int, - // int, int) - SimpleTimeZone st = new SimpleTimeZone(1000, "Test_TZ"); - // Spec indicates that both end and start must be set or result is - // undefined - st.setStartRule(Calendar.NOVEMBER, 1, Calendar.SUNDAY, 0); - st.setEndRule(Calendar.NOVEMBER, -1, Calendar.SUNDAY, 0); - assertTrue("StartRule improperly set1", st.useDaylightTime()); - assertTrue("StartRule improperly set2", st - .inDaylightTime(new GregorianCalendar(1998, Calendar.NOVEMBER, - 13).getTime())); - assertTrue("StartRule improperly set3", !(st - .inDaylightTime(new GregorianCalendar(1998, Calendar.OCTOBER, - 13).getTime()))); - } - - /** - * @tests java.util.SimpleTimeZone#setEndRule(int, int, int, int, boolean) - */ - public void test_setEndRuleIIIIZ() { - // Test for method void java.util.SimpleTimeZone.setEndRule(int, int, - // int, int, boolean) + gc = new GregorianCalendar(1998, Calendar.NOVEMBER, 11); + assertTrue("Returned incorrect daylight value2", !(zone + .inDaylightTime(gc.getTime()))); + gc = new GregorianCalendar(zone); + gc.set(1999, Calendar.APRIL, 4, 1, 59, 59); + assertTrue("Returned incorrect daylight value3", !(zone + .inDaylightTime(gc.getTime()))); + Date date = new Date(gc.getTime().getTime() + 1000); + assertTrue("Returned incorrect daylight value4", zone + .inDaylightTime(date)); + gc.set(1999, Calendar.OCTOBER, 31, 1, 0, 0); + assertTrue("Returned incorrect daylight value5", !(zone + .inDaylightTime(gc.getTime()))); + date = new Date(gc.getTime().getTime() - 1000); + assertTrue("Returned incorrect daylight value6", zone + .inDaylightTime(date)); + + assertTrue("Returned incorrect daylight value7", !zone + .inDaylightTime(new Date(891752400000L + 7200000 - 1))); + assertTrue("Returned incorrect daylight value8", zone + .inDaylightTime(new Date(891752400000L + 7200000))); + assertTrue("Returned incorrect daylight value9", zone + .inDaylightTime(new Date(909288000000L + 7200000 - 1))); + assertTrue("Returned incorrect daylight value10", !zone + .inDaylightTime(new Date(909288000000L + 7200000))); + } + + /** + * java.util.SimpleTimeZone#setDSTSavings(int) + */ + public void test_setDSTSavingsI() { + // Test for method void java.util.SimpleTimeZone.setDSTSavings(int) + SimpleTimeZone st = new SimpleTimeZone(1000, "Test_TZ"); + st.setStartRule(0, 1, 1, 1); + st.setEndRule(11, 1, 1, 1); + st.setDSTSavings(1); + assertEquals(1, st.getDSTSavings()); + try { + st.setDSTSavings(0); + fail(); + } catch (IllegalArgumentException expected) { + } + try { + st.setDSTSavings(-1); + fail(); + } catch (IllegalArgumentException expected) { + } + } + + /** + * java.util.SimpleTimeZone#setEndRule(int, int, int) + */ + public void test_setEndRuleIII() { + SimpleTimeZone st = new SimpleTimeZone(1000, "Test_TZ"); + st.setStartRule(Calendar.NOVEMBER, 1, 0); + st.setEndRule(Calendar.NOVEMBER, 20, 0); + assertTrue("StartRule improperly set1", st.useDaylightTime()); + assertTrue("StartRule improperly set2", st.inDaylightTime( + new GregorianCalendar(1998, Calendar.NOVEMBER, + 13).getTime())); + assertTrue("StartRule improperly set3", !(st + .inDaylightTime(new GregorianCalendar(1998, Calendar.OCTOBER, + 13).getTime()))); + + try { + st.setEndRule(13, 20, 0); + fail("IllegalArgumentException is not thrown."); + } catch(IllegalArgumentException iae) { + //expected + } + + try { + st.setEndRule(1, 32, 0); + fail("IllegalArgumentException is not thrown."); + } catch(IllegalArgumentException iae) { + //expected + } + + try { + st.setEndRule(1, 30, 10); + fail("IllegalArgumentException is not thrown."); + } catch(IllegalArgumentException iae) { + //expected + } + } + + /** + * java.util.SimpleTimeZone#setEndRule(int, int, int, int) + */ + public void test_setEndRuleIIII() { + // Test for method void java.util.SimpleTimeZone.setEndRule(int, int, + // int, int) + SimpleTimeZone st = new SimpleTimeZone(1000, "Test_TZ"); + // Spec indicates that both end and start must be set or result is + // undefined + st.setStartRule(Calendar.NOVEMBER, 1, Calendar.SUNDAY, 0); + st.setEndRule(Calendar.NOVEMBER, -1, Calendar.SUNDAY, 0); + assertTrue("StartRule improperly set1", st.useDaylightTime()); + assertTrue("StartRule improperly set2", st + .inDaylightTime(new GregorianCalendar(1998, Calendar.NOVEMBER, + 13).getTime())); + assertTrue("StartRule improperly set3", !(st + .inDaylightTime(new GregorianCalendar(1998, Calendar.OCTOBER, + 13).getTime()))); + + try { + st.setEndRule(12, -1, Calendar.SUNDAY, 0); + fail("IllegalArgumentException is not thrown."); + } catch(IllegalArgumentException iae) { + //expected + } + + try { + st.setEndRule(Calendar.NOVEMBER, 10, Calendar.SUNDAY, 0); + fail("IllegalArgumentException is not thrown."); + } catch(IllegalArgumentException iae) { + //expected + } + + try { + st.setEndRule(Calendar.NOVEMBER, -1, 8, 0); + fail("IllegalArgumentException is not thrown."); + } catch(IllegalArgumentException iae) { + //expected + } + + try { + st.setEndRule(Calendar.NOVEMBER, -1, Calendar.SUNDAY, -10); + fail("IllegalArgumentException is not thrown."); + } catch(IllegalArgumentException iae) { + //expected + } + } + + /** + * java.util.SimpleTimeZone#setEndRule(int, int, int, int, boolean) + */ + public void test_setEndRuleIIIIZ() { + // Test for method void java.util.SimpleTimeZone.setEndRule(int, int, + // int, int, boolean) + SimpleTimeZone st = new SimpleTimeZone(1000, "Test_TZ"); + // Spec indicates that both end and start must be set or result is + // undefined + st.setStartRule(Calendar.NOVEMBER, 8, Calendar.SUNDAY, 1, false); + st.setEndRule(Calendar.NOVEMBER, 15, Calendar.SUNDAY, 1, true); + assertTrue("StartRule improperly set1", st.useDaylightTime()); + assertTrue("StartRule improperly set2", st + .inDaylightTime((new GregorianCalendar(1999, Calendar.NOVEMBER, + 7, 12, 0).getTime()))); + assertTrue("StartRule improperly set3", st + .inDaylightTime((new GregorianCalendar(1999, Calendar.NOVEMBER, + 20, 12, 0).getTime()))); + assertTrue("StartRule improperly set4", !(st + .inDaylightTime(new GregorianCalendar(1999, Calendar.NOVEMBER, + 6, 12, 0).getTime()))); + assertTrue("StartRule improperly set5", !(st + .inDaylightTime(new GregorianCalendar(1999, Calendar.NOVEMBER, + 21, 12, 0).getTime()))); + + try { + st.setEndRule(20, 15, Calendar.SUNDAY, 1, true); + fail("IllegalArgumentException is not thrown."); + } catch(IllegalArgumentException iae) { + //expected + } + + try { + st.setEndRule(Calendar.NOVEMBER, 35, Calendar.SUNDAY, 1, true); + fail("IllegalArgumentException is not thrown."); + } catch(IllegalArgumentException iae) { + //expected + } + + try { + st.setEndRule(Calendar.NOVEMBER, 15, 12, 1, true); + fail("IllegalArgumentException is not thrown."); + } catch(IllegalArgumentException iae) { + //expected + } + + try { + st.setEndRule(Calendar.NOVEMBER, 15, Calendar.SUNDAY, -1, true); + fail("IllegalArgumentException is not thrown."); + } catch(IllegalArgumentException iae) { + //expected + } + } + + /** + * java.util.SimpleTimeZone#setRawOffset(int) + */ + public void test_setRawOffsetI() { + // Test for method void java.util.SimpleTimeZone.setRawOffset(int) + + st1 = new SimpleTimeZone(TimeZone.getTimeZone("EST").getRawOffset(), "EST"); + int off = st1.getRawOffset(); + st1.setRawOffset(1000); + boolean val = st1.getRawOffset() == 1000; + st1.setRawOffset(off); + assertTrue("Incorrect offset set", val); + } + + /** + * java.util.SimpleTimeZone#setStartRule(int, int, int) + */ + public void test_setStartRuleIII() { + // Test for method void java.util.SimpleTimeZone.setStartRule(int, int, + // int) + SimpleTimeZone st = new SimpleTimeZone(1000, "Test_TZ"); + // Spec indicates that both end and start must be set or result is + // undefined + st.setStartRule(Calendar.NOVEMBER, 1, 1); + st.setEndRule(Calendar.DECEMBER, 1, 1); + assertTrue("StartRule improperly set", st.useDaylightTime()); + assertTrue("StartRule improperly set", st + .inDaylightTime((new GregorianCalendar(1998, Calendar.NOVEMBER, + 13).getTime()))); + assertTrue("StartRule improperly set", !(st + .inDaylightTime(new GregorianCalendar(1998, Calendar.OCTOBER, + 13).getTime()))); + + try { + st.setStartRule(13, 20, 0); + fail("IllegalArgumentException is not thrown."); + } catch(IllegalArgumentException iae) { + //expected + } + + try { + st.setStartRule(1, 32, 0); + fail("IllegalArgumentException is not thrown."); + } catch(IllegalArgumentException iae) { + //expected + } + + try { + st.setStartRule(1, 30, 10); + fail("IllegalArgumentException is not thrown."); + } catch(IllegalArgumentException iae) { + //expected + } + } + + /** + * java.util.SimpleTimeZone#setStartRule(int, int, int, int) + */ + public void test_setStartRuleIIII() { + // Test for method void java.util.SimpleTimeZone.setStartRule(int, int, + // int, int) + SimpleTimeZone st = new SimpleTimeZone(1000, "Test_TZ"); + // Spec indicates that both end and start must be set or result is + // undefined + st.setStartRule(Calendar.NOVEMBER, 1, Calendar.SUNDAY, 0); + st.setEndRule(Calendar.NOVEMBER, -1, Calendar.SUNDAY, 0); + assertTrue("StartRule improperly set1", st.useDaylightTime()); + assertTrue("StartRule improperly set2", st + .inDaylightTime((new GregorianCalendar(1998, Calendar.NOVEMBER, + 13).getTime()))); + assertTrue("StartRule improperly set3", !(st + .inDaylightTime(new GregorianCalendar(1998, Calendar.OCTOBER, + 13).getTime()))); + + try { + st.setStartRule(12, -1, Calendar.SUNDAY, 0); + fail("IllegalArgumentException is not thrown."); + } catch(IllegalArgumentException iae) { + //expected + } + + try { + st.setStartRule(Calendar.NOVEMBER, 10, Calendar.SUNDAY, 0); + fail("IllegalArgumentException is not thrown."); + } catch(IllegalArgumentException iae) { + //expected + } + + try { + st.setStartRule(Calendar.NOVEMBER, -1, 8, 0); + fail("IllegalArgumentException is not thrown."); + } catch(IllegalArgumentException iae) { + //expected + } + + try { + st.setStartRule(Calendar.NOVEMBER, -1, Calendar.SUNDAY, -10); + fail("IllegalArgumentException is not thrown."); + } catch(IllegalArgumentException iae) { + //expected + } + } + + /** + * java.util.SimpleTimeZone#setStartRule(int, int, int, int, boolean) + */ + public void test_setStartRuleIIIIZ() { + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + // Test for method void java.util.SimpleTimeZone.setStartRule(int, int, + // int, int, boolean) + SimpleTimeZone st = new SimpleTimeZone(TimeZone.getTimeZone("EST").getRawOffset(), "EST"); + // Spec indicates that both end and start must be set or result is + // undefined + st.setStartRule(Calendar.NOVEMBER, 1, Calendar.SUNDAY, 1, true); + st.setEndRule(Calendar.NOVEMBER, 15, Calendar.SUNDAY, 1, false); + assertTrue("StartRule improperly set1", st.useDaylightTime()); + assertTrue("StartRule improperly set2", st + .inDaylightTime((new GregorianCalendar(1999, Calendar.NOVEMBER, + 7, 12, 0).getTime()))); + assertTrue("StartRule improperly set3", st + .inDaylightTime((new GregorianCalendar(1999, Calendar.NOVEMBER, + 13, 12, 0).getTime()))); + assertTrue("StartRule improperly set4", !(st + .inDaylightTime(new GregorianCalendar(1999, Calendar.NOVEMBER, + 6, 12, 0).getTime()))); + assertTrue("StartRule improperly set5", !(st + .inDaylightTime(new GregorianCalendar(1999, Calendar.NOVEMBER, + 14, 12, 0).getTime()))); + + try { + st.setStartRule(20, 15, Calendar.SUNDAY, 1, true); + fail("IllegalArgumentException is not thrown."); + } catch(IllegalArgumentException iae) { + //expected + } + + try { + st.setStartRule(Calendar.NOVEMBER, 35, Calendar.SUNDAY, 1, true); + fail("IllegalArgumentException is not thrown."); + } catch(IllegalArgumentException iae) { + //expected + } + + try { + st.setStartRule(Calendar.NOVEMBER, 15, 12, 1, true); + fail("IllegalArgumentException is not thrown."); + } catch(IllegalArgumentException iae) { + //expected + } + + try { + st.setStartRule(Calendar.NOVEMBER, 15, Calendar.SUNDAY, -1, true); + fail("IllegalArgumentException is not thrown."); + } catch(IllegalArgumentException iae) { + //expected + } + } + + /** + * java.util.SimpleTimeZone#setStartYear(int) + */ + public void test_setStartYearI() { + // Test for method void java.util.SimpleTimeZone.setStartYear(int) SimpleTimeZone st = new SimpleTimeZone(1000, "Test_TZ"); - // Spec indicates that both end and start must be set or result is - // undefined - st.setStartRule(Calendar.NOVEMBER, 8, Calendar.SUNDAY, 1, false); - st.setEndRule(Calendar.NOVEMBER, 15, Calendar.SUNDAY, 1, true); - assertTrue("StartRule improperly set1", st.useDaylightTime()); - assertTrue("StartRule improperly set2", st - .inDaylightTime((new GregorianCalendar(1999, Calendar.NOVEMBER, - 7, 12, 0).getTime()))); - assertTrue("StartRule improperly set3", st - .inDaylightTime((new GregorianCalendar(1999, Calendar.NOVEMBER, - 20, 12, 0).getTime()))); - assertTrue("StartRule improperly set4", !(st - .inDaylightTime(new GregorianCalendar(1999, Calendar.NOVEMBER, - 6, 12, 0).getTime()))); - assertTrue("StartRule improperly set5", !(st - .inDaylightTime(new GregorianCalendar(1999, Calendar.NOVEMBER, - 21, 12, 0).getTime()))); - } - - /** - * @tests java.util.SimpleTimeZone#setRawOffset(int) - */ - public void test_setRawOffsetI() { - // Test for method void java.util.SimpleTimeZone.setRawOffset(int) - - st1 = (SimpleTimeZone) TimeZone.getTimeZone("EST"); - int off = st1.getRawOffset(); - st1.setRawOffset(1000); - boolean val = st1.getRawOffset() == 1000; - st1.setRawOffset(off); - assertTrue("Incorrect offset set", val); - } - - /** - * @tests java.util.SimpleTimeZone#setStartRule(int, int, int) - */ - public void test_setStartRuleIII() { - // Test for method void java.util.SimpleTimeZone.setStartRule(int, int, - // int) - SimpleTimeZone st = new SimpleTimeZone(1000, "Test_TZ"); - // Spec indicates that both end and start must be set or result is - // undefined - st.setStartRule(Calendar.NOVEMBER, 1, 1); - st.setEndRule(Calendar.DECEMBER, 1, 1); - assertTrue("StartRule improperly set", st.useDaylightTime()); - assertTrue("StartRule improperly set", st - .inDaylightTime((new GregorianCalendar(1998, Calendar.NOVEMBER, - 13).getTime()))); - assertTrue("StartRule improperly set", !(st - .inDaylightTime(new GregorianCalendar(1998, Calendar.OCTOBER, - 13).getTime()))); - - } - - /** - * @tests java.util.SimpleTimeZone#setStartRule(int, int, int, int) - */ - public void test_setStartRuleIIII() { - // Test for method void java.util.SimpleTimeZone.setStartRule(int, int, - // int, int) - SimpleTimeZone st = new SimpleTimeZone(1000, "Test_TZ"); - // Spec indicates that both end and start must be set or result is - // undefined - st.setStartRule(Calendar.NOVEMBER, 1, Calendar.SUNDAY, 0); - st.setEndRule(Calendar.NOVEMBER, -1, Calendar.SUNDAY, 0); - assertTrue("StartRule improperly set1", st.useDaylightTime()); - assertTrue("StartRule improperly set2", st - .inDaylightTime((new GregorianCalendar(1998, Calendar.NOVEMBER, - 13).getTime()))); - assertTrue("StartRule improperly set3", !(st - .inDaylightTime(new GregorianCalendar(1998, Calendar.OCTOBER, - 13).getTime()))); - } - - /** - * @tests java.util.SimpleTimeZone#setStartRule(int, int, int, int, boolean) - */ - public void test_setStartRuleIIIIZ() { - // Test for method void java.util.SimpleTimeZone.setStartRule(int, int, - // int, int, boolean) - SimpleTimeZone st = new SimpleTimeZone(0, "Test"); - // Spec indicates that both end and start must be set or result is - // undefined - st.setStartRule(Calendar.NOVEMBER, 1, Calendar.SUNDAY, 1, true); - st.setEndRule(Calendar.NOVEMBER, 15, Calendar.SUNDAY, 1, false); - assertTrue("StartRule improperly set1", st.useDaylightTime()); - assertTrue("StartRule improperly set2", st - .inDaylightTime((new GregorianCalendar(1999, Calendar.NOVEMBER, - 7, 12, 0).getTime()))); - assertTrue("StartRule improperly set3", st - .inDaylightTime((new GregorianCalendar(1999, Calendar.NOVEMBER, - 13, 12, 0).getTime()))); - assertTrue("StartRule improperly set4", !(st - .inDaylightTime(new GregorianCalendar(1999, Calendar.NOVEMBER, - 6, 12, 0).getTime()))); - assertTrue("StartRule improperly set5", !(st - .inDaylightTime(new GregorianCalendar(1999, Calendar.NOVEMBER, - 14, 12, 0).getTime()))); - } - - /** - * @tests java.util.SimpleTimeZone#setStartYear(int) - */ - public void test_setStartYearI() { - // Test for method void java.util.SimpleTimeZone.setStartYear(int) - SimpleTimeZone st = new SimpleTimeZone(1000, "Test_TZ"); - st.setStartRule(Calendar.NOVEMBER, 1, Calendar.SUNDAY, 0); - st.setEndRule(Calendar.NOVEMBER, -1, Calendar.SUNDAY, 0); - st.setStartYear(1999); - assertTrue("set year improperly set1", !(st - .inDaylightTime(new GregorianCalendar(1999, Calendar.JULY, 12) - .getTime()))); - assertTrue("set year improperly set2", !(st - .inDaylightTime(new GregorianCalendar(1998, Calendar.OCTOBER, - 13).getTime()))); - assertTrue("set year improperly set3", (st - .inDaylightTime(new GregorianCalendar(1999, Calendar.NOVEMBER, - 13).getTime()))); - } - - /** - * @tests java.util.SimpleTimeZone#toString() - */ - public void test_toString() { - // Test for method java.lang.String java.util.SimpleTimeZone.toString() - String string = TimeZone.getTimeZone("EST").toString(); - assertNotNull("toString() returned null", string); - assertTrue("toString() is empty", string.length() != 0); - } - - /** - * @tests java.util.SimpleTimeZone#useDaylightTime() - */ - public void test_useDaylightTime() { - // Test for method boolean java.util.SimpleTimeZone.useDaylightTime() - SimpleTimeZone st = new SimpleTimeZone(1000, "Test_TZ"); - assertTrue("useDaylightTime returned incorrect value", !st - .useDaylightTime()); - // Spec indicates that both end and start must be set or result is - // undefined - st.setStartRule(Calendar.NOVEMBER, 1, Calendar.SUNDAY, 0); - st.setEndRule(Calendar.NOVEMBER, -1, Calendar.SUNDAY, 0); - assertTrue("useDaylightTime returned incorrect value", st - .useDaylightTime()); - } - - /** - * Sets up the fixture, for example, open a network connection. This method - * is called before a test is executed. - */ - protected void setUp() { - } - - /** - * Tears down the fixture, for example, close a network connection. This - * method is called after a test is executed. - */ - protected void tearDown() { - } + st.setStartRule(Calendar.NOVEMBER, 1, Calendar.SUNDAY, 0); + st.setEndRule(Calendar.NOVEMBER, -1, Calendar.SUNDAY, 0); + st.setStartYear(1999); + assertTrue("set year improperly set1", !(st + .inDaylightTime(new GregorianCalendar(1999, Calendar.JULY, 12) + .getTime()))); + assertTrue("set year improperly set2", !(st + .inDaylightTime(new GregorianCalendar(1998, Calendar.OCTOBER, + 13).getTime()))); + assertTrue("set year improperly set3", (st + .inDaylightTime(new GregorianCalendar(1999, Calendar.NOVEMBER, + 13).getTime()))); + } + + /** + * java.util.SimpleTimeZone#toString() + */ + public void test_toString() { + // Test for method java.lang.String java.util.SimpleTimeZone.toString() + String string = TimeZone.getTimeZone("EST").toString(); + assertNotNull("toString() returned null", string); + assertTrue("toString() is empty", string.length() != 0); + } + + /** + * java.util.SimpleTimeZone#useDaylightTime() + */ + public void test_useDaylightTime() { + // Test for method boolean java.util.SimpleTimeZone.useDaylightTime() + SimpleTimeZone st = new SimpleTimeZone(1000, "Test_TZ"); + assertTrue("useDaylightTime returned incorrect value", !st + .useDaylightTime()); + // Spec indicates that both end and start must be set or result is + // undefined + st.setStartRule(Calendar.NOVEMBER, 1, Calendar.SUNDAY, 0); + st.setEndRule(Calendar.NOVEMBER, -1, Calendar.SUNDAY, 0); + assertTrue("useDaylightTime returned incorrect value", st + .useDaylightTime()); + } + + public void test_getOffsetJ() { + Calendar cal = Calendar.getInstance(); + cal.set(1998, Calendar.NOVEMBER, 11, 0, 0); + st1 = new SimpleTimeZone(TimeZone.getTimeZone("EST").getRawOffset(), "EST"); + + assertTrue("Incorrect offset returned", st1.getOffset(cal.getTimeInMillis()) == + -(5 * 60 * 60 * 1000)); + + st1 = new SimpleTimeZone(TimeZone.getTimeZone("EST").getRawOffset(), "EST"); + cal.set(1998, Calendar.JUNE, 11, 0, 0); + assertEquals("Incorrect offset returned", -(5 * 60 * 60 * 1000), st1 + .getOffset(cal.getTimeInMillis())); + + // Regression for HARMONY-5459 + st1 = new SimpleTimeZone(TimeZone.getDefault().getRawOffset(), TimeZone.getDefault().getID()); + int fourHours = 4*60*60*1000; + st1.setRawOffset(fourHours); + cal.set(2099, 01, 1, 0, 0); + + assertEquals(fourHours, st1.getOffset(cal.getTimeInMillis())); + + } + + + /** + * Sets up the fixture, for example, open a network connection. This method + * is called before a test is executed. + */ + protected void setUp() { + } + + /** + * Tears down the fixture, for example, close a network connection. This + * method is called after a test is executed. + */ + protected void tearDown() { + } } diff --git a/jre_emul/apache_harmony/classlib/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/util/TimeZoneTest.java b/jre_emul/apache_harmony/classlib/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/util/TimeZoneTest.java index de0ad9ea95..b03bd8ef6d 100644 --- a/jre_emul/apache_harmony/classlib/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/util/TimeZoneTest.java +++ b/jre_emul/apache_harmony/classlib/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/util/TimeZoneTest.java @@ -18,151 +18,204 @@ package org.apache.harmony.luni.tests.java.util; import tests.support.Support_TimeZone; - import java.util.Arrays; import java.util.Calendar; +import java.util.Date; import java.util.GregorianCalendar; import java.util.List; import java.util.Locale; +import java.util.SimpleTimeZone; import java.util.TimeZone; public class TimeZoneTest extends junit.framework.TestCase { - private static final int ONE_HOUR = 3600000; - - /** - * @tests java.util.TimeZone#getDefault() - */ - public void test_getDefault() { - assertNotSame("returns identical", - TimeZone.getDefault(), TimeZone.getDefault()); - } - - /** - * @tests java.util.TimeZone#getDSTSavings() - */ - 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", - ONE_HOUR, 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) - */ - 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)); - - // 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)); - long time2 = new GregorianCalendar(1998, Calendar.JUNE, 11) - .getTimeInMillis(); - 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) - */ - 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 proper GMT formatted string for GMT-8.45.", - "GMT-0845", 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+0830", 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+0302", TimeZone.getTimeZone("GMT+3:02").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", TimeZone.getTimeZone("GMT-00").getID()); - } - + private static final int ONE_HOUR = 3600000; + + private TimeZone processDefault; + + /** + * java.util.TimeZone#getDefault() + */ + public void test_getDefault() { + assertNotSame("returns identical", + TimeZone.getDefault(), TimeZone.getDefault()); + } + + /** + * java.util.TimeZone#getDSTSavings() + */ + public void test_getDSTSavings() { + // Test for method int java.util.TimeZone.getDSTSavings() + + // test on subclass SimpleTimeZone + TimeZone st1 = TimeZone.getTimeZone("America/New_York"); + assertEquals("T1A. Incorrect daylight savings returned", + ONE_HOUR, 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#getDisplayName(java.util.Locale) + * java.util.TimeZone#getOffset(long) + */ + 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)); + } + + /** + * java.util.TimeZone#getTimeZone(java.lang.String) + */ + 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()); + + // j2objc: NSTimeZone can actually parse this format. + // assertEquals("Must return GMT when given an invalid TimeZone time GMT-8.45.", + // "GMT", TimeZone.getTimeZone("GMT-8.45").getID()); + assertEquals("Must return proper GMT formatted string for GMT-8.45.", + "GMT-0845", 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()); + + // j2objc: NSTimeZone can actually parse this format. + // 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+8:30 (eg. GMT+08:20).", + "GMT+0830", 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()); + + // j2objc: NSTimeZone can actually parse this format. + // 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+3:02 (eg. GMT+08:20).", + "GMT+0302", 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()); + + // j2objc: NSTimeZone treats GMT-00 as GMT. + // // 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()); + assertEquals("Must return proper GMT formatted string for GMT-00 (eg. GMT+08:20).", + "GMT", TimeZone.getTimeZone("GMT-00").getID()); + } + + /** + * java.util.TimeZone#setDefault(java.util.TimeZone) + */ + public void test_setDefaultLjava_util_TimeZone() { + // NOTE: Required to get tests passing under vogar. Vogar sets + // a hardcoded timezone before running every test, so we have to + // set it back to the "real" default before we run the test. + TimeZone.setDefault(null); + + 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()); + } + + /** + * java.util.TimeZone#getDisplayName(java.util.Locale) */ public void test_getDisplayNameLjava_util_Locale() { TimeZone timezone = TimeZone.getTimeZone("Asia/Shanghai"); - assertEquals("\u4e2d\u56fd\u6807\u51c6\u65f6\u95f4", - timezone.getDisplayName(Locale.CHINA)); + assertEquals("\u4e2d\u56fd\u6807\u51c6\u65f6\u95f4", timezone + .getDisplayName(Locale.CHINA)); } - + /** - * @tests java.util.TimeZone#getDisplayName(boolean, int, java.util.Locale) - * + * java.util.TimeZone#getDisplayName(boolean, int, java.util.Locale) */ public void test_getDisplayNameZILjava_util_Locale() { TimeZone timezone = TimeZone.getTimeZone("Asia/Shanghai"); + + // j2objc: disabled; use an older assertion that also works on OS X/iOS. + // /* Time zone data was changed in ICU49.2. Many common short names were removed. */ + // assertEquals("中国标准时间", + // timezone.getDisplayName(false, TimeZone.LONG, Locale.CHINA)); + // assertEquals("GMT+08:00", + // timezone.getDisplayName(false, TimeZone.SHORT, Locale.CHINA)); assertTrue("\u4e2d\u56fd\u6807\u51c6\u65f6\u95f4".equals( - timezone.getDisplayName(false, TimeZone.LONG, Locale.CHINA))); + timezone.getDisplayName(false, TimeZone.LONG, Locale.CHINA))); + try { timezone.getDisplayName(false, 100, Locale.CHINA); fail("should throw IllegalArgumentException"); @@ -170,25 +223,57 @@ public void test_getDisplayNameZILjava_util_Locale() { // expected } } - - protected void setUp() { - } - protected void tearDown() { - } - - /** - * @add test {@link java.util.TimeZone#getAvailableIDs(int)} + /* + * Regression for HARMONY-5860 */ + 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() { + processDefault = TimeZone.getDefault(); + } + + protected void tearDown() { + TimeZone.setDefault(processDefault); + } + + public void test_getAvailableIDs_I_16947622() { + TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles"); + int rawOffset = tz.getRawOffset(); + assertEquals(-8 * 60 * 60 * 1000, rawOffset); + List ids = Arrays.asList(TimeZone.getAvailableIDs(rawOffset)); + + // Obviously, for all time zones, the time zone whose raw offset we started with + // should be one of the available ids for that offset. + assertTrue(ids.toString(), ids.contains("America/Los_Angeles")); + + // Any one of these might legitimately change its raw offset, though that's + // fairly unlikely, and the chances of more than one changing are very slim. + assertTrue(ids.toString(), ids.contains("America/Dawson")); + assertTrue(ids.toString(), ids.contains("America/Tijuana")); + assertTrue(ids.toString(), ids.contains("America/Vancouver")); + + // j2objc: NSTimeZone does not list Canada/* as known time zone names. + // assertTrue(ids.toString(), ids.contains("Canada/Pacific")); + // assertTrue(ids.toString(), ids.contains("Canada/Yukon")); + assertTrue(ids.toString(), ids.contains("Pacific/Pitcairn")); + } + public void test_getAvailableIDs_I() { TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai"); int rawoffset = tz.getRawOffset(); String[] ids = TimeZone.getAvailableIDs(rawoffset); List idList = Arrays.asList(ids); - assertTrue("Asia/Shanghai and Asia/Hong_Kong should have the same rawoffset", - idList.contains("Asia/Hong_Kong")); + assertTrue(idList.toString(), idList.contains("Asia/Hong_Kong")); } - + /** * @add test {@link java.util.TimeZone#getDisplayName()} */ @@ -198,7 +283,7 @@ public void test_getDisplayName() { String defaultName = defaultZone.getDisplayName(); String expectedName = defaultZone.getDisplayName(defaulLocal); assertEquals( - "getDisplayName() did not return the default Locale suitable name", + "getDispalyName() did not return the default Locale suitable name", expectedName, defaultName); } @@ -221,6 +306,11 @@ public void test_getDisplayName_ZI() { */ public void test_hasSameRules_Ljava_util_TimeZone() { TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai"); + + // j2objc: disabled. This test can be problematic. The first id in the ids array that does + // not have the same id as tz may actually not have the same rules. We use another test in + // NativeTimeZoneTest to cover the method hasSameRules. + /* int offset = tz.getRawOffset(); String[] ids = TimeZone.getAvailableIDs(offset); @@ -236,6 +326,8 @@ public void test_hasSameRules_Ljava_util_TimeZone() { } } } + */ + assertFalse("should return false when parameter is null", tz .hasSameRules(null)); } diff --git a/jre_emul/java_sources.mk b/jre_emul/java_sources.mk index 0b4054d4ce..c8a096b3ef 100644 --- a/jre_emul/java_sources.mk +++ b/jre_emul/java_sources.mk @@ -353,6 +353,7 @@ JAVA_PUBLIC_SOURCES_CORE = \ JAVA_PRIVATE_SOURCES_CORE = \ com/google/j2objc/LibraryNotLinkedError.java \ com/google/j2objc/ReflectionStrippedError.java \ + com/google/j2objc/util/NativeTimeZone.java \ com/google/j2objc/util/ScopedLocalRef.java \ dalvik/system/BlockGuard.java \ dalvik/system/CloseGuard.java \ diff --git a/jre_emul/tests.mk b/jre_emul/tests.mk index b95e37b3e1..65a8b757e8 100644 --- a/jre_emul/tests.mk +++ b/jre_emul/tests.mk @@ -217,6 +217,7 @@ TEST_SOURCES := \ com/google/j2objc/ThrowableTest.java \ com/google/j2objc/net/NSErrorExceptionTest.java \ com/google/j2objc/security/IosSecureRandomImplTest.java \ + com/google/j2objc/util/NativeTimeZoneTest.java \ dalvik/system/JniTest.java \ java/lang/SystemTest.java \ java/lang/ref/PhantomReferenceTest.java \