#charset "us-ascii"
#pragma once

 *   Copyright (c) 2001, 2006 Michael J. Roberts
 *   This file is part of TADS 3.
 *   This header defines the Date and TimeZone intrinsic classes.  

/* include our base class definition */
#include "systype.h"

/* ------------------------------------------------------------------------ */
 *   The Date intrinsic class stores a date-and-time value representing a
 *   particular point in time, and provides methods and operators for date
 *   arithmetic, formatting, and parsing.
 *   The date/time value is stored internally in terms of universal time
 *   (UTC).  This makes it independent of locations and time zones.  When a
 *   new Date object is created for a given calendar day or clock time, that
 *   source value is assumed to be in terms of the local wall clock time of
 *   the machine it's running on, but a different time zone can be explicitly
 *   specified instead; the Date object automatically translates that local
 *   time value to UTC for storage.  Likewise, when a Date is formatted to a
 *   string representation, or when calendar or clock components are
 *   extracted from it, the formatted or extracted value is translated by
 *   default to the local time zone, but a different time zone can be
 *   specified.
 *   You can create a Date object from a number of other representations for
 *   date values:
 *.   new Date() - creates a Date representing the current date and time.
 *.   new Date('string', refTZ?, refDate?) - parses the string as a date
 *.          value.  'refTZ' is an optional TimeZone object; if provided,
 *.          the date string will be interpreted as a local time in that
 *.          zone, unless the string contains a timezone specifier.  The
 *.          default timezone if 'refTZ' is missing is the local system's
 *.          time zone.  'refDate' is an optional Date object that's used
 *.          to fill in certain missing date elements in the string.  If
 *.          the string doesn't specify the year (e.g., 'March 1'), the
 *.          year is taken from refDate; if the string only specifies only
 *.          a time, the date is taken from refDate.  If the date uses a
 *.          two-digit year number ('5/15/92'), the century is inferred
 *.          from the reference date by finding the year closest to the
 *.          reference year (for example, if it's currently 2012, '92' is
 *.          interpreted as 1992, since that's closer to 2012 than is
 *.          2092).  The date parser accepts numerous common human-readable
 *.          formats and several standard computer formats.  For a full
 *.          list of, see the System Manual.  The parser uses the locale
 *.          settings from setLocaleInfo() to match month names, weekday
 *.          names, etc; the default settings are for US English format.
 *.   new Date(number, 'J') - 'number' can be an integer or a BigNumber.
 *.          This creates a Date object representing the given number of
 *.          days after January 1, 4713 BCE on the Julian calendar, at
 *.          noon UTC.  The fractional part is the fraction of a day
 *.          past noon; for example, a fractional portion of 0.25
 *.          represents 1/4 of a day, or 6 hours, so it represents a
 *.          clock time of 18:00 UTC (6 hours past noon).
 *.   new Date(number, 'U') - 'number' can be an integer or a BigNumber.
 *.          This creates a Date object representing the given number of
 *.          seconds after standard Unix Epoch (1/1/1970 00:00:00 UTC),
 *.          or before the Epoch if the value is negative.  If 'number'
 *.          is a BigNumber, it can specify fractions of a second, which
 *.          the Date object will round to the nearest milliseconds.
 *.          This constructor format is provided because "seconds since
 *.          1/1/1970" is the standard representation of time on Unix-like
 *.          systems, and as a result it's also common in file formats.
 *.   new Date(year, month, day, tz?) - midnight on year/month/day (all
 *.          given as integers), in the given local time zone 'tz' (given
 *.          as a TimeZone object or a string giving a time zone name).
 *.          The default time zone if 'tz' is omitted is the system's
 *.          local time zone.  The year must be given as the full year
 *.          with century, e.g., 2012, not just 12; the latter is valid
 *.          but is taken literally as the first-century year 12.  The
 *.          month is 1-12 for January to December.  The day is simply
 *.          the calendar day of the month (e.g., 5 for January 5).  The
 *.          year can zero or negative.  Note that because year 0 is a
 *.          valid year in Date's calendar system, negative years are off
 *.          by one from the "BC" convention: in the AD/BC convention,
 *.          the year before AD 1 is 1 BC, not AD 0; so on our calendar,
 *.          year 0 corresponds to 1 BC, -1 is 2 BC, etc.
 *.   new Date(year, month, day, hour, minute, seconds, ms, tz?) - the
 *.          given date and time value, with each element as an integer.
 *.          The value is in terms of the given local time zone 'tz',
 *.          or the system's local time zone if 'tz' is omitted.  'ms'
 *.          is the number of milliseconds (0-999).
 *   Date arithmetic: the following operators perform calendar calculations
 *   on the date value:
 *.   Date + integer   - add days to the date
 *.   Date - integer   - subtract days from date
 *.   Date + BigNumber - add days (which can include fractional days)
 *.   Date - BigNumber - subtract days (which can include fractional days)
 *.   Date - Date      - number of days between dates (with fractional days)
 *   Adding an integer or BigNumber returns a new Date object representing
 *   the result; Date objects are immutable, so the original Date value isn't
 *   changed by the operation.
 *   Subtracting one Date from another yields a BigNumber with the difference
 *   in days between the two dates.  Note that this might have a fractional
 *   part, because the difference might not be whole days; for example,
 *   subtracting 13:00 from 19:00 on the same day yields 0.25, which is 1/4
 *   of a 24-hour day, or 6 hours..  Like all Date arithmetic, subtraction
 *   works in universal time, so the subtraction yields the true time
 *   difference between the events even if they were created from times in
 *   different time zones.  For example, subtracting 1 PM Eastern Time from 1
 *   PM Pacific Time on the same day yields 0.125 (1/8 of a day, or 3 hours).
 *   The comparison operators (< > <= >=) compare two Date values by order of
 *   occurrence in time.  For example, a > b is true if a is later than b.
 *   The comparison is done in universal time, so the comparison yields the
 *   actual event order, not the nominal local time order.  For example, 2 PM
 *   Eastern Time is earlier than 1 PM Pacific Time on any given day.
 *   Time zone specifications: when a time zone is specified in a constructor
 *   or method argument, you can supply a TimeZone object, or a string with
 *   the name of a time zone, using the same formats that the TimeZone
 *   constructor accepts.  See the TimeZone object for more information.  The
 *   default if you don't specify a time zone is 
