Proposal for rule based time zone (ticket#5454)

View: New views
4 Messages — Rating Filter:   Alert me  

Proposal for rule based time zone (ticket#5454)

by yoshito_umaoka :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


This is a design proposal for "Rule based time zone" -> http://bugs.icu-project.org/trac/ticket/5454
Please review this design proposal and provide your feedback.

Thanks
Yoshito
-----------------------------------------------------

Scope of the RFE

1) ICU uses timezone.res which is generated from Olson tzdata.  Although you can get UTC offset of local time, you cannot get when the offset is changed.  For example, some ICU clients may want to get next daylight saving time start/end date for some reasons.  For now, what ICU clients can do is to probe UTC offset at a certain date, then find the point of time when the offset is changed by binary search.  The ICU internal time zone data actually contains the time of transitions or rule used for getting the transitions.  But there are no APIs to access the transitions at this moment.

2) ICU clients may want to define their own time zones.  For now, SimpleTimeZone is only the class which you can use to create a custom time zone.  SimpleTimeZone does not support historical rule changes.  If you really want to define a time zone with historical rule changes, you will need to subclass TimeZone and write your own TimeZone class.

3) iCalendar is a standard calendar protocol and has its own way to represent time zones.  When you develop a calendar application, you may need to extract offset transition rules for a time zone when composing an iCalendar message.  Also, when parsing an iCalendar message, you will need to parse the time zone definitions in RFC2445 format and create a TimeZone object to be used in your code.  Technically, if above 2 items are supported (extracting transition rules/generating a time zone object by historical rules), you can write your own RFC2445 VTIMEZONE formatter/parser.  But implementing the formatter/parser is not a trivial work, so ICU clients may want to have the implementation in ICU itself.


Overview of proposed APIs

The proposed API documentation is found here -> http://source.icu-project.org/repos/icu/icuhtml/trunk/design/rbtz/ICU4J_JavaDoc/index.html
ICU4C APIs will be added soon.

1) TimeZoneRule/AnnualTimeZoneRule/TimeArrayTimeZoneRule

TimeZoneRule is a class representing a rule for a time zone.  TimeZoneRule has next 3 fields - name, standard offset and daylight saving.  For example, US Eastern Daylight Saving Time may be represented by name = "EDT" / standard offset = -18000000 (milliseconds) / daylight saving = 3600000.   There are two subclasses of TimeZoneRule - AnnualTimeZoneRule and TimeArrayTimeZoneRule.

AnnualTimeZoneRule  defines start times by an instance of AnnualDateTimeRule.  AnnualDateTimeRule is a class representing a rule date/time.  The rule date can be specified by 4 different ways (day of month, Nth weekday in month, first weekday after day of month, last weekday before day of month).  The time rule can be specified 3 different type - WALL_TIME, STANDARD_TIME and UNIVERSAL_TIME.  They are equivalent to rules which are currently used in SimpleTimeZone internally.  AnnualTimeZoneRule also defines applicable year range.

For example, US Eastern Daylight Saving time since 1987 is represented by next two AnnualTimeZoneRule instances.

// First Sunday on or after April 1st, 2AM at local wall time
AnnualDateTimeRule dtRule1 = new AnnualDateTimeRule(Calendar.APRIL, 1, Calendar.SUNDAY, true,
                                                    2*60*60*1000, AnnualDateTimeRule.WALL_TIME);
// First Sunday on or after March 8th, 2AM at local wall time
AnnualDateTimeRule dtRule2 = new AnnualDateTimeRule(Calendar.MARCH, 8, Calendar.SUNDAY, true,
                                                    2*60*60*1000, AnnualDateTimeRule.WALL_TIME);

// Rule for 1987 - 2006
AnnualTimeZoneRule tzRule1 = new AnnualTimeZoneRule("EDT", // name of time zone
                                                    -5*60*60*1000, // standard UTC offset -5 hours
                                                    1*60*60*1000, // daylight saving
                                                    dtRule1, // annual date time rule
                                                    1987, // start year
                                                    2006); // end year
// Rule for 2007 -
AnnualTimeZoneRule tzRule1 = new AnnualTimeZoneRule("EDT", // name of time zone
                                                    -5*60*60*1000, // standard UTC offset -5 hours
                                                    1*60*60*1000, // daylight saving
                                                    dtRule2, // annual date time rule
                                                    2007, // start year
                                                    AnnualTimeZoneRule.MAX_YEAR); // end year - forever


TimeArrayTimeZoneRule defines start times by an array of  milliseconds since UTC epoch time (Jan 1, 1970 00:00:00).


2) TimeZoneTransition

TimeZoneTransition is a class repesenting a single time transition.  A TimeZoneTransition has 3 fields - time, time zone rule before/after the time.  TimeZoneTransition objects are used as return type in new APIs.


3) HasTimeZoneTransitions

HasTimeZoneTransitions is an interface which defines two methods -

public TimeZoneTransition getNextTransition(long base);
public TimeZoneTransition getPreviousTransition(long base);

TimeZone Implementation classes - SimpleTimeZone and OlsonTimeZone - will implement the interface to allow ICU clients to get exact time when time is changed.  For example, next Java code snipet will return the next time transition in time zone "America/New_York".

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", ULocale.ROOT);
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));

TimeZoneTransition nextTT = TimeZone.getTimeZone("America/New_York").getNextTransition(System.currentTimeMillis());

System.out.println("Next transition time: " + sdf.format(new Date(nextTT.getTime())));
System.out.println("From: " + nextTT.getFrom().getStdOffset() + "/" + nextTT.getFrom().getDstSaving());
System.out.println("To:   " + nextTT.getTo().getStdOffset() + "/" + nextTT.getTo().getDstSaving());

Above code snipet will print out the results below (as of now) -

