From y.umaoka at gmail.com Tue Aug 12 14:59:18 2008 From: y.umaoka at gmail.com (Yoshito Umaoka) Date: Tue, 12 Aug 2008 17:59:18 -0400 Subject: TimeZone API for getting raw offset and daylight saving amount Message-ID: <48A207B6.7000507@gmail.com> Hello all, I'm experiencing a problem for setting my own TimeZone implementation as system default time zone. After some investigation, I think this problem is caused by the lack of API in java.util.TimeZone. When TimeZone was introduced in JDK 1.1, it did not support historical GMT offsets/daylight saving time rules. So "raw" offset is always same at anytime. When JDK 1.4 implemented historic rules, APIs were not much changed. With TimeZone methods, you can get GMT offset at the specified time. You can also see if the specified time is in daylight saving time or not. HOWEVER, you have no way to know "raw" GMT offset and daylight saving amount. This is usually not a problem, because you can still get the GMT offset (raw + dstsaving). The problem shows up when TimeZone is used by Calendar. Calendar has two fields - ZONE_OFFSET and DST_OFFSET. Calendar implementation obviously needs to get the raw GMT offset and the daylight saving amount for setting these fields. However, there are no such APIs in TimeZone class. Calendar implementation calls my TimeZone subclass's getRawOffset()/getDSTSavings() instead. getRawOffset() and getDSTSavings() are somewhat broken when the historic rule support was introduced. The raw GMT offset and the daylight saving amount could change time to time. But these APIs do not take any arguments specifying date. Calendar code calls another method supporting historic raw/dst amount changes when the implementation class of TimeZone is JDK's own private one. I think such API should be added in TimeZone as a public API, so Java users can implement their own TimeZone subclasses which work well with Calendar. In our project (ICU4J), we added an API below in our TimeZone class - public void getOffset(long date, boolean local, int[] offsets) This API returns the raw offset in offsets[0] and the daylight saving amount in offsets[1] at the specified time. I do not think the second argument (specifying whether 'date' is local wall time or GMT) is necessary. I think JDK TimeZone also needs such method to resolve Calendar field calculation problem above. The default implementation would be - public void getOffset(long date, int[] offsets) { if (offsets == null || offsets.length < 2) { offsets = new int[2]; } if (inDaylightTime(new Date(date)) { offsets[1] = getDSTSavings(); offsets[0] = getOffset(date) - offsets[1]; } else { offsets[0] = getOffset(date); offsets[1] = 0; } } I propose to add this method in java.util.TimeZone and use it in JDK Calendar implementation. Any opinions? Yoshito Umaoka (ICU Project) From y.umaoka at gmail.com Wed Aug 13 12:14:42 2008 From: y.umaoka at gmail.com (Yoshito Umaoka) Date: Wed, 13 Aug 2008 15:14:42 -0400 Subject: TimeZone API for getting raw offset and daylight saving amount In-Reply-To: <48A207B6.7000507@gmail.com> References: <48A207B6.7000507@gmail.com> Message-ID: <48A332A2.5080005@gmail.com> Oops.. stupid mistake in the previous note.. > public void getOffset(long date, int[] offsets) { > if (offsets == null || offsets.length < 2) { > offsets = new int[2]; > } > if (inDaylightTime(new Date(date)) { > offsets[1] = getDSTSavings(); > offsets[0] = getOffset(date) - offsets[1]; > } else { > offsets[0] = getOffset(date); > offsets[1] = 0; > } > } int[] is not a return value of the method.. Just let it throw NullPointerException or ArrayIndexOutOfBoundsException when int[] offsets is null or too short. public void getOffset(long date, int[] offsets) { if (inDaylightTime(new Date(date)) { offsets[1] = getDSTSavings(); offsets[0] = getOffset(date) - offsets[1]; } else { offsets[0] = getOffset(date); offsets[1] = 0; } } Yoshito Umaoka (ICU Project) From Masayoshi.Okutsu at Sun.COM Wed Aug 13 19:05:39 2008 From: Masayoshi.Okutsu at Sun.COM (Masayoshi Okutsu) Date: Thu, 14 Aug 2008 11:05:39 +0900 Subject: TimeZone API for getting raw offset and daylight saving amount In-Reply-To: <48A207B6.7000507@gmail.com> References: <48A207B6.7000507@gmail.com> Message-ID: <48A392F3.8060804@sun.com> Hi Umaoka-san, Thank you for your proposal. Yes, the TimeZone class has some built-in assumptions which cause many problems. I had been planning to introduce some methods, one of which is very similar to your proposal, mainly for fixing the disambiguation problem during the standard-daylight transitions. I still want to fix it in JDK7, but I'm not sure if I can have time to do so at this point. Thanks, Masayoshi On 8/13/2008 6:59 AM, Yoshito Umaoka wrote: > Hello all, > > I'm experiencing a problem for setting my own TimeZone implementation > as system default time zone. After some investigation, I think this > problem is caused by the lack of API in java.util.TimeZone. > > When TimeZone was introduced in JDK 1.1, it did not support historical > GMT offsets/daylight saving time rules. So "raw" offset is always > same at anytime. When JDK 1.4 implemented historic rules, APIs were > not much changed. > > With TimeZone methods, you can get GMT offset at the specified time. > You can also see if the specified time is in daylight saving time or > not. HOWEVER, you have no way to know "raw" GMT offset and daylight > saving amount. This is usually not a problem, because you can still > get the GMT offset (raw + dstsaving). The problem shows up when > TimeZone is used by Calendar. > > Calendar has two fields - ZONE_OFFSET and DST_OFFSET. Calendar > implementation obviously needs to get the raw GMT offset and the > daylight saving amount for setting these fields. However, there are > no such APIs in TimeZone class. Calendar implementation calls my > TimeZone subclass's getRawOffset()/getDSTSavings() instead. > > getRawOffset() and getDSTSavings() are somewhat broken when the > historic rule support was introduced. The raw GMT offset and the > daylight saving amount could change time to time. But these APIs do > not take any arguments specifying date. > > Calendar code calls another method supporting historic raw/dst amount > changes when the implementation class of TimeZone is JDK's own private > one. I think such API should be added in TimeZone as a public API, so > Java users can implement their own TimeZone subclasses which work well > with Calendar. > > In our project (ICU4J), we added an API below in our TimeZone class - > > public void getOffset(long date, boolean local, int[] offsets) > > This API returns the raw offset in offsets[0] and the daylight saving > amount in offsets[1] at the specified time. I do not think the second > argument (specifying whether 'date' is local wall time or GMT) is > necessary. I think JDK TimeZone also needs such method to resolve > Calendar field calculation problem above. The default implementation > would be - > > public void getOffset(long date, int[] offsets) { > if (offsets == null || offsets.length < 2) { > offsets = new int[2]; > } > if (inDaylightTime(new Date(date)) { > offsets[1] = getDSTSavings(); > offsets[0] = getOffset(date) - offsets[1]; > } else { > offsets[0] = getOffset(date); > offsets[1] = 0; > } > } > > I propose to add this method in java.util.TimeZone and use it in JDK > Calendar implementation. Any opinions? > > > Yoshito Umaoka (ICU Project) From Masayoshi.Okutsu at Sun.COM Wed Aug 13 19:06:46 2008 From: Masayoshi.Okutsu at Sun.COM (Masayoshi Okutsu) Date: Thu, 14 Aug 2008 11:06:46 +0900 Subject: TimeZone API for getting raw offset and daylight saving amount In-Reply-To: <48A332A2.5080005@gmail.com> References: <48A207B6.7000507@gmail.com> <48A332A2.5080005@gmail.com> Message-ID: <48A39336.9000608@sun.com> I agree that the revised one is reasonable. Thanks, Masayoshi On 8/14/2008 4:14 AM, Yoshito Umaoka wrote: > Oops.. stupid mistake in the previous note.. > > > public void getOffset(long date, int[] offsets) { > > if (offsets == null || offsets.length < 2) { > > offsets = new int[2]; > > } > > if (inDaylightTime(new Date(date)) { > > offsets[1] = getDSTSavings(); > > offsets[0] = getOffset(date) - offsets[1]; > > } else { > > offsets[0] = getOffset(date); > > offsets[1] = 0; > > } > > } > > int[] is not a return value of the method.. > Just let it throw NullPointerException or > ArrayIndexOutOfBoundsException when int[] offsets is null > or too short. > > public void getOffset(long date, int[] offsets) { > if (inDaylightTime(new Date(date)) { > offsets[1] = getDSTSavings(); > offsets[0] = getOffset(date) - offsets[1]; > } else { > offsets[0] = getOffset(date); > offsets[1] = 0; > } > } > > Yoshito Umaoka (ICU Project) From y.umaoka at gmail.com Thu Aug 14 07:59:37 2008 From: y.umaoka at gmail.com (Yoshito Umaoka) Date: Thu, 14 Aug 2008 10:59:37 -0400 Subject: TimeZone API for getting raw offset and daylight saving amount In-Reply-To: <48A392F3.8060804@sun.com> References: <48A207B6.7000507@gmail.com> <48A392F3.8060804@sun.com> Message-ID: <48A44859.1040908@gmail.com> Hi Okutsu-san, > Thank you for your proposal. Yes, the TimeZone class has some built-in > assumptions which cause many problems. I had been planning to introduce > some methods, one of which is very similar to your proposal, mainly for > fixing the disambiguation problem during the standard-daylight transitions. Thanks for the information. It would be great to have the problems resolved in JDK 7. I once went through the ambiguous wall time problems at transitions. I found several tricky cases other than annual daylight->standard transitions. 1) Negative raw offset shift. For example, GMT-05:00(standard) to GMT-06:00(standard). 2) Negative daylight saving amount change. There were some zones used "double summer time" in the past. Transition from "double summer time" to regular summer time created ambiguous time range. 3) Positive offset change at daylight->standard transition. For example, America/Nome at Oct 30, 1983 - GMT-10:00(daylight) to GMT-09:00(standard). My conclusion was that adding a flag indicating standard time or daylight saving time was not enough to resolve ambiguous wall time problems. We implemented such feature in ICU, but not exposed yet. Yoshito Umaoka (ICU Project)