intrinsic class Date 'date/030000': Object
     *   Parse a date.  This is similar to the new Date('date string')
     *   constructor, but lets you specify your own custom format templates,
     *   and returns a detailed breakdown of the source string elements that
     *   were matched in the various fields.  'str' is the source string to
     *   be parsed.  'format' is an optional format string, or a list of
     *   format strings used to parse the date, or be nil if you simply want
     *   to use the built-in formats.  See the System Manual for the syntax
     *   of these strings.  If you want to specify one or more custom formats
     *   and also use the built-in formats, use a list for 'format', and
     *   include a nil element to include the standard formats.  'refDate' is
     *   the reference date, which is used to fill in certain missing fields;
     *   this works the same way as in the new Date('str', refDate)
     *   constructor, and defaults to the current time if omitted or nil.
     *   'refTZ' is the reference time zone, and defaults to the host
     *   system's local time zone if omitted or nil.
     *   The return value on success is a list: [date, tzobj, format, era,
     *   year, month, day, yearDay, weekDay, ampm, hour, minute, second, ms,
     *   unix, tz].  'date' is the parsed Date object.  'tzobj' is a TimeZone
     *   object if a timezone is specified in the date string, otherwise nil
     *   (in which case the date is implicitly in terms of 'refTZ', or the
     *   host system's local timezone if 'refTZ' is omitted).  'format' is
     *   the actual format string(s) that was/were matched, which can come
     *   from the custom format strings you supplied and/or the built-in
     *   formats; if multiple formats were matched, they'll be concatenated
     *   together to form this string.  The remaining fields are strings
     *   giving the literal source text matched for the individual date
     *   components, or nil for components not matched.
     *   If the date string can't be parsed, the return value is nil.
    static parseDate(str, format?, refDate?, refTZ?);

     *   Parse a Julian date.  This works like parseDate(), except that the
     *   date is interpreted on the Julian calendar.  Julian dates have the
     *   same form as Gregorian dates, but a given day will have different
     *   nominal dates on the two calendars, except for most of the third
     *   century, where they happen to align.  The further in time a day is
     *   from the overlap in the third century, the more the dates will
     *   diverge on the two calendars; in the 21st century, the difference is
     *   about 13 days.
    static parseJulianDate(str, format?, refDate?, refTZ?);

     *   Format the date/time value as a Gregorian calendar date, using the
     *   given format template string.  Returns a string with the formatted
     *   date/time.  The date/time is displayed in the given time zone (or
     *   the system's local time zone if 'tz' isn't specified).
    formatDate(format, tz?);

     *   Format the date/time value as a Julian calendar date, using the
     *   given format template string. 
    formatJulianDate(format, tz?);

     *   Compare to another Date object; returns an integer less than zero if
     *   this Date is before the other Date, zero if they refer to the same
     *   date, greater than zero if this Date is after the other Date.  The
     *   same comparisons can be done with the ordinary comparison operators
     *   (<, >, <=, >=, ==, !=), but this is convenient for sorting callbacks
     *   since it lets you get the greater/equal/less result in one shot.

     *   Get the Gregorian calendar date represented by this Date object, in
     *   terms of local time in the given time zone (or the system's local
     *   time zone if 'tz' isn't specified).  Returns a list consisting of
     *   [year, month, day, weekday], each value represented as an integer.
     *   The weekday is 1 for Sunday, 2 for Monday, etc.  For example, June
     *   21, 2012 (a Thursday) is represented as [2012,6,21,5].

     *   Get the Julian day number.  This is the number of days since January
     *   1, 4713 BCE on the (proleptic) Julian calendar, at noon UTC.  This
     *   is an important figure in astronomy.  It's also often useful as a
     *   common currency for converting between arbitrary calendars: you
     *   might not be able to find a published formula for converting between
     *   calendar X and calendar Y, but you can almost always find a formula
     *   for converting between any given calendar and the Julian day system.
     *   The return value is a BigNumber value giving the Julian day
     *   corresponding to this Date value, including a fractional part for
     *   the time past noon UTC on that date.
     *   Note that there's no local time zone involved in this calculation,
     *   since the Julian day number is specifically defined in terms of
     *   universal time.

     *   Get the Julian calendar date for this Date object, in terms of the
     *   local time in the given time zone (or the system's local time zone
     *   if 'tz' isn't specified).  Returns a list consisting of [year,
     *   month, day, weekday].  (The weekday on the Julian calendar is always
     *   the same as the weekday on the Gregorian calendar for a given Date
     *   value.)

     *   Get the ISO 8601 week date.  This returns a list with three
     *   elements, [year, week, day], where 'year' is the ISO year number
     *   containing the date, 'week' is the week number (1 to 53), and 'day'
     *   is the day of the week (1-7, Monday to Sunday, per the ISO 8601
     *   conventions).  The year on the ISO week calendar can differ from the
     *   year on the Gregorian calendar for dates during the first and last
     *   week of a year on Gregorian calendar, because year boundaries on the
     *   ISO calendar always occur on week boundaries.  For example, Jan 1,
     *   2005 has the ISO week date 2004-W53-6 - it's part of 2004 on the ISO
     *   week calendar because weeks can't be split across years, so the
     *   entire week belongs to 2004 on the ISO calendar.  This can work in
     *   both directions: Dec 31, 2007 has the ISO week date 2008-W01-1.

     *   Get the wall clock time represented by this Date object, in terms of
     *   local time in the given time zone (or the system's local time zone
     *   is 'tz' isn't specified).  Returns a list of integers: [hour,
     *   minute, second, ms].  The hour is on a 24-hour clock, with 0 hours
     *   representing midnight and 23 representing 11 PM.  The 'ms' value is
     *   a value from 0 to 999 giving the milliseconds portion of the time.

     *   Add an interval to this date, returning a new date object.  The
     *   interval is given as a list of integers: [years, months, days,
     *   hours, minutes, seconds].  The 'seconds' value can be a BigNumber
     *   with a fractional part (but anything smaller than milliseconds is
     *   discarded).  Elements can be omitted from the end of the list; for
     *   example, [0, 2] adds two months.  An element can be negative: [-1]
     *   subtracts one year.

     *   Find a given day of the week relative to this date, in its local
     *   time zone.  'weekday' is the target weekday to find, as an integer:
     *   1 for Sunday, 2 for Monday, ..., 7 for Saturday.  'which' is an
     *   integer specifying which relative day to find: 1 means to find the
     *   next occurrence of the given weekday on or after this date, 2 means
     *   the second occurrence on or after this date, and so on.  -1 means
     *   the first occurrence on or before this date; -2 is the second
     *   occurrence on or before this date; etc.
    findWeekday(weekday, which, tz?);

     *   Set a locale string.  This sets localized versions of the string
     *   values used for parsing and formatting date values.  By default,
     *   suitable English strings are used.  See the DateXxx index values for
     *   the individual locale strings that can be customized.
     *   Note that this is a static method that you call on the Date class
     *   object (e.g., Date.setLocaleInfo(DateMonthNames,
     *   'Sunday,Monday,...').
     *   There are two ways to call this method:
     *.  1. Date.setLocaleInfo([monthNames, monthAbbrs, weekdayNames, ...])
     *.  Each item in the list is a string.  This lets you set all of
     *   the locale items in one shot; the items are listed in order of
     *   the DateXxx index values.  You can omit items from the end of
     *   the list; any omitted items won't be changed.
     *   2. Date.setLocaleInfo(DateXxx, 'value', ...);
     *.  Specify DateXxx indices and the corresponding string values as
     *   alternating arguments.  These have to be provided in pairs.
     *   Any indices not listed won't be affected.
     *   All of the values are specified as strings.  Most are formatted as
     *   lists of words, separated by commas:
     *.    Date.setLocaleInfo(DateWeekdayAbbrs, 'Sun,Mon,Tue,Wed,Thu,Fri,Sat');
     *   For input parsing, you can provide synonyms, separated by '='.  For
     *   example, for month abbreviations, the English version accepts "Sep"
     *   and "Sept" as synonyms, which you can specify like so:
     *.    Date.setLocaleInfo(DateMonthAbbrs, 'Jan,Feb,Mar,Apr,May,Jun,'
     *.                       + 'Jul,Aug,Sep=Sept,Oct,Nov,Dec');
     *   When formatting output, the first item in a synonym list is the one
     *   displayed.
    static setLocaleInfo(...);

 *   Locale indices for Date.setLocaleInfo()

/* full names of months - January,February,March,... */
#define DateMonthNames     0

/* month name abbreviations - Jan,Feb,Mar... */
#define DateMonthAbbrs     1

/* full names of weekdays - Sunday,Monday,Tuesday,... */
#define DateWeekdayNames   2

/* abbreviated weekday names - Sun,Mon,Tue,... */
#define DateWeekdayAbbrs   3

/* AM/PM indicators - AM,PM */
#define DateAMPM           4

/* "era" indicator - AD=CE,BC=BCE */
#define DateEra            5

 *   Parsing filter for culture-specific date formats.  This can be 'us' to
 *   select the US-style formats, or 'eu' to select European-style formats.
 *   This controls day/month or month/day order when parsing numeric dates -
 *   the 'us' formats use the "month/day" style, as in 11/20 for November 20,
 *   and the 'eu' formats use "day/month", as in 20/11.
#define DateParseFilter    6

 *   Ordinal suffixes for 1st, 2nd, 3rd, Nth, X1st, X2nd, Xrd.  'Nth' is the
 *   suffix for everything not otherwise enumerated.  'X1st' is the suffix
 *   for the 21st, 31st, 1041st, etc - this applies to all of the decades
 *   except the units and teens; likewise for 'X2nd' and 'X3rd'.  Specify
 *   only the suffix; e.g., for English, 'st,nd,rd,th,st,nd,rd'.  If all of
 *   the items after a given point are the same for the target language, you
 *   can omit them, and the last item in the list will be used for all
 *   missing items; e.g., French can specify simply 'er,e', and German can
 *   specify simply '.'.
#define DateOrdSuffixes    7

 *   Default local format for date/time stamps.  This is a format string
 *   suitable for use in formatDate().  The default is '%a %b %#d %T %Y'
 *   (which produces, e.g., 'Thu Feb 7 15:20:33 2009').
#define DateFmtTimestamp   8

 *   Default local format for the time, without the date.  The default is
 *   '%H:%M:%S' ('18:44:39').
#define DateFmtTime        9

 *   Default local format for the date, without the time.  The default is
 *   '%m/%d/%Y' (02/15/2012).
#define DateFmtDate       10

 *   Local short date format.  The default is '%m/%d/%y' (02/15/12). 
#define DateFmtShortDate  11

 *   12-hour clock format.  The default is '%#I:%M:%S %P' ('5:30:22 PM').
#define DateFmt12Hour     12

 *   24-hour clock format.  The default is '%H:%M' (17:30).
#define DateFmt24Hour     13

 *   24-hour clock format with seconds.  The default is '%H:%M:%S'
 *   (17:30:22). 
#define DateFmt24HourSecs 14

/* ------------------------------------------------------------------------ */
 *   TimeZone intrinsic class.  A TimeZone object represents a location entry
 *   in the IANA zoneinfo database.  It contains information on the
 *   location's wall clock time settings relative to universal time (UTC),
 *   allowing translations between local wall clock time and UTC.  The object
 *   stores the current clock settings in the location, the current ongoing
 *   rules for future switches between standard and daylight time (if
 *   applicable in the zone), and a full history of the past changes to the
 *   location's time settings, including standard/daylight time changes,
 *   redefinitions of the time zone, and changes in the location from one
 *   time zone to another.  (For example, some US cities that lie near zone
 *   borders have switched their time zones at various points in their
 *   history.)  The historical information for most zones goes back to the
 *   original establishment of standard time zones, typically in the late
 *   19th century, and for dates before that, the history usually includes
 *   the Local Mean Time settings for the location.  The history information
 *   allows the accurate reconstruction of the local time representation for
 *   virtually any date and time in the past, present, or future.
 *   Construction: 
 *.    new TimeZone() - creates a TimeZone object representing the local
 *.        system time zone.  Note that a TimeZone object created this way
 *.        will always represent the local zone.  If the game is saved on
 *.        one machine and restored on another that uses a different local
 *.        time zone, the restored object will represent the new machine's
 *.        local time zone after the restore.
 *.   new TimeZone(integer) - creates a TimeZone object representing the
 *.        given offset from UTC, in seconds.  Positive values are east of
 *.        UTC, negative values are west; for example, Pacific Standard
 *.        Time is 8 hours west of UTC, so you'd use -8*60*60 as the offset.
 *.        This type of TimeZone represents a fixed offset
 *.   new TimeZone('name') - creates a TimeZone object for the given zone
 *.        name.  This can use a number of formats:
 *.        'America/New_York' - a name from the IANA zoneinfo database.
 *.            This is the best way to specify a zone because it's
 *.            unambiguous.
 *.        'Z', 'UTC' - UTC (Universal Time Coordinated, also sometimes
 *.            called GMT/Greenwich Mean Time, or Z/Zulu time)
 *.        'EST' - a colloquial English abbreviation for a local time
 *.            zone.  Many of these are ambiguous, since some zone names
 *.            are used in several different regions.  For example,
 *.            'CST' is used in the US, Brazil, Australia, and China,
 *.            for time zones at different offsets from UTC.  When the
 *.            name is ambiguous, we use a fixed mapping that tends to
 *.            favor zones in the US and Europe.  This format is mapped
 *.            to a zoneinfo entry, so the actual underlying zone will
 *.            be one of the location-based entries.  For example, 'EST'
 *.            is mapped to 'America/New_York'.  This is important
 *.            because it means that the TimeZone object uses the full
 *.            rule set and history for the mapped zone, which might
 *.            differ from the history of the same nominal zone in other
 *.            locations; e.g., 'America/New_York' and 'Canada/Montreal'
 *.            are both on Eastern Time, but they have some differences
 *.            in their historical daylight savings rules.
 *.        'PST8PDT' - a POSIX TZ-style string, with the standard time
 *.            abbreviation, the standard time offset in hours (and
 *.            optionally minutes and seconds, with colons), the daylight
 *.            time abbreviation, and optionally the daylight time
 *.            offset (which defaults to one hour ahead of standard
 *.            time when not specified).  This is somewhat less ambiguous
 *.            than using just the zone abbreviation, but is still
 *.        '+0430' or 'UTC+0430' - four hours thirty minutes east of UTC;
 *.            this can also be written as '+4:30' or '+4:30:00'.  For a
 *.            whole number of hours, you can write it as simply '+4', for
 *.            example.  A negative number is west of UTC; e.g., Pacific
 *.            Standard Time is '-8'.  When using this format, the zone
 *.            represents a fixed time offset from UTC; it's not tied to
 *.            any location or named time zone, and doesn't use daylight
 *.            savings time.
 *   Note that the commonly used time zone names (e.g., PST, or Pacific
 *   Standard Time) aren't allowed.  The standard time zone names are
 *   ambiguous; for example, CST refers to at least four different time zones
 *   (USA Central Standard Time, Australia Central Standard Time, China
 *   Standard Time, and Cuba Summer Time).
intrinsic class TimeZone 'timezone/030000' : Object
     *   Get the name or names for this timezone.  This returns a list of
     *   strings with the timezone's names, as defined in the IANA zoneinfo
     *   database.  The zoneinfo database names zones by location, usually
     *   using a combination of a continent major city, as in
     *   'America/New_York'.  Some zones have multiple aliases as a matter of
     *   convenience, such as when there are several major cities in a region
     *   that share the same timezone rules.  When a zone has aliases, the
     *   primary name is listed first, followed by the aliases.

     *   Get the history item that applies to a given date, or the entire
     *   enumerated history of clock changes in this timezone.
     *   If 'date' is supplied, it must be a Date object.  This returns a
     *   list describing the single period in the timezone history that
     *   applies to the given date.  The list contains [date, offset, save,
     *   abbr], where 'date' is a Date object giving the starting date when
     *   the history item took effect; 'offset' is the offset from UTC in
     *   milliseconds of standard time in the zone during this period, using
     *   the zoneinfo convention that positive values are east of GMT; 'save'
     *   is the additional time added if daylight savings is in effect during
     *   this period, in milliseconds, or zero if standard time is in effect;
     *   and 'abbr' is a string giving the abbreviation for the zone during
     *   this period ('PST', 'EDT', etc).  Each period in the history is
     *   entirely in daylight or standard time; if 'save' is zero, standard
     *   time is in effect, otherwise daylight time.
     *   If 'date' is omitted or nil, this returns a list of all of the
     *   pre-computed changes in the timezone's history, including definition
     *   changes and daylight time changes.  Each list entry is a sublist of
     *   the form described above.
     *   In a full history, the first and last items are special.  The first
     *   item represents the settings in the location prior to the
     *   establishment of standard time zones; this is usually a "local mean
     *   time" setting (with abbreviation LMT) for the mean solar time at the
     *   location.  The last item represents the last pre-computed history
     *   entry, which is sometimes in the future; further transitions after
     *   this item might occur if the zone has ongoing rules.
     *   In many cases, the history list contains a number of periods that
     *   could have been inferred from the ongoing rules, so strictly
     *   speaking they don't need to be enumerated in the history.  When
     *   they're included, it's for faster run-time lookup.  TADS
     *   pre-computes rule-based transitions up to the present and a few
     *   years into the future, since history-based lookups are much faster
     *   than applying the rules.  We expect that the typical program will
     *   mostly work with dates close to the present time, so we pre-compute
     *   transitions for a few years into the future to speed things up for
     *   the typical case.  For changes after the last enumerated entry, TADS
     *   applies the rules, so transitions in the far future will be
     *   correctly figured when needed.

     *   Get the ongoing rules that are in effect after the last enumerated
     *   history item.  This returns a list of the rules for future changes
     *   to the zone; each rule fires once annually, and encodes the day of
     *   year when the rule fires, and the new clock settings in effect after
     *   the rule fires.  Virtually all zones that use ongoing rules have
     *   exactly two: one for the annual change to daylight savings time in
     *   the spring, and one for the return to standard time in the fall.
     *   Each rule's firing date is specified in an abstract format designed
     *   to handle the variety of regional daylight savings schemes: "last
     *   Sunday in March", "second Sunday in November", "January 15", etc.
     *   Each rule in the list is described by a sublist: [abbr, offset,
     *   save, when, mm, typ, dd, wkday, time, zone].  'abbr' is a string
     *   with the time zone abbreviation while the rule is in effect; most
     *   zones use one abbreviation for standard time and another for
     *   daylight time, so each rule tells us the abbreviation to use while
     *   the rule is in effect.  'offset' is the standard time GMT offset, in
     *   milliseconds, while the rule is in effect, and 'save' is the
     *   additional offset for daylight savings time - so the full offset
     *   while the rule is in effect is offset+save.  'when' is a string with
     *   a human-readable description of the firing date: this will be of the
     *   form 'Mar last Sun' (for the last Sunday in March), 'Mar Sun>=1' for
     *   the first Sunday in March on or after March 1, 'Mar Sun<=28' for the
     *   last Sunday in March on or before March 28, 'Mar 7' for March 7, or
     *   'DOY 72' for the 72nd day of the year.  Next we have the same firing
     *   date information in a more computer-friendly format: 'mm' is the
     *   month number, 1-12 for Jan-Dec; 'typ' is an integer giving the type
     *   of date specification (0 for a fixed day of the month 'mm/dd', 1 for
     *   the last <weekday> of month <mm>, 2 for the first <weekday> of month
     *   <mm> on or after day <dd>, and 3 for the last <weekday> of month
     *   <mm> on or before day <dd>), 'dd' is the day of the month (which is
     *   ignored if 'typ' is 1), 'wkday' is the day of the week, 1-7 for
     *   Sunday-Saturday (which is ignored if 'typ' is 0).  'time' is the
     *   time of day the rule goes into effect, as milliseconds after
     *   midnight.  'zone' is a code for the timezone used to interpret the
     *   date and time; this is usually 'w' for local wall clock time (in
     *   other words, the local time zone that was in effect up until the
     *   moment this rule takes effect - so if this is a daylight savings
     *   rule, the rule is stated in terms of local standard time, and vice
     *   versa), but can also be 's' for local standard time (in other words,
     *   if the previous period was in daylight time, ignore that and read
     *   this rule's time in terms of local standard time instead), or 'u'
     *   for UTC.  Note that the zone has to be applied to the full
     *   date-and-time value, since an 's' or 'u' could conceivably cause the
     *   local date and the date in the rule's zone to differ by a day at the
     *   time of day of the rule.

     *   Get the zone's location.  This returns a list: [country, lat, lon,
     *   comment], where 'country' is a string with the country code (a
     *   two-letter ISO 3166 code) for the country that contains the zone's
     *   main city, 'lat' is a string giving the latitude in the format +ddmm
     *   (degrees and minutes) or +ddmmss (and seconds), 'lon' is the
     *   longitude as a string in the format +dddmm or +dddmmss, and
     *   'comment' is a string with any comment text from the zoneinfo
     *   database.
TADS 3 Library Manual
Generated on 5/16/2013 from TADS version 3.1.3