ISO C 201X Proposal:
Timezone Functions


By David R. Tribble
david@tribble.com

Revision 1.4, 2009-10-08

 

 Contents

 

 Cover Sheet

 
                     Document Number:  WG14 N___/X3J11 __-___

                           C201X Revision Proposal
                           =======================

 Title:              Timezone Functions
 Author:             David R. Tribble
 Author Affiliation: Self
 Postal Address:     Plano, TX
                     USA
 E-mail Address:     david@tribble.com
 Web URL:            http://david.tribble.com
 Telephone Number:   ***************
 Sponsor:            ________________________________________
 Revision:           1.4, 2009-10-08
 Supersedes:         1.3, 2009-08-19
 Proposal Category:
    __ Editorial change/non-normative contribution
    __ Correction
    X_ New feature
    __ Addition to obsolescent feature list
    __ Addition to Future Directions
    __ Other (please specify)  _________________________________
 Area of Standard Affected:
    __ Environment
    __ Language
    __ Preprocessor
    X_ Library
       X_ Macro/typedef/tag name
       X_ Function
       X_ Header
       __ Other (please specify)  ______________________________  
 Prior Art:
    The Java standard runtime library provides a TimeZone utility
    class which works in concert with its Date and Calendar
    utility classes.
 Target Audience:    C/C++/POSIX programmers.
 Related Documents (if any): None
 Proposal Attached: X_ Yes __ No, but what's your interest?
 Abstract:
    The addition of new constants, types, and functions in a new
    <stdtime.h> header for calendar computations,
    intended to augment the existing capabilities of the 'tm'
    structure and its related functions.  Date conversions are
    also brought closer in line with the rules of ISO 8601.
 

 

 1. Introduction

This proposal presents enhancements to the standard C library affecting the time and date handling functions. The standard addressed is ISO/IEC 9899:1999 [1].

There are several key components to the proper handling of dates, times, and calendars:

Timezones

The world is divided into timezones in order to deal with the fact that the Earth is round, such that 12:00 noon in London is not simultaneously noon in New York. Every country has rules governing its use of timezones. Most regions use an integer number of hours offset from the UTC timezone as the basis of their timezone calculations, but a few regions use offsets with fractional hours.

Daylight Saving Time (DST)

Some countries employ a set of timekeeping rules whereby the clock is advanced ahead a specific amount of time (typically one hour) during the Spring (usually in April) and back again in the Fall (usually October) as a way of increasing the number of working daylight hours during the summer months. These rules thus make it possible for times within a certain interval (typically between 02:00:00 and 03:00:00) to occur not at all on one particular night of the year (when DST takes effect) and to occur twice on another particular night of the year (when DST reverts back to normal).


1.1 Existing Deficiencies

There are several deficiencies and limitations with the existing (C99) standard library time and date functions, either because of missing functionality or because some operations are difficult (or impossible) to achieve.

Timezone limitations

  1. The standard library can only handle two timezones at the same time: UTC and the local timezone, as provided by the gmtime() and localtime() functions. The local timezone is generally established as a global variable.
  2. Arbitrary timezone settings cannot be applied easily to a broken-down calendar date value (tm structure). This makes it difficult to convert a broken-down time for one given timezone into a time for another arbitrary timezone.
  3. It is possible to determine the offset of the local timezone from UTC, but this requires explicit calculations by user code (i.e., finding the difference between the results of the localtime() and gmtime() functions).
  4. It is not possible to retrieve a timezone by name or offset from UTC (e.g., "PST" or "+0800").
  5. Once a broken-down calendar date value has been established, either relative to UTC or to the local timezone, its association with that timezone setting is lost. A broken-down calendar date (tm structure) contains no indication of what timezone was used to derive its member values.
  6. There is no way to convert a broken-down calendar date into a system time_t value relative to any timezone other than the local timezone (using the mktime() function).

Daylight Saving Time (DST) limitations

  1. Historically, the application of Daylight Saving Time (DST) to civil time has varied considerably. Rules vary according to the period of history (notably World War II) and according to region. Some countries employed rules that resulted in up to six different possible DST adjustments for certain periods in time.
  2. ISO C provides no specific method for handling DST rules. Most implementations encode these rules in a global data structure, or within the standard date functions themselves.
  3. ISO C cannot handle DST adjustments with a resolution finer than one second. This is a limitation of the tm structure, since it cannot represent times with a resolution finer than one second.