Next transition time: 2007-11-04T06:00:00Z
From: -18000000/3600000
To:   -18000000/0


4) RuleBasedTimeZone

RuleBasedTimeZone is a subclass of TimeZone for creating a custom time zone by rules.  The constructor takes 4 arguments - time zone ID, initial time name/standard offset/daylight saving.  When the instance is created, it has fixed UTC offset.  Then you can add your own rules defined by AnnualTimeZoneRule and/or TimeArrayTimeZoneRule objects.  Below is a coding example of RuleBasedTimeZone representing US Eastern time since 1967.

int HOUR = 60*60*1000;

RuleBasedTimeZone rbtz = new RuleBasedTimeZone("US_Eastern", "EST", -5*HOUR, 0);

AnnualDateTimeRule dtr;
AnnualTimeZoneRule tzr;

// Standard time
dtr = new AnnualDateTimeRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*HOUR, AnnualDateTimeRule.WALL_TIME);
tzr = new AnnualTimeZoneRule("EST", -5*HOUR, 0, dtr, 1967, 2006);
rbtz.addRule(tzr);

dtr = new AnnualDateTimeRule(Calendar.NOVEMBER, 1, Calendar.SUNDAY, true, 2*HOUR, AnnualDateTimeRule.WALL_TIME);
tzr = new AnnualTimeZoneRule("EST", -5*HOUR, 0, dtr, 2007, AnnualTimeZoneRule.MAX_YEAR);
rbtz.addRule(tzr);

// Daylight saving time
dtr = new AnnualDateTimeRule(Calendar.APRIL, -1, Calendar.SUNDAY, 2*HOUR, AnnualDateTimeRule.WALL_TIME);
tzr = new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, dtr, 1967, 1973);
rbtz.addRule(tzr);

dtr = new AnnualDateTimeRule(Calendar.JANUARY, 6, 2*HOUR, AnnualDateTimeRule.WALL_TIME);
tzr = new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, dtr, 1974, 1974);
rbtz.addRule(tzr);

dtr = new AnnualDateTimeRule(Calendar.FEBRUARY, 23, 2*HOUR, AnnualDateTimeRule.WALL_TIME);
tzr = new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, dtr, 1975, 1975);
rbtz.addRule(tzr);

dtr = new AnnualDateTimeRule(Calendar.APRIL, -1, Calendar.SUNDAY, 2*HOUR, AnnualDateTimeRule.WALL_TIME);
tzr = new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, dtr, 1976, 1986);
rbtz.addRule(tzr);

dtr = new AnnualDateTimeRule(Calendar.APRIL, 1, Calendar.SUNDAY, true, 2*HOUR, AnnualDateTimeRule.WALL_TIME);
tzr = new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, dtr, 1987, 2006);
rbtz.addRule(tzr);

dtr = new AnnualDateTimeRule(Calendar.MARCH, 8, Calendar.SUNDAY, true, 2*HOUR, AnnualDateTimeRule.WALL_TIME);
tzr = new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, dtr, 2007, AnnualTimeZoneRule.MAX_YEAR);
rbtz.addRule(tzr);


5) VTimeZone

VTimeZone is a subclass of TimeZone implementing RFC2445 iCalendar VTIMEZONE.  There are two ways to create an instance of VTimeZone - one from ICU/Olson time zone ID and another from VTIMEZONE data stream.  VTimeZone has a private member which store store either OlsonTimeZone or RuleBasedTimeZone.  When a VTimeZone object is created from ID, OlsonTimeZone is created for the ID.  When it is created from RFC2445 VTIMEZONE data stream, an instance of RuleBasedTimeZone is created and initialized by parsing rules in the RFC format.  VTimeZone provides two write methods in addition to TimeZone public APIs.

public boolean write(Writer writer)
public boolean write(Writer writer, long start, long end)

In general, all of historical transitions used by an ICU OlsonTimeZone is not necessary in iCalendar applications.  When you create an iCalendar message, you may only need time zone rules including the event times.  The second write method allow you to filter the rules and only pick rules applicable to the specified time range.  By doing so, you can reduce the size of VTIMEZONE data block in the iCalendar message.


Development note - design consideration, question, limitation and etc.

1) In last year, I proposed APIs supporting RuleBasedTimeZone and VTimeZone.  At that time, I designed APIs under strong ifluence of RFC2445 VTIMEZONE.  However, I realized the initial implementation was not ideal for supporting zic (Olson tzdata) source files.  Although implementing zic compiler was not an important goal, I wanted to reconsider the design to be able to support zic source files with less efforts.  The big difference between VTIMEZONE and zic syntax is - a time zone in VTIMEZONE has an attribute "TZOFFSETFROM".  Although the time of zone transition is specified by local wall time, you can get the exact UTC time when the rule starts without looking into other rules.  On the other hand, a single zic rule may only tell you the starts in local wall time without previous offset.  That means, to process rule/zone definitions in zic source format, you have to walk through the historical transitions from the begining.  Actually, VTIMEZONE syntax is somewhat error prone, because "to offset" may not match the next time's "from offset".  In the new proposal, I removed "from offset" in AnnualTimeZoneRule.  It allows you to transform zic source into the rule without looking into other past rules.

2) Although it is possible to use these APIs to implement a parser to create a TimeZone from zic source format, it is still not a trivial work.  With the zic syntax, standard offset transitions are separated from daylight saving transitions (Zone line vs. Rule line).  On the other hand, TimeZoneRule represent both standard offset and start times in a single object.  Thus, to implement zic parser, you need to go through both Zone lines and Rule lines to detect any changes including standard offset.  For example, the next zic source data -

