Okutsu-san,
Thanks for your quick reply. I looked at the JDK-6380023. I think my
point was slightly different - what I want to do is to create my own
time zone and use it as default JRE's time zone. But, I agree that the
things discussed in the bug are necessary to achieve my goal with
java.util.TimeZone.
With JSR-310 changes, can we do this through ZoneRulesProvider SPI?
Assume my goal is to support 'latest' rules from tz database, without
waiting/updating time zone data update patch from Oracle (or others) -
and use them in both traditional date/time APIs (Calendar/DateFormat) as
well as java.time APIs. In this case, can I achieve the goal with -
1) Implement my own ZoneRulesProvider with a new unique zone id - e.g.
"Boston-MA"
2) TimeZone.setDefault(TimeZone.getTimeZone("Boston-MA"))
With this approach, can I override the default time zone of the JRE,
with all historic/future rule changes implemented by my custom zone
"Boston-MA"?
-Yoshito
On 10/19/2014 8:03 PM, Masayoshi Okutsu wrote:
Hi Umaoka-san,
Thanks for your bug report which I've closed as a duplicate of
JDK-6380023. Yes, it's an API design flaw of java.util.TimeZone.
Since we now have the java.time API, I guess JDK-6380023 doesn't have
any high priority (unless it gets escalated by someone).
Regards,
Masayoshi
On 10/18/2014 5:43 AM, Yoshito Umaoka wrote:
Dear Java i18n team,
I was looking at recent Russian time zone changes and noticed a
design issue in JDK. I think I knew this issue, but I forgot about
this until recently. The problem is - Java does not support user
defined custom TimeZone implementation properly.
java.util.TimeZone is quite old, and the original design assumed 'raw
offset' and 'daylight saving amount' will never changed. To implement
a subclass of TimeZone, you have to override an awkward abstract
method - abstract int getOffset(int era, int year, int month, int
day, int dayOfWeek, int milliseconds). This method signature itself
does not limit a custom TimeZone implementation to support historic
raw/dst offset changes. However, if you do so, you will see some
problems in other places.
I filed a bug below:
====
Java should handle user defined TimeZone subclass instances
supporting historic rule changes properly.
You can create a custom time zone implementation class by extending
java.util.TimeZone. By the contract, the subclass must implement a
few methods:
abstract int getOffset(int,int,int,int,int,int);
abstract int getRawOffset();
abstract boolean inDaylightTime(Date);
abstract void setRawOffset(int);
abstract boolean useDaylightTime();
Although, the interface above do not assume UTC offset or daylight
saving amount is not changing time to time, a user can provide an
implementation supporting historic UTC offset changes by int
getOffset(int,int,int,int,int,int). However, there are two Java
implementation problems.
1. The default implementation of TimeZone#getOffset(long date) does
not use the abstract method - int getOffset(int,int,int,int,int,int).
Therefore, when a different 'raw' offset was used in the past, or
will be used in future, getOffset(long) always returns a result
calculated from getRawOffset() and getDSTSavings(). Although a
subclass implementation can provide TimeZone#getOffset(long date),
the default implementation should use
getOffset(int,int,int,int,int,int).
2. java.util.GregorianCalendar checks if a TimeZone instance is
sun.util.calendar.TimZone or not, and if not, the offset field is
calculated based on getRawOffset() / getDSTSavings(). Therefore, even
a custom TimeZone implementation support different 'raw' offsets in
the past or future, current 'raw' offset (getRawOffset()) value is used.
Use case:
A user may want to create a custom TimeZone instance from iCalendar
VTIMEZONE component. iCalendr VTIMEZONE can support historic time
zone rule changes.
Suggestions:
1) Add API TimeZone#getRawOffset(long) with the default
implementation - return getRawOffset().
2) Add API TimeZone#getDSTSavings(long) with the default
implementation - return getDSTSavings().
2) Update the default implementation of TimeZone#getOffset(long) to
use #getRawOffset(long) #getDSTSavings(long) above along is existing
#inDaylightTime(Date).
3) Gregorian calendar to use #getRawOffset(long) and
#getDSTSavings(long), if not ZoneInfo.
====
There is an IETF working draft for timezone service protocol. In
future, someone may want to create a custom time zone, interacting
with a timezone service server to get the latest time zone rule data,
instead of applying tzdata update utility. In this case, such
limitation becomes a blocker. There are several ways to resolve the
issue - I just suggested one way in the bug report. Are there anyone
willing to look into this?
Thanks,
Yoshito