1.2 Solutions

The types and functions described in this proposal solve many of the problems mentioned in the previous section.

The following diagram illustrates the various types and their relationships within this proposal and its related proposals.

Conversion functions
  C99 Library   Proposed
(a) localtime() (c) setcalendartime()
  gmtime()   mklongtime()
  mktime()    
    (d) calendarformat()
(b) strftime()   calendarscanf()
  strptime()   POSIX, not ISO C    
    (e) inittimezone()
      mktimezonename()
       
    (f) longtimetotime()
      timetolongtime()

 

 2. Definitions

The following terms are used in this proposal. Some of the terms may need to be added to the ISO C standard.

broken-down time
Same as calendar date.

calendar date
A data structure whose members comprise the components of a date and time value, i.e., a year, month, day of the month, hour, minute, second, etc. Such a set of values represents a date within a calendric system, which is usually taken to be the international Gregorian calendar. Also known as broken-down time.

Daylight Saving Time (DST)
An adustment made to civil time ostensibly to provide more hours of sunlight during non-working hours during a portion of the year. This generally involves setting clocks forward one hour from the "real" time while DST is in effect.

timezone
A region of the Earth's surface having a given time difference from UTC (a.k.a. Zulu or GMT) time. This is necessary to reflect the fact that 12:00 noon in Bangladesh is not the same moment in time as 12:00 noon in New York or London, due to the fact that the Earth is round. Timezones are usually defined as being an integral number of hours offset from UTC time, but there are exceptions to this rule.

 

 3. Constants

The following constant is defined in the <stdtime.h> standard header.

    _TZ_ERROR

It is described in detail below.


3.1 Constant _TZ_ERROR

Synopsis

    #include <stdtime.h>

    #define _TZ_ERROR  integer-expression

Description

This is a constant of type long int, representing an invalid timezone offset.

The value of this constant must not compare equal to the offset of any supported combination of timezone setting and Daylight Saving Time adjustment.

[Notes]
This constant is used as a special error return value of the timezoneoffset() function. It is also used as a special value for the tz_offset member to indicate an invalid timezone setting.

See also

timezone.tz_offset, timezoneoffset().

 

 4. Types

The following types are defined in the <stdtime.h> standard header file:

    struct calendar
    struct timezone

Each type is described in detail below.


4.1 Structure calendar

Synopsis

    #include <stdtime.h>

    struct calendar;

Description

This structure contains a broken-down calendar date.

The contents of this structure are discussed in a separate proposal (see Proposal [P1] for more details.)


4.2 Structure timezone

Synopsis

    #include <stdtime.h>

    struct timezone;

Description

This structure contains information about a timezone and its DST variants.

[Notes]
Timezone objects are allocated and deallocated by the programmer. Therefore there are no additional requirements for the standard library to call malloc() or free().

It is intended that multiple calendar date objects can share (i.e., point to) the same timezone object.

It is recommended that implementations define the timezone structure such that its members are not pointers to allocated data objects that would need to be explicitly deallocated by the programmer. On the other hand, the structure members could be pointers to statically allocated objects which do not require any deallocation.

Intimately related to timezones is the application of Daylight Saving Time rules. Timezones thus come in (at least) two flavors, those with DST in effect and those without. This setting is presumably reflected in their names (e.g., "CST" versus "CDT").

For POSIX implementations, the intent is to have the proposed timezone object contain the settings of the global timezone and daylight variables. This would allow a program to manage multiple timezones in addition to the local zone.

Implementations that support complicated timezone naming schemes (such as POSIX) will probably provide extra members in this structure to deal with DST time change rules, etc.

This structure contains the following members, which may occur in any order within the structure:

    long int    tz_offset;          // Milliseconds east of UTC
    struct      tz_z[N];            // DST-adjusted zones

The tz_z array is composed of one or more DST structures. This structure type contains the following members, which may occur in any order:

    int         z_dst;              // Seconds of DST adjustment
    char        z_name[N+1];        // DST-adjusted zone name

Each member is described in more detail below.

long int tz_offset

Specifies the number of milliseconds offset from UTC (Z) for the timezone with no DST adjustments applied, i.e., the amount of time that must be added to UTC times to convert them into their corresponding local times. Positive offsets are for zones east (ahead) of UTC, and negative offsets are for zones west of (behind) UTC.