# Rule        NAME        FROM        TO        TYPE        IN        ON        AT        SAVE        LETTER
Rule        FOO   1950  2000  -     Apr   1     1:00  1:00  D
Rule        FOO   1950  max   -     Oct   31    1:00  0:00  S
Rule        FOO   2001  max   -     Mar   1     1:00  1:00  D

# Rule        NAME        FROM        TO        TYPE        IN        ON        AT        SAVE        LETTER
Rule        BAR   1950  max   -     Apr   2     2:00  1:00  D
Rule        BAR   1950  max   -     Oct   30    2:00  0:00  S

# Zone        NAME                GMTOFF        RULES        FORMAT        [UNTIL]
Zone        Custom1     2:34:56     -     LMT         1960
                        2:30        BAR   B%sT        1990
                        2:00        FOO   F%sT

will be parsed into

- RuleBasedTimeZone constructed with initial name "LMT" with standard offset 1:23:45
- AnnualTimeZoneRule for daylight saving time (std 2:30/sav 1:00) starting on Apr 2 at 2am from 1961 to 1990 with name "BDT"
- AnnualTimeZoneRule for standard time (std 2:30/sav 0:00) starting on Oct 30 at 2am from 1961 to 1990 with name "BST"
- AnnualTimeZoneRule for daylight saving time (std 2:00/sav 1:00) on Apr 1 at 1am from 1991 to 2000 with name "FDT"
- AnnualTimeZoneRule for standard time (std 2:00/sav 0:00) on Oct 31 at 1am from 1991 to max with name "FST"
- AnnualTimeZoneRule for daylight saving time (std 2:00/sav 1:00) on Mar 1 at 1am from 2001 to max with name "FDT"

Does anyone want to have the zic parser implemented in ICU?

3) When you create VTimeZone instance from zone ID such as "America/New_York" and write out the rule into RFC2445 format, you will see historical transitions are represented by a list of date time, instead of the original rule such as 1st Sunday in April.  When ICU imports Olson tzdata into timezone.res, the tool already resolves historical transition times in UTC and they are no longer in mont/day rule format.  Only the latest rules might be represented in the format originally from tzdata.

4) RuleBasedTimeZone is a subclass of TimeZone, thus, it has getRawOffset(), setRawOffset(int), getDaylightSaving() and useDaylightTime().  These APIs do not make sense much in TimeZone implementation which supports historical transitions.  The implementation may try to return a result based on the currently active - except setRawOffset, which may do nothing.


-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
icu-design mailing list
icu-design@...
To Un/Subscribe: https://lists.sourceforge.net/lists/listinfo/icu-design

Re: Proposal for rule based time zone (ticket#5454)

by Mark Davis-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Some parts of this message have been removed. Learn more about Nabble's security policy.
Looks good to me; however, I wasn't able to see

http://source.icu-project.org/repos/icu/icuhtml/trunk/design/rbtz/ICU4J_JavaDoc/index.html

the link opens up a view into raw HTML.

Mark

On 5/14/07, yoshito_umaoka@... < yoshito_umaoka@...> wrote:

This is a design proposal for "Rule based time zone" -> http://bugs.icu-project.org/trac/ticket/5454
Please review this design proposal and provide your feedback.

Thanks
Yoshito
-----------------------------------------------------

Scope of the RFE

1) ICU uses timezone.res which is generated from Olson tzdata.  Although you can get UTC offset of local time, you cannot get when the offset is changed.  For example, some ICU clients may want to get next daylight saving time start/end date for some reasons.  For now, what ICU clients can do is to probe UTC offset at a certain date, then find the point of time when the offset is changed by binary search.  The ICU internal time zone data actually contains the time of transitions or rule used for getting the transitions.  But there are no APIs to access the transitions at this moment.

2) ICU clients may want to define their own time zones.  For now, SimpleTimeZone is only the class which you can use to create a custom time zone.  SimpleTimeZone does not support historical rule changes.  If you really want to define a time zone with historical rule changes, you will need to subclass TimeZone and write your own TimeZone class.

3) iCalendar is a standard calendar protocol and has its own way to represent time zones.  When you develop a calendar application, you may need to extract offset transition rules for a time zone when composing an iCalendar message.  Also, when parsing an iCalendar message, you will need to parse the time zone definitions in RFC2445 format and create a TimeZone object to be used in your code.  Technically, if above 2 items are supported (extracting transition rules/generating a time zone object by historical rules), you can write your own RFC2445 VTIMEZONE formatter/parser.  But implementing the formatter/parser is not a trivial work, so ICU clients may want to have the implementation in ICU itself.


Overview of proposed APIs

The proposed API documentation is found here -> http://source.icu-project.org/repos/icu/icuhtml/trunk/design/rbtz/ICU4J_JavaDoc/index.html
ICU4C APIs will be added soon.

1) TimeZoneRule/AnnualTimeZoneRule/TimeArrayTimeZoneRule

TimeZoneRule is a class representing a rule for a time zone.  TimeZoneRule has next 3 fields - name, standard offset and daylight saving.  For example, US Eastern Daylight Saving Time may be represented by name = "EDT" / standard offset = -18000000 (milliseconds) / daylight saving = 3600000.   There are two subclasses of TimeZoneRule - AnnualTimeZoneRule and TimeArrayTimeZoneRule.

AnnualTimeZoneRule  defines start times by an instance of AnnualDateTimeRule.  AnnualDateTimeRule is a class representing a rule date/time.  The rule date can be specified by 4 different ways (day of month, Nth weekday in month, first weekday after day of month, last weekday before day of month).  The time rule can be specified 3 different type - WALL_TIME, STANDARD_TIME and UNIVERSAL_TIME.  They are equivalent to rules which are currently used in SimpleTimeZone internally.  AnnualTimeZoneRule also defines applicable year range.

For example, US Eastern Daylight Saving time since 1987 is represented by next two AnnualTimeZoneRule instances.

