timezones

import times
import timezones

# Create a timezone representing a static offset from UTC.
let zone = tz"+02:30"
echo initDateTime(1, mJan, 2000, 12, 00, 00, zone)
# => 2000-01-01T12:00:00+02:30

# Static offset timezones can also be created with the proc ``staticTz``,
# which is preferable if the offset is only known at runtime.
doAssert zone == staticTz(hours = -2, minutes = -30)

# Create a timezone representing a timezone in the IANA timezone database.
let stockholm = tz"Europe/Stockholm"
echo initDateTime(1, mJan, 1850, 00, 00, 00, stockholm)
# => 1850-01-01T00:00:00+01:12

# Like above, but returns a `TimezoneInfo` object which contains some
# extra metadata.
let stockholmInfo = tzInfo"Europe/Stockholm"
# Countries are specified with it's two character country code,
# see ISO 3166-1 alpha-2.
doAssert stockholmInfo.countries == @["SE"]
doAssert stockholmInfo.timezone == stockholm

# Note that some timezones are used by multiple countries.
let bangkok = tzInfo"Asia/Bangkok"
doAssert bangkok.countries == @["TH", "KH", "LA", "VN"]

Types

Country = string

A country is represented by a two character country code, using ISO 3166-1 alpha-2.

See https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2.

TimezoneDb = TimezoneDbImpl
A collection of loaded timezones, typically from a specific release of the IANA timezone database.
TimezoneInfo = object
  timezone*: Timezone          ## \
                    ## The timezone as a ``times.Timezone`` object.
  countries*: seq[Country]     ## \
                         ## Get a list of countries that are
                         ## known to use this timezone.
                         ## Note that some countries use
                         ## multiple timezones.
  location*: Option[Coordinates] ## \
                               ## Get the coordinates of a timezone. This is generally the
                               ## coordinates of the city in the timezone name.
                               ## E.g ``db.location"Europe/Stockholm"`` will give the the
                               ## coordinates of Stockholm, the capital of Sweden.
  
A timezone with additional metadata attached.
Dms = object
  deg*, min*, sec*: int16
A coordinate specified in degrees (deg), minutes (min) and seconds (sec).
Coordinates = object
  lat*, lon*: Dms
Earth coordinates.

Procs

proc tz(db: TimezoneDb; tzName: string): Timezone {...}{.raises: [ValueError], tags: [].}
Retrieve a timezone from a timezone name, where the timezone name is one of the following:
  • The string "LOCAL", representing the systems local timezone.
  • A string of the form "±HH:MM:SS" or "±HH:MM", representing a fixed offset from UTC. Note that the sign will be the opposite when compared to staticTz. For example, tz"+01:00" is the same as staticTz(hour = -1).
  • A timezone name from the IANA timezone database. See wikipedia for a list of available timezone names. Note that there is no guranteas about what timezones are available in db, but as a special rule "Etc/UTC" is always supported.

In case tzName does not follow any of these formats, or the timezone name doesn't exist in the database, a ValueError is raised.

proc tz(tzName: string): Timezone {...}{.inline, raises: [ValueError], tags: [].}
Convenience proc using the default timezone database.

Examples:

import
  times

let stockholm = tz"Europe/Stockholm"
let dt = initDateTime(1, mJan, 1850, 0, 0, 0, stockholm)
doAssert $dt == "1850-01-01T00:00:00+01:12"
proc tzInfo(db: TimezoneDb; tzName: string): TimezoneInfo {...}{.raises: [ValueError],
    tags: [].}

Retrieve a timezone with additional metadata.

The tzName parameter follows the same format as db.tz(...).

In case tzName has an invalid format, or the timezone name doesn't exist in the database, a ValueError is raised.

proc tzInfo(tzName: string): TimezoneInfo {...}{.inline, raises: [ValueError], tags: [].}
Convenience proc using the default timezone database.

Examples:

import
  times, options

let stockholmInfo = tzInfo"Europe/Stockholm"
doAssert stockholmInfo.timezone == tz"Europe/Stockholm"
doAssert stockholmInfo.countries == @["SE"]
doAssert $stockholmInfo.location == "Some(59° 20′ 0″ N 18° 3′ 0″ E)"
proc setDefaultTzDb(db: TimezoneDb) {...}{.raises: [], tags: [].}
Sets the timezone database that will be used for tz(tzName) and tzInfo(tzName). The default timezone database is stored in a thread local variable, so calling this only affects the calling thread!
proc getDefaultTzDb(): TimezoneDb {...}{.raises: [], tags: [].}
Gets the timezone database that is used for tz(tzName) and tzInfo(tzName). The default timezone database is stored in a thread local varaible, so calling setDefaultTzDb only affects the calling thread!
proc staticTz(hours, minutes, seconds: int = 0): Timezone {...}{.noSideEffect, raises: [],
    tags: [].}
Create a timezone using a static offset from UTC.

Examples:

import
  times

let tz = staticTz(hours = -2, minutes = -30)
doAssert $tz == "+02:30"
let dt = initDateTime(1, mJan, 2000, 12, 0, 0, tz)
doAssert $dt == "2000-01-01T12:00:00+02:30"
proc parseTzDb(content: string): TimezoneDb {...}{.raises: [KeyError, ValueError,
    JsonKindError, Exception, Defect, IOError, OSError, JsonParsingError],
    tags: [ReadIOEffect, WriteIOEffect].}
Parse a timezone database from its JSON representation.
proc parseTzDb(s: Stream): TimezoneDb {...}{.raises: [KeyError, ValueError, JsonKindError,
    Exception, Defect, IOError, OSError, JsonParsingError],
                                    tags: [ReadIOEffect, WriteIOEffect].}
Parse a timezone database from its JSON representation.
proc loadTzDb(path: string): TimezoneDb {...}{.raises: [IOError, Exception, OSError,
    KeyError, ValueError, JsonKindError, Defect, JsonParsingError],
                                      tags: [WriteIOEffect, ReadIOEffect].}
Load a timezone database from a JSON file.
proc version(db: TimezoneDb): string {...}{.raises: [], tags: [].}

The version of the IANA timezone database being represented by db. The string consist of the year plus a letter. For example, "2018a" is the first database release of 2018, "2018b" the second one and so on.

If the version is unknown, returns "".

proc tzNames(db: TimezoneDb): seq[string] {...}{.raises: [], tags: [].}
Retrieve a list of all available timezones in db.
proc initCoordinates(lat, lon: (int16, int16, int16)): Coordinates {...}{.raises: [], tags: [].}
Create a coordinates object.
proc `$`(coords: Coordinates): string {...}{.raises: [], tags: [].}
Human-friendly stringification of coordinates.

Examples:

let loc = initCoordinates((1'i16, 2'i16, 3'i16), (4'i16, 5'i16, 6'i16))
doAssert $loc == r"1° 2′ 3″ N 4° 5′ 6″ E"