If this member if equal to _TZ_ERROR, the timezone object represents an invalid timezone.

[Note]
For example, U.S. Central Standard Time is 6 hours west of UTC, so its timezone offset is -21,600,000 (-6×60×60×1000) msec. Thus adding -06:00 to a UTC time of 18:00 yields a local CST time of 12:00.

Millisecond resolution is used because of rather unusual offsets that exist for some historical timezones.

struct tz_z[N]

An array of at least two elements, each of which is a structure containing information about the timezone with a particular Daylight Saving Time (DST) adjustment applied. The first element of the array (tz_z[0]) contains timezone settings with no DST adjustments applied.

int tz_z[i].z_dst

Specifies the number of seconds to adjust for Daylight Saving Time (DST). (Index i specifies a specific DST variant of the timezone.) A value of zero indicates that no DST adjustment is made, while a value greater than zero indicates the DST adjustment that is applied.

[Note]
This member provides functionality similar to the tm_dst member of the struct tm type. The semantics are more specific, though.

char tz_z[i].z_name[N+1]

A null-terminated string containing the name of the timezone and DST setting. (Index i specifies a specific DST variant of the timezone.) The length (N), format, and content of the string are implementation-defined.

[Note]
Presumably, some widely accepted naming convention might be used for timezone names. For example, something similar to the POSIX timezone naming conventions could be used, e.g., "CST" for "US Central Standard Time", and so forth.

This structure may contain other implementation-defined members.

[Note]
Other members may be needed to encode the name of the timezone, and the DST rules, i.e., what days of the year DST starts and ends, etc.

On POSIX systems, for instance, the timezone structure could contain all of the information obtained by a call to tzset().

To use a timezone object, it must be known which DST adjustment to apply to the timezone, which is determined based on a specific time value. In other words, a specific time is used to determine the appropriate DST rule to apply based on the time of year it occurs in, the locale settings currently in effect, etc.

Example

Consider a timezone specification "CST6CDT" designating the "U.S. Central Standard Time" / "U.S. Central Daylight Time" timezone combination, having a base offset of 6 hours west of UTC. Its corresponding timezone object contains the following member values:

    struct timezone     tz_cst_cdt =
    {
        .tz_offset =    -6 * 60*60*1000L, // -6 hours east of UTC

        .tz_z =
        {
            // .tz_z[0]
            {
                .z_name =   "CST",
                .z_dst =    0,            // No adjustment
            },

            // .tz_z[1]
            {
                .z_name =   "CDT",
                .z_dst =    1 * 60*60,    // 1 hour adjustment
            },
        },
    };

See also

_TZ_ERROR, inittimezone().

 

 5. Functions

The following sections describe the proposed functions to be added to the <stdtime.h> standard library header.

The following functions are defined in the <stdtime.h> standard header file:

    inittimezone()
    mktimezonename()
    timezonedst()
    timezoneoffset()

Each function is described in detail below.


5.1 Function inittimezone()

Synopsis

    #include <stdtime.h>

    int  inittimezone(struct timezone *zone, const char *name);

Description

Initializes a timezone object, filling it with information corresponding to a timezone designated by a given name.

[Notes]
Timezone objects can be established by name (e.g., "UTC", "Z", "CST", "CST6CDT", "US Central Standard Time", etc.). Such names are implementation-specific, although it is hoped that some common naming convention (such as the one defined in POSIX) can be achieved.

The allocation and deallocation of timezone objects is completely controlled by the programmer. There are thus no requirements for the standard library to call malloc() or free().

mktimezonename() is the functional complement of this function.

Argument name points to a null-terminated string containing the name of a timezone. The string may contain a name constructed by a prior call to mktimezonename(). If the string is empty (""), the local timezone is assumed. This argument may be null, in which case it is equivalent to an empty string (""). If the string compares equal to "Z", the UTC timezone with no DST adjustments is assumed.

Conforming implementations are required to support, at a minimum, timezone objects corresponding to the local and the UTC timezones.

Conforming implementations are also required to support, at a minimum, timezones corresponding to names specified by the following syntax:

    timezone-name:
        [+|] [h]h [mm]

Positive values (optionally prefixed with a '+') specify zone times east (ahead) of UTC, and negative values (prefixed with a '−') specify zones west of (behind) UTC (as per the syntax defined in RFC 2822).