// First Sunday on or after April 1st, 2AM at local wall time
AnnualDateTimeRule dtRule1 = new AnnualDateTimeRule(Calendar.APRIL, 1, Calendar.SUNDAY, true,
                                                    2*60*60*1000, AnnualDateTimeRule.WALL_TIME);
// First Sunday on or after March 8th, 2AM at local wall time
AnnualDateTimeRule dtRule2 = new AnnualDateTimeRule(Calendar.MARCH, 8, Calendar.SUNDAY, true,
                                                    2*60*60*1000, AnnualDateTimeRule.WALL_TIME);

// Rule for 1987 - 2006
AnnualTimeZoneRule tzRule1 = new AnnualTimeZoneRule("EDT", // name of time zone
                                                    -5*60*60*1000, // standard UTC offset -5 hours
                                                    1*60*60*1000, // daylight saving
                                                    dtRule1, // annual date time rule
                                                    1987, // start year
                                                    2006); // end year
// Rule for 2007 -
AnnualTimeZoneRule tzRule1 = new AnnualTimeZoneRule("EDT", // name of time zone
                                                    -5*60*60*1000, // standard UTC offset -5 hours
                                                    1*60*60*1000, // daylight saving
                                                    dtRule2, // annual date time rule
                                                    2007, // start year
                                                    AnnualTimeZoneRule.MAX_YEAR); // end year - forever


TimeArrayTimeZoneRule defines start times by an array of  milliseconds since UTC epoch time (Jan 1, 1970 00:00:00).


2) TimeZoneTransition

TimeZoneTransition is a class repesenting a single time transition.  A TimeZoneTransition has 3 fields - time, time zone rule before/after the time.  TimeZoneTransition objects are used as return type in new APIs.


3) HasTimeZoneTransitions

HasTimeZoneTransitions is an interface which defines two methods -

public TimeZoneTransition getNextTransition(long base);
public TimeZoneTransition getPreviousTransition(long base);

TimeZone Implementation classes - SimpleTimeZone and OlsonTimeZone - will implement the interface to allow ICU clients to get exact time when time is changed.  For example, next Java code snipet will return the next time transition in time zone "America/New_York".

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", ULocale.ROOT);
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));

TimeZoneTransition nextTT = TimeZone.getTimeZone("America/New_York").getNextTransition(System.currentTimeMillis());

System.out.println("Next transition time: " + sdf.format(new Date(nextTT.getTime())));
System.out.println("From: " + nextTT.getFrom().getStdOffset() + "/" + nextTT.getFrom().getDstSaving());
System.out.println("To:   " + nextTT.getTo().getStdOffset() + "/" + nextTT.getTo().getDstSaving());

Above code snipet will print out the results below (as of now) -

Next transition time: 2007-11-04T06:00:00Z
From: -18000000/3600000
To:   -18000000/0


4) RuleBasedTimeZone

RuleBasedTimeZone is a subclass of TimeZone for creating a custom time zone by rules.  The constructor takes 4 arguments - time zone ID, initial time name/standard offset/daylight saving.  When the instance is created, it has fixed UTC offset.  Then you can add your own rules defined by AnnualTimeZoneRule and/or TimeArrayTimeZoneRule objects.  Below is a coding example of RuleBasedTimeZone representing US Eastern time since 1967.

int HOUR = 60*60*1000;

RuleBasedTimeZone rbtz = new RuleBasedTimeZone("US_Eastern", "EST", -5*HOUR, 0);

AnnualDateTimeRule dtr;
AnnualTimeZoneRule tzr;

// Standard time
dtr = new AnnualDateTimeRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*HOUR, AnnualDateTimeRule.WALL_TIME);
tzr = new AnnualTimeZoneRule("EST", -5*HOUR, 0, dtr, 1967, 2006);
rbtz.addRule(tzr);

dtr = new AnnualDateTimeRule(Calendar.NOVEMBER, 1, Calendar.SUNDAY, true, 2*HOUR, AnnualDateTimeRule.WALL_TIME);
tzr = new AnnualTimeZoneRule("EST", -5*HOUR, 0, dtr, 2007, AnnualTimeZoneRule.MAX_YEAR);
rbtz.addRule(tzr);

// Daylight saving time
dtr = new AnnualDateTimeRule(Calendar.APRIL, -1, Calendar.SUNDAY, 2*HOUR, AnnualDateTimeRule.WALL_TIME);
tzr = new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, dtr, 1967, 1973);
rbtz.addRule(tzr);

dtr = new AnnualDateTimeRule(Calendar.JANUARY, 6, 2*HOUR, AnnualDateTimeRule.WALL_TIME);
tzr = new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, dtr, 1974, 1974);
rbtz.addRule(tzr);

dtr = new AnnualDateTimeRule(Calendar.FEBRUARY, 23, 2*HOUR, AnnualDateTimeRule.WALL_TIME);
tzr = new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, dtr, 1975, 1975);
rbtz.addRule(tzr);

dtr = new AnnualDateTimeRule(Calendar.APRIL, -1, Calendar.SUNDAY, 2*HOUR, AnnualDateTimeRule.WALL_TIME);
tzr = new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, dtr, 1976, 1986);
rbtz.addRule(tzr);

dtr = new AnnualDateTimeRule(Calendar.APRIL, 1, Calendar.SUNDAY, true, 2*HOUR, AnnualDateTimeRule.WALL_TIME);
tzr = new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, dtr, 1987, 2006);
rbtz.addRule(tzr);

dtr = new AnnualDateTimeRule(Calendar.MARCH, 8, Calendar.SUNDAY, true, 2*HOUR, AnnualDateTimeRule.WALL_TIME);
tzr = new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, dtr, 2007, AnnualTimeZoneRule.MAX_YEAR);
rbtz.addRule(tzr);