Implementations must recognize timezone names "−1400" through "+1400" (and their variant spellings), representing 29 distinct timezone offsets. (The designation "+0000" is preferred over "−0000", but both represent a zero offset from UTC.)

[Notes]
This syntax is based on RFC 2822.

Note that positive offsets of this format designate zones east of UTC, which corresponds to the tz_offset member of a given timezone object.

These minimum requirements provides a reasonably useful set of timezone names that are portable across implementations.

Implementations are free to recognize other timezone names in addition to these required names. Other than the required timezone names described above, the means by which timezone names correspond to timezone objects is implementation-defined.

Returns

The function returns zero if successful.

If no timezones with names corresponding to the string pointed to by name are supported by the implementation, or if some other error occurs, the tz_offset member of the timezone object is set to a value equal to _TZ_ERROR, and the function returns −1. The values of the other members of the timezone object are indeterminate.

[Notes]
Timezone names are implementation-specific, although it is hoped that some common naming convention can be achieved. A recommended scheme is the one used by POSIX implementations (e.g., with names like "CST6CDT" to represent "Central Standard Time" with a 6 hour offset west of UTC and "Central Daylight Time" with an additional DST adjustment of one hour).

It is intended that the following function call will work as expected on POSIX compliant systems:

    inittimezone(&zone, getenv("TZ"));

Timezone naming schemes can be quite complicated. For example, POSIX uses the "TZ" environment variable to specify the local timezone for each user, and employs a fairly complicated syntax, allowing names such as "CST+6CDT,M4.1.0/2,M10.5.0/2", which specifies a DST/non-DST pair of timezone names and UTC offsets as well as the times of the year when the DST changes occur. It is presumed that the inittimezone() function on POSIX systems will be quite capable of handling such strings, just as the POSIX tzset() function currently does.

Requiring a small set of well-defined timezone names allows portable conforming programs to be written that adjust for the 24 major timezones of the world.

Intimately related to timezones is the application of Daylight Saving Time rules. Timezones thus come in two flavors, those with DST adjustments and those without, which presumably is reflected in their names (e.g., "CST" and "CDT").

Examples

The following code fragment initializes a timezone object for a timezone with a positive six hour offset from UTC.

    struct timezone     zone;

    // Initialize a timezone that is 6 hours west of UTC
    inittimezone(&zone, "-0600");

The following function initializes a timezone object for a timezone with an arbitrary offset from UTC.

    #include <stdio.h>
    #include <stdtime.h>
    #include <string.h>

    int init_tz(struct timezone *zone, int hrs_east)
    {
        char    buf[20];

        // Initialize the timezone with a given UTC offset
        sprintf(buf, "%+04d", hrs_east*100);        // "±hh00"
        return (inittimezone(zone, buf));
    }

See also

_TZ_ERROR, struct timezone, mktimezonename().

5.2 Function mktimezonename()

Synopsis

    #include <stdtime.h>

    int  mktimezonename(char *buf, size_t max, const struct timezone *zone);

Description

Constructs the name of a given timezone object.

[Notes]
This is the functional complement of inittimezone().

Argument buf points to a character array to be filled with the resulting timezone name. The resulting string will contain the name corresponding to the timezone object, being composed of printable characters and a terminating null character. The format, length, and contents of the string are implementation-defined. This argument may be null only if argument max is zero.

Argument max specifies the maximum number of characters, including a terminating null character, that can be written into the character array. If the resulting name requires more that max characters, the function fails.

Argument zone points to a timezone object, which is assumed to have been previously initialized with a call to inittimezone(). If the tz_offset member of this object has a value equal to _TZ_ERROR, the function fails.

Returns

If successful, the function returns a value greater than zero indicating the number of characters, excluding the terminating null character, that were written into array buf. The resulting name is suitable for use as the name argument of a subsequent call to inittimezone().

[Notes]
The resulting name presumably encodes enough information about the timezone and its DST variants so that if it is passed to a subsequent call to inittimezone(), the resulting timezone object will be identical, for all intents and purposes, to the original timezone object passed to mktimezonename().

If the tz_offset member of the specified timezone object has a value equal to _TZ_ERROR, the function returns zero.

If the function fails or encounters an error, a negative value is returned and the contents of array buf are indeterminate. The absolute value of the returned value specifies a recommended minimum number of characters, including a terminating null character, needed to successfully construct a name for the specified timezone.

[Notes]
A negative return value allows the calling function to determine the minimum size to allocate for the name buffer for use in a second call to mktimezonename(). (See the example below.)

Example

The following function allocates a string of the appropriate length and fills it with the name of a given timezone.

    #include <stdlib.h>
    #include <stdtime.h>

    char * get_tz_name(const struct timezone *zone)
    {
        char *  name;
        int     len;

        // Determine a recommended name length
        len = -mktimezonename(NULL, 0, zone);
        name = malloc(len);

        // Construct the name of the timezone
        mktimezonename(name, len, zone);
        return (name);
    }

See also

_TZ_ERROR, struct timezone, inittimezone().

5.3 Function timezonedst()

Synopsis

    #include <stdtime.h>

    int  timezonedst(const struct calendar *date, const struct timezone *zone);

Description

Determines the Daylight Saving Time adjustment to apply to a specified calendar date within a given timezone.

Argument date points to a broken-down calendar date object. If the calendar date object does not represent a meaningful date, the function fails.

Argument zone points to a timezone object, which is assumed to have been previously initialized with a call to inittimezone(). This argument may be null, in which case no DST adjustment is specified, and the function returns zero.

Returns

If successful, the function returns the index of the tz_z[] element within the given timezone object which specifies the appropriate adjustment to apply to the given calendar date object.

If an error occurs, the function returns −1.

See also

timezone.tz_z, inittimezone(), timezoneoffset().

5.4 Function timezoneoffset()

Synopsis

    #include <stdtime.h>

    long int  timezoneoffset(const struct calendar *date,
        const struct timezone *zone);

Description

Determines the combined timezone and Daylight Saving Time offset to apply to a specified calendar date within a given timezone.

Argument date points to a broken-down calendar date object. If the calendar date object does not represent a meaningful date, the function fails.

Argument zone points to a timezone object, which is assumed to have been previously initialized with a call to inittimezone(). This argument may be null, in which case no timezone or DST adjustment is specified, and the function returns zero.

Returns

If successful, the function returns the number of milliseconds that must be added to the given calendar date in order to have it reflect the correct time for the specified timezone.

If an error occurs, the function returns a value equal to _TZ_ERROR.

See also