5) VTimeZone

VTimeZone is a subclass of TimeZone implementing RFC2445 iCalendar VTIMEZONE.  There are two ways to create an instance of VTimeZone - one from ICU/Olson time zone ID and another from VTIMEZONE data stream.  VTimeZone has a private member which store store either OlsonTimeZone or RuleBasedTimeZone.  When a VTimeZone object is created from ID, OlsonTimeZone is created for the ID.  When it is created from RFC2445 VTIMEZONE data stream, an instance of RuleBasedTimeZone is created and initialized by parsing rules in the RFC format.  VTimeZone provides two write methods in addition to TimeZone public APIs.

public boolean write(Writer writer)
public boolean write(Writer writer, long start, long end)

In general, all of historical transitions used by an ICU OlsonTimeZone is not necessary in iCalendar applications.  When you create an iCalendar message, you may only need time zone rules including the event times.  The second write method allow you to filter the rules and only pick rules applicable to the specified time range.  By doing so, you can reduce the size of VTIMEZONE data block in the iCalendar message.


Development note - design consideration, question, limitation and etc.

1) In last year, I proposed APIs supporting RuleBasedTimeZone and VTimeZone.  At that time, I designed APIs under strong ifluence of RFC2445 VTIMEZONE.  However, I realized the initial implementation was not ideal for supporting zic (Olson tzdata) source files.  Although implementing zic compiler was not an important goal, I wanted to reconsider the design to be able to support zic source files with less efforts.  The big difference between VTIMEZONE and zic syntax is - a time zone in VTIMEZONE has an attribute "TZOFFSETFROM".  Although the time of zone transition is specified by local wall time, you can get the exact UTC time when the rule starts without looking into other rules.  On the other hand, a single zic rule may only tell you the starts in local wall time without previous offset.  That means, to process rule/zone definitions in zic source format, you have to walk through the historical transitions from the begining.  Actually, VTIMEZONE syntax is somewhat error prone, because "to offset" may not match the next time's "from offset".  In the new proposal, I removed "from offset" in AnnualTimeZoneRule.  It allows you to transform zic source into the rule without looking into other past rules.

2) Although it is possible to use these APIs to implement a parser to create a TimeZone from zic source format, it is still not a trivial work.  With the zic syntax, standard offset transitions are separated from daylight saving transitions (Zone line vs. Rule line).  On the other hand, TimeZoneRule represent both standard offset and start times in a single object.  Thus, to implement zic parser, you need to go through both Zone lines and Rule lines to detect any changes including standard offset.  For example, the next zic source data -

# Rule        NAME        FROM        TO        TYPE        IN        ON        AT        SAVE        LETTER
Rule        FOO   1950  2000  -     Apr   1     1:00  1:00  D
Rule        FOO   1950  max   -     Oct   31    1:00  0:00  S
Rule        FOO   2001  max   -     Mar   1     1:00  1:00  D

# Rule        NAME        FROM        TO        TYPE        IN        ON        AT        SAVE        LETTER
Rule        BAR   1950  max   -     Apr   2     2:00  1:00  D
Rule        BAR   1950  max   -     Oct   30    2:00  0:00  S

# Zone        NAME                GMTOFF        RULES        FORMAT        [UNTIL]
Zone        Custom1     2:34:56     -     LMT         1960
                        2:30        BAR   B%sT        1990
                        2:00        FOO   F%sT

will be parsed into

- RuleBasedTimeZone constructed with initial name "LMT" with standard offset 1:23:45
- AnnualTimeZoneRule for daylight saving time (std 2:30/sav 1:00) starting on Apr 2 at 2am from 1961 to 1990 with name "BDT"
- AnnualTimeZoneRule for standard time (std 2:30/sav 0:00) starting on Oct 30 at 2am from 1961 to 1990 with name "BST"
- AnnualTimeZoneRule for daylight saving time (std 2:00/sav 1:00) on Apr 1 at 1am from 1991 to 2000 with name "FDT"
- AnnualTimeZoneRule for standard time (std 2:00/sav 0:00) on Oct 31 at 1am from 1991 to max with name "FST"
- AnnualTimeZoneRule for daylight saving time (std 2:00/sav 1:00) on Mar 1 at 1am from 2001 to max with name "FDT"

Does anyone want to have the zic parser implemented in ICU?

3) When you create VTimeZone instance from zone ID such as "America/New_York" and write out the rule into RFC2445 format, you will see historical transitions are represented by a list of date time, instead of the original rule such as 1st Sunday in April.  When ICU imports Olson tzdata into timezone.res, the tool already resolves historical transition times in UTC and they are no longer in mont/day rule format.  Only the latest rules might be represented in the format originally from tzdata.

4) RuleBasedTimeZone is a subclass of TimeZone, thus, it has getRawOffset(), setRawOffset(int), getDaylightSaving() and useDaylightTime().  These APIs do not make sense much in TimeZone implementation which supports historical transitions.  The implementation may try to return a result based on the currently active - except setRawOffset, which may do nothing.


-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
icu-design mailing list
icu-design@...
To Un/Subscribe: https://lists.sourceforge.net/lists/listinfo/icu-design



--
Mark
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
icu-design mailing list
icu-design@...
To Un/Subscribe: https://lists.sourceforge.net/lists/listinfo/icu-design

Re: Proposal for rule based time zone (ticket#5454)

by Steven R. Loomis :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Yoshito, please do:

svn propset svn:mime-type text/html filename.html
svn commit filename.html


to set the mime type, also  check your svn configuration file to make  
sure text/html and others are properly tagged on creation

-s


On May 14, 2007, at 8:38 PM, Mark Davis wrote:

> Looks good to me; however, I wasn't able to see
>
> http://source.icu-project.org/repos/icu/icuhtml/trunk/design/rbtz/ 
> ICU4J_JavaDoc/index.html
>
> the link opens up a view into raw HTML.
>
> Mark
>
> On 5/14/07, yoshito_umaoka@... < yoshito_umaoka@...>  
> wrote:
> This is a design proposal for "Rule based time zone" -> http://
> bugs.icu-project.org/trac/ticket/5454
> Please review this design proposal and provide your feedback.
>
> Thanks
> Yoshito
> -----------------------------------------------------
>
> Scope of the RFE
>
> 1) ICU uses timezone.res which is generated from Olson tzdata.  
> Although you can get UTC offset of local time, you cannot get when  
> the offset is changed.  For example, some ICU clients may want to  
> get next daylight saving time start/end date for some reasons.  For  
> now, what ICU clients can do is to probe UTC offset at a certain  
> date, then find the point of time when the offset is changed by  
> binary search.  The ICU internal time zone data actually contains  
> the time of transitions or rule used for getting the transitions.  
> But there are no APIs to access the transitions at this moment.
>
> 2) ICU clients may want to define their own time zones.  For now,  
> SimpleTimeZone is only the class which you can use to create a  
> custom time zone.  SimpleTimeZone does not support historical rule  
> changes.  If you really want to define a time zone with historical  
> rule changes, you will need to subclass TimeZone and write your own  
> TimeZone class.
>
> 3) iCalendar is a standard calendar protocol and has its own way to  
> represent time zones.  When you develop a calendar application, you  
> may need to extract offset transition rules for a time zone when  
> composing an iCalendar message.  Also, when parsing an iCalendar  
> message, you will need to parse the time zone definitions in  
> RFC2445 format and create a TimeZone object to be used in your  
> code.  Technically, if above 2 items are supported (extracting  
> transition rules/generating a time zone object by historical  
> rules), you can write your own RFC2445 VTIMEZONE formatter/parser.  
> But implementing the formatter/parser is not a trivial work, so ICU  
> clients may want to have the implementation in ICU itself.
>
>
> Overview of proposed APIs
>
> The proposed API documentation is found here -> http://source.icu- 
> project.org/repos/icu/icuhtml/trunk/design/rbtz/ICU4J_JavaDoc/
> index.html
> ICU4C APIs will be added soon.
>
> 1) TimeZoneRule/AnnualTimeZoneRule/TimeArrayTimeZoneRule
>
> TimeZoneRule is a class representing a rule for a time zone.  
> TimeZoneRule has next 3 fields - name, standard offset and daylight  
> saving.  For example, US Eastern Daylight Saving Time may be  
> represented by name = "EDT" / standard offset = -18000000  
> (milliseconds) / daylight saving = 3600000.   There are two  
> subclasses of TimeZoneRule - AnnualTimeZoneRule and  
> TimeArrayTimeZoneRule.
>
> AnnualTimeZoneRule  defines start times by an instance of  
> AnnualDateTimeRule.  AnnualDateTimeRule is a class representing a  
> rule date/time.  The rule date can be specified by 4 different ways  
> (day of month, Nth weekday in month, first weekday after day of  
> month, last weekday before day of month).  The time rule can be  
> specified 3 different type - WALL_TIME, STANDARD_TIME and  
> UNIVERSAL_TIME.  They are equivalent to rules which are currently  
> used in SimpleTimeZone internally.  AnnualTimeZoneRule also defines  
> applicable year range.
>
> For example, US Eastern Daylight Saving time since 1987 is  
> represented by next two AnnualTimeZoneRule instances.
>
> // First Sunday on or after April 1st, 2AM at local wall time
> AnnualDateTimeRule dtRule1 = new AnnualDateTimeRule(Calendar.APRIL,  
> 1, Calendar.SUNDAY, true,
>                                                     2*60*60*1000,  
> AnnualDateTimeRule.WALL_TIME);
> // First Sunday on or after March 8th, 2AM at local wall time
> AnnualDateTimeRule dtRule2 = new AnnualDateTimeRule(Calendar.MARCH,  
> 8, Calendar.SUNDAY, true,
>                                                     2*60*60*1000,  
> AnnualDateTimeRule.WALL_TIME);
>
> // Rule for 1987 - 2006
> AnnualTimeZoneRule tzRule1 = new AnnualTimeZoneRule("EDT", // name  
> of time zone
>                                                      
> -5*60*60*1000, // standard UTC offset -5 hours
>                                                      
> 1*60*60*1000, // daylight saving
>                                                     dtRule1, //  
> annual date time rule
>                                                     1987, // start  
> year
>                                                     2006); // end year
> // Rule for 2007 -
> AnnualTimeZoneRule tzRule1 = new AnnualTimeZoneRule("EDT", // name  
> of time zone
>                                                      
> -5*60*60*1000, // standard UTC offset -5 hours
>                                                      
> 1*60*60*1000, // daylight saving
>                                                     dtRule2, //  
> annual date time rule
>                                                     2007, // start  
> year
>                                                      
> AnnualTimeZoneRule.MAX_YEAR); // end year - forever
>
>
> TimeArrayTimeZoneRule defines start times by an array of  
> milliseconds since UTC epoch time (Jan 1, 1970 00:00:00).
>
>
> 2) TimeZoneTransition
>
> TimeZoneTransition is a class repesenting a single time  
> transition.  A TimeZoneTransition has 3 fields - time, time zone  
> rule before/after the time.  TimeZoneTransition objects are used as  
> return type in new APIs.
>
>
> 3) HasTimeZoneTransitions
>
> HasTimeZoneTransitions is an interface which defines two methods -
>
> public TimeZoneTransition getNextTransition(long base);
> public TimeZoneTransition getPreviousTransition(long base);
>
> TimeZone Implementation classes - SimpleTimeZone and OlsonTimeZone  
> - will implement the interface to allow ICU clients to get exact  
> time when time is changed.  For example, next Java code snipet will  
> return the next time transition in time zone "America/New_York".
>
> SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-
> dd'T'HH:mm:ssZ", ULocale.ROOT);
> sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
>
> TimeZoneTransition nextTT = TimeZone.getTimeZone("America/
> New_York").getNextTransition(System.currentTimeMillis());
>
> System.out.println("Next transition time: " + sdf.format(new Date
> (nextTT.getTime())));
> System.out.println("From: " + nextTT.getFrom().getStdOffset() + "/"  
> + nextTT.getFrom().getDstSaving());
> System.out.println("To:   " + nextTT.getTo().getStdOffset() + "/" +  
> nextTT.getTo().getDstSaving());
>
> Above code snipet will print out the results below (as of now) -
>
> Next transition time: 2007-11-04T06:00:00Z
> From: -18000000/3600000
> To:   -18000000/0
>
>
> 4) RuleBasedTimeZone
>
> RuleBasedTimeZone is a subclass of TimeZone for creating a custom  
> time zone by rules.  The constructor takes 4 arguments - time zone  
> ID, initial time name/standard offset/daylight saving.  When the  
> instance is created, it has fixed UTC offset.  Then you can add  
> your own rules defined by AnnualTimeZoneRule and/or  
> TimeArrayTimeZoneRule objects.  Below is a coding example of  
> RuleBasedTimeZone representing US Eastern time since 1967.
>
> int HOUR = 60*60*1000;
>
> RuleBasedTimeZone rbtz = new RuleBasedTimeZone("US_Eastern", "EST",  
> -5*HOUR, 0);
>
> AnnualDateTimeRule dtr;
> AnnualTimeZoneRule tzr;
>
> // Standard time
> dtr = new AnnualDateTimeRule(Calendar.OCTOBER, -1, Calendar.SUNDAY,  
> 2*HOUR, AnnualDateTimeRule.WALL_TIME);
> tzr = new AnnualTimeZoneRule("EST", -5*HOUR, 0, dtr, 1967, 2006);
> rbtz.addRule(tzr);
>
> dtr = new AnnualDateTimeRule(Calendar.NOVEMBER, 1, Calendar.SUNDAY,  
> true, 2*HOUR, AnnualDateTimeRule.WALL_TIME);
> tzr = new AnnualTimeZoneRule("EST", -5*HOUR, 0, dtr, 2007,  
> AnnualTimeZoneRule.MAX_YEAR);
> rbtz.addRule(tzr);
>
> // Daylight saving time
> dtr = new AnnualDateTimeRule(Calendar.APRIL, -1, Calendar.SUNDAY,  
> 2*HOUR, AnnualDateTimeRule.WALL_TIME);
> tzr = new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, dtr, 1967, 1973);
> rbtz.addRule(tzr);
>
> dtr = new AnnualDateTimeRule(Calendar.JANUARY, 6, 2*HOUR,  
> AnnualDateTimeRule.WALL_TIME);
> tzr = new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, dtr, 1974, 1974);
> rbtz.addRule(tzr);
>
> dtr = new AnnualDateTimeRule(Calendar.FEBRUARY, 23, 2*HOUR,  
> AnnualDateTimeRule.WALL_TIME);
> tzr = new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, dtr, 1975, 1975);
> rbtz.addRule(tzr);
>
> dtr = new AnnualDateTimeRule(Calendar.APRIL, -1, Calendar.SUNDAY,  
> 2*HOUR, AnnualDateTimeRule.WALL_TIME);
> tzr = new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, dtr, 1976, 1986);
> rbtz.addRule(tzr);
>
> dtr = new AnnualDateTimeRule(Calendar.APRIL, 1, Calendar.SUNDAY,  
> true, 2*HOUR, AnnualDateTimeRule.WALL_TIME);
> tzr = new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, dtr, 1987, 2006);
> rbtz.addRule(tzr);
>
> dtr = new AnnualDateTimeRule(Calendar.MARCH, 8, Calendar.SUNDAY,  
> true, 2*HOUR, AnnualDateTimeRule.WALL_TIME);
> tzr = new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, dtr, 2007,  
> AnnualTimeZoneRule.MAX_YEAR);
> rbtz.addRule(tzr);
>
>
> 5) VTimeZone
>
> VTimeZone is a subclass of TimeZone implementing RFC2445 iCalendar  
> VTIMEZONE.  There are two ways to create an instance of VTimeZone -  
> one from ICU/Olson time zone ID and another from VTIMEZONE data  
> stream.  VTimeZone has a private member which store store either  
> OlsonTimeZone or RuleBasedTimeZone.  When a VTimeZone object is  
> created from ID, OlsonTimeZone is created for the ID.  When it is  
> created from RFC2445 VTIMEZONE data stream, an instance of  
> RuleBasedTimeZone is created and initialized by parsing rules in  
> the RFC format.  VTimeZone provides two write methods in addition  
> to TimeZone public APIs.
>
> public boolean write(Writer writer)
> public boolean write(Writer writer, long start, long end)
>
> In general, all of historical transitions used by an ICU  
> OlsonTimeZone is not necessary in iCalendar applications.  When you  
> create an iCalendar message, you may only need time zone rules  
> including the event times.  The second write method allow you to  
> filter the rules and only pick rules applicable to the specified  
> time range.  By doing so, you can reduce the size of VTIMEZONE data  
> block in the iCalendar message.
>
>
> Development note - design consideration, question, limitation and etc.
>
> 1) In last year, I proposed APIs supporting RuleBasedTimeZone and  
> VTimeZone.  At that time, I designed APIs under strong ifluence of  
> RFC2445 VTIMEZONE.  However, I realized the initial implementation  
> was not ideal for supporting zic (Olson tzdata) source files.  
> Although implementing zic compiler was not an important goal, I  
> wanted to reconsider the design to be able to support zic source  
> files with less efforts.  The big difference between VTIMEZONE and  
> zic syntax is - a time zone in VTIMEZONE has an attribute  
> "TZOFFSETFROM".  Although the time of zone transition is specified  
> by local wall time, you can get the exact UTC time when the rule  
> starts without looking into other rules.  On the other hand, a  
> single zic rule may only tell you the starts in local wall time  
> without previous offset.  That means, to process rule/zone  
> definitions in zic source format, you have to walk through the  
> historical transitions from the begining.  Actually, VTIMEZONE  
> syntax is somewhat error prone, because "to offset" may not match  
> the next time's "from offset".  In the new proposal, I removed  
> "from offset" in AnnualTimeZoneRule.  It allows you to transform  
> zic source into the rule without looking into other past rules.
>
> 2) Although it is possible to use these APIs to implement a parser  
> to create a TimeZone from zic source format, it is still not a  
> trivial work.  With the zic syntax, standard offset transitions are  
> separated from daylight saving transitions (Zone line vs. Rule  
> line).  On the other hand, TimeZoneRule represent both standard  
> offset and start times in a single object.  Thus, to implement zic  
> parser, you need to go through both Zone lines and Rule lines to  
> detect any changes including standard offset.  For example, the  
> next zic source data -
>
> # Rule        NAME        FROM        TO        TYPE        
> IN        ON        AT        SAVE        LETTER
> Rule        FOO   1950  2000  -     Apr   1     1:00  1:00  D
> Rule        FOO   1950  max   -     Oct   31    1:00  0:00  S
> Rule        FOO   2001  max   -     Mar   1     1:00  1:00  D
>
> # Rule        NAME        FROM        TO        TYPE        
> IN        ON        AT        SAVE        LETTER
> Rule        BAR   1950  max   -     Apr   2     2:00  1:00  D
> Rule        BAR   1950  max   -     Oct   30    2:00  0:00  S
>
> # Zone        NAME                GMTOFF        RULES        
> FORMAT        [UNTIL]
> Zone        Custom1     2:34:56     -     LMT         1960
>                         2:30        BAR   B%sT        1990
>                         2:00        FOO   F%sT
>
> will be parsed into
>
> - RuleBasedTimeZone constructed with initial name "LMT" with  
> standard offset 1:23:45
> - AnnualTimeZoneRule for daylight saving time (std 2:30/sav 1:00)  
> starting on Apr 2 at 2am from 1961 to 1990 with name "BDT"
> - AnnualTimeZoneRule for standard time (std 2:30/sav 0:00) starting  
> on Oct 30 at 2am from 1961 to 1990 with name "BST"
> - AnnualTimeZoneRule for daylight saving time (std 2:00/sav 1:00)  
> on Apr 1 at 1am from 1991 to 2000 with name "FDT"
> - AnnualTimeZoneRule for standard time (std 2:00/sav 0:00) on Oct  
> 31 at 1am from 1991 to max with name "FST"
> - AnnualTimeZoneRule for daylight saving time (std 2:00/sav 1:00)  
> on Mar 1 at 1am from 2001 to max with name "FDT"
>
> Does anyone want to have the zic parser implemented in ICU?
>
> 3) When you create VTimeZone instance from zone ID such as "America/
> New_York" and write out the rule into RFC2445 format, you will see  
> historical transitions are represented by a list of date time,  
> instead of the original rule such as 1st Sunday in April.  When ICU  
> imports Olson tzdata into timezone.res, the tool already resolves  
> historical transition times in UTC and they are no longer in mont/
> day rule format.  Only the latest rules might be represented in the  
> format originally from tzdata.
>
> 4) RuleBasedTimeZone is a subclass of TimeZone, thus, it has  
> getRawOffset(), setRawOffset(int), getDaylightSaving() and  
> useDaylightTime().  These APIs do not make sense much in TimeZone  
> implementation which supports historical transitions.  The  
> implementation may try to return a result based on the currently  
> active - except setRawOffset, which may do nothing.
>
>
> ----------------------------------------------------------------------
> ---
> This SF.net email is sponsored by DB2 Express
> Download DB2 Express C - the FREE version of DB2 express and take
> control of your XML. No limits. Just data. Click to get it now.
> http://sourceforge.net/powerbar/db2/
> _______________________________________________
> icu-design mailing list
> icu-design@...
> To Un/Subscribe: https://lists.sourceforge.net/lists/listinfo/icu- 
> design
>
>
>
> --
> Mark
> ----------------------------------------------------------------------
> ---
> This SF.net email is sponsored by DB2 Express
> Download DB2 Express C - the FREE version of DB2 express and take
> control of your XML. No limits. Just data. Click to get it now.
> http://sourceforge.net/powerbar/db2/ 
> _______________________________________________
> icu-design mailing list
> icu-design@...
> To Un/Subscribe: https://lists.sourceforge.net/lists/listinfo/icu- 
> design


-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
icu-design mailing list
icu-design@...
To Un/Subscribe: https://lists.sourceforge.net/lists/listinfo/icu-design

Re: Proposal for rule based time zone (ticket#5454)

by yoshito_umaoka :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

> Yoshito, please do:
>
> svn propset svn:mime-type text/html filename.html
> svn commit filename.html
>
>
> to set the mime type, also  check your svn configuration file to make
> sure text/html and others are properly tagged on creation
>
> -s

Steven, thanks.  I set text/html to all of *.html files.
Mark, you should be able to browse the JavaDoc files now.

-Yoshito

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
icu-design mailing list
icu-design@...
To Un/Subscribe: https://lists.sourceforge.net/lists/listinfo/icu-design