_TZ_ERROR, inittimezone(), timezonedst().

 

 6. Prior Art

  1. POSIX provides the tzset() function for parsing the value of the "TZ" environment variable. This variable specifies the local timezone for each program, and employs a fairly complicated syntax:
        tz-spec:
            std offset [dst [offset]] [, rule]
    
        offset:
            [+|−] time
    
        rule:
            date [/ time] , date [/ time]]
    
        date:
            [n][n]n
            J [n][n]n
            M m . w . d
    
        time:
            [h]h [: mm [: ss]
    
    This allows names such as "CST+6CDT+5,M4.1.0/2,M10.5.0/2", which specifies a DST/non-DST pair of timezone names and UTC offsets as well as the times of the year when the DST changes occur.

    POSIX also provides the global variable timezone, which specifies the difference in seconds between UTC and local timezone. It also provides the global variable daylight, which specifies that a DST adjustment should be applied to the local timezone in use. Presumably, the DST rules encoded in the "TZ" variable are also stored in global variables.

  2. The Java standard runtime library provides a Date class that is capable of storing system times to the nearest microsecond. Java also provides TimeZone and Calendar utility classes that are integrated with the Date class, and which provide the ability to convert between system time values and calendar date values.

    A given Calendar object is assigned a specific TimeZone setting, which affects all subsequent date conversions on that calendar object.

    The Java library supports a small table of standard timezone names.

 

 Appendix A – Further Discussion
[gettimezonelist()]
Previous revisions of this proposal included a gettimezonelist() function which returned a list of timezone objects representing the timezones supported by the implementation. This function was removed because it was felt that it might be impossible for some implementations to provide a complete list of supported timezones, due to the fact that timezone naming schemes can be quite complicated and produce a large universe of possible names.

 

 References

[1]  ISO/IEC 9899:1999(E)
Programming Language C
Second edition, Dec 1999, ISO/IEC.
Available at www.ansi.org

[2]  ISO/IEC 14882:1998(E)
Programming Language C++
First edition, Sep 1998, ISO/IEC.
Available at www.ansi.org

[3]  Single Unix Specification
The Open Group.
www.unix-systems.org/single_unix_specification

[4]  Java API Reference
Class java.util.TimeZone
Class java.util.Calendar
Java 2 Standard Edition (SE),
Sun Microsystems, Inc., 2001.
java.sun.com/j2se/1.5/docs/api/java/util/TimeZone.html
java.sun.com/j2se/1.5/docs/api/java/util/Calendar.html

[5]  RFC 2822 - Internet Message Format
Apr 2001.
www.ietf.org/rfc/rfc2822.txt

[6]  ISO 8601:2000(E)
Data elements and interchange formats − Information interchange
Representation of dates and times
Second edition, Dec 2000, ISO/IEC, TC 154.
Available at www.iso.org
A draft version in PDF format is at xml.coverpages.org/ISO-FDIS-8601.pdf
(see also xml.coverpages.org/related.html#iso8601)

[7]  Systems of Time
U.S. Naval Observatory − Time Service Department, Jun 1998.
tycho.usno.navy.mil/systime.html

[8]  A Summary of the International Standard Date and Time Notation
Markus Kuhn, May 1996.
www.cl.cam.ac.uk/~mgk25/iso-time.html

[9]  Specifying the Time Zone with TZ
POSIX-compatible GNU C runtime library
GNU − Free Software Foundation, May 2001.
www.gnu.org/manual/glibc-2.2.3/html_node/libc_431.html

[10]  Global Data and the TZ Environment Variable
QNX 6.1 C/C++ Runtime Library Documentation.
qdn.qnx.com/support/docs/neutrino/lib_ref/global.html#TheTZEnvironmentVariable

[11]  Daylight Saving Time
The history of daylight saving, from Benjamin Franklin to the present.
webexhibits.org/daylightsaving

[12]  ISO 8601 references
DMOZ, The Open Directory Project.
dmoz.org/Science/Reference/Standards/Individual_Standards/ISO_8601

[13]  Wikipedia: Daylight Saving Time
en.wikipedia.org/wiki/Daylight_saving_time

[14]  Wikipedia: ISO 8601
en.wikipedia.org/wiki/ISO_8601

 

 Related Proposals

[P1]  ISO C 201X Proposal: Calendar Functions
Jun 2002, David R. Tribble.
david.tribble.com/text/c0xcalendar.html
A related proposal specifying types and functions for manipulating calendar date objects.

[P2]  ISO C 201X Proposal: Long Time Type
Jun 2004, David R. Tribble.
david.tribble.com/text/c0xlongtime.html
A related proposal specifying a long time type and supporting functions for manipulating system time values.

[P3]  Proposed new <time.h> for ISO C 200X
Markus Kuhn, Sep 1998.
www.cl.cam.ac.uk/~mgk25/time/c

[P4]  Modernized <time.h> API for ISO C
Paul Eggert, Jan 2000.
www.twinsun.com/tz/timeapi.html

[P5]  A proposal for thread-safe time zone information
Jonathan Lennox, Columbia University, Jun 2001 (Version 2).
www.cl.cam.ac.uk/~mgk25/c-time/proposal-lennox.txt

 

 Source Code

The following source files provide a proof-of-concept implementation of this proposal.

    c0xtimezone.c
    c0xtimezone.h

 

 Acknowledgments

My thanks to the people who gave helpful comments on early drafts of this document, and who posted suggestions and corrections on the comp.std.c newsgroup.

 

 Revision History

1.4, 2009-10-08
Changed the tz_offset member to be the offset east of UTC instead of west, to conform with ISO 8601 and RFC 2822 notations.

1.3, 2009-08-19
Updated the title from an ISO 200X to an ISO 201X proposal.
Added the "big picture" diagram in the "Solutions" section.
Added more intra-document links.
Improved section headings and paging.
Made minor corrections.
Added references to Wikipedia articles.

1.2, 2004-09-02
Replaced the use of "GMT" with "UTC".
Clarified the semantics of RFC 2822 timezone designations.

1.1, 2004-07-30
Renamed function gettimezone() to inittimezone().
Added function mktimezonename().
Removed the tz_name and tz_abbr members from the timezone structure.

1.0, 2004-06-30
First revision.


This document is in the public domain. Permission is granted to freely redistribute, copy, or reference this document.

This document: http://david.tribble.com/text/c0xtimezone.html.

Author's email: david@tribble.com.
Author's home page: http://david.tribble.com.