RFC 9636

The Time Zone Information Format (TZif)

๐Ÿ“… published October 2024, from ietf

RFC 9636: The Time Zone Information Format (TZif) ๐Ÿ•ฐ๏ธ๐ŸŽ€

Okay bestie, RFC 9636 is giving main character energy ๐Ÿ’…. It's a Standards Track doc from October 2024, written by A. Olson, P. Eggert (UCLA), and K. Murchison (Fastmail). Its ISSN is 2070-1721 ๐Ÿ“„. It obsoletes RFC 8536 (the older version), and it doesn't update anything else ๐ŸŒธ. It's an official IETF document, so this is the real deal โœจ.

Abstract ๐Ÿ’–

This document specifies the Time Zone Information Format (TZif) for representing and exchanging time zone information, independent of any particular service or protocol. Two media types for this format are also defined ๐Ÿฆ‹.

This document replaces and obsoletes RFC 8536 ๐Ÿซถ.

Status of This Memo ๐Ÿ“œ

This is an Internet Standards Track document ๐Ÿ‘‘.

This document is a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community. It has received public review and has been approved for publication by the Internet Engineering Steering Group (IESG). Further information on Internet Standards is available in Section 2 of RFC 7841 โœจ.

Information about the current status of this document, any errata, and how to provide feedback on it may be obtained at https://www.rfc-editor.org/info/rfc9636 ๐Ÿ“.

Copyright (c) 2024 IETF Trust and the persons identified as the document authors. All rights reserved ๐ŸŒˆ.

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, because they describe your rights and restrictions with respect to this document ๐Ÿ™ˆ. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions, and they are provided without warranty as described in the Revised BSD License ๐Ÿ’œ.

Table of Contents ๐Ÿ—บ๏ธ

1.  Introduction
2.  Conventions Used in This Document
3.  The Time Zone Information Format (TZif)
  3.1.  TZif Header
  3.2.  TZif Data Block
  3.3.  TZif Footer
    3.3.1.  All-Year Daylight Saving Time
    3.3.2.  TZ String Extension
4.  Interoperability Considerations
5.  Internationalization Considerations
6.  Use with the Time Zone Data Distribution Service
  6.1.  Truncating TZif Files
  6.2.  Example TZDIST Request for TZif Data
7.  Security Considerations
8.  Privacy Considerations
9.  IANA Considerations
  9.1.  application/tzif
  9.2.  application/tzif-leap
10. References
  10.1.  Normative References
  10.2.  Informative References
Appendix A.  Common Interoperability Issues
Appendix B.  Example TZif Files
  B.1.  Version 1 File Representing UTC (with Leap Seconds)
  B.2.  Version 2 File Representing Pacific/Honolulu
  B.3.  Truncated Version 2 File Representing Pacific/Johnston
  B.4.  Truncated Version 3 File Representing Asia/Jerusalem
  B.5.  Truncated Version 4 File Representing Europe/London
Appendix C.  Changes from RFC 8536
Acknowledgments
Authors' Addresses

1. Introduction โœจ

Okay so, time zone data usually includes offsets from universal time (UT) ๐Ÿ•’, daylight saving transition rules โ˜€๏ธ, one or more local time designations (acronyms or abbreviations) ๐Ÿท๏ธ, and optional leap-second adjustments โž•. One format that carries this info is iCalendar [RFC5545] ๐Ÿ“…. It's text-based and used by calendaring and scheduling systems, so it's giving organized ๐Ÿ—“๏ธ.

This document specifies the widely deployed Time Zone Information Format (TZif) ๐ŸŽ€. It's a binary format that most UNIX systems use to work out local time ๐Ÿ’ป. It came out in the 1980s and has since evolved into several upward-compatible versions, which is honestly iconic ๐Ÿงš. Lots of interoperable software can generate and read files in this format [tz-link] ๐Ÿ™Œ.

This specification doesn't define where the data in a TZif file comes from ๐Ÿคทโ€โ™€๏ธ. One such source is the IANA-hosted time zone database [RFC6557] ๐ŸŒ.

This document obsoletes [RFC8536] ๐Ÿซถ, bringing editorial improvements, new details, and errata fixes, all while keeping full compatibility with the interchange format of [RFC8536] ๐Ÿ’–. It also defines a new version of the format ๐Ÿฆ‹. The changes from [RFC8536] are summarized in Appendix C ๐Ÿ“.

2. Conventions Used in This Document ๐Ÿ”ค

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here ๐Ÿ’….

Here are the terms used in this document. For more detail about civil timekeeping data and practice, check out "Time zone and daylight saving time data" [tz-link] ๐Ÿง .

Coordinated Universal Time (UTC): The basis for civil time since 1960 โฑ๏ธ. It's approximately equal to mean solar time at the prime meridian (0 degrees longitude) ๐ŸŒž.

Daylight Saving Time (DST): The time according to a location's law or practice, adjusted as necessary from standard time ๐ŸŒ…. The adjustment may be positive or negative, and its amount may vary depending on the date and time. The TZif format even allows the adjustment to be zero, although that isn't common practice ๐Ÿ™ƒ.

International Atomic Time (TAI): The time standard based on atomic clocks since 1972 โš›๏ธ. It's equal to UTC, but without leap-second adjustments ๐Ÿงฎ.

Leap Second: A one-second adjustment that keeps UTC close to mean solar time at the prime meridian (see [ITU-R-TF.460]) ๐Ÿ•›. Each inserted or deleted leap second happens at the end of a UTC month, meaning a month using the Gregorian calendar and the UTC timescale ๐Ÿ“†.

Leap-Second Correction (LEAPCORR): The value of "TAI - UTC - 10" for timestamps after the first leap second, and zero for timestamps before that ๐Ÿ”ข. The expression "TAI - UTC - 10" comes from the fact that TAI - UTC was defined to be 10 just before the first leap second in 1972. That's why clocks with leap seconds have a zero LEAPCORR before the first leap second ๐Ÿฅน.

Local Time: Civil time for a particular location ๐Ÿ“. Its offset from universal time can depend on the date and time of day ๐Ÿ•ฐ๏ธ.

POSIX Epoch: 1970-01-01 00:00:00 UTC, which is the basis for absolute timestamps in this document ๐Ÿ.

Standard Time: The time according to a location's law or practice, without any daylight saving adjustment ๐Ÿงƒ.

Time Change: A change to civil timekeeping practice ๐Ÿ”„. It happens when one or more of the following occur simultaneously:

  1. a change in UT offset
  2. a change in whether daylight saving time is in effect
  3. a change in time zone abbreviation
  4. a leap second (i.e., a change in LEAPCORR)

Time Zone Data: The Time Zone Data Distribution Service (TZDIST) [RFC7808] defines "Time zone data" as "data that defines a single time zone, including an identifier, UTC offset values, DST rules, and other information such as time zone abbreviations". The interchange format defined in this document is one such form of time zone data ๐Ÿ—บ๏ธ.

Transition Time: The moment a time change occurs that is not a leap second โฐ. It's identified with a signed integer count of UNIX leap time seconds since the POSIX epoch ๐Ÿ”ข.

Universal Time (UT): The basis of civil time ๐ŸŒ. For timestamps before UTC was introduced in 1960, this is the principal form of mean solar time at the prime meridian (0 degrees longitude). For timestamps after that, it's UTC ๐ŸŒŸ. Other sources sometimes call UT "UTC" or "GMT", but this specification uses the term "UT" to avoid confusion with UTC or with GMT ๐Ÿ™…โ€โ™€๏ธ.

UNIX Time: The time returned by the time() function provided by the C programming language (see Section 3 of the "System Interfaces" volume of [POSIX]) ๐Ÿ’พ. It's an integer number of seconds since the POSIX epoch, not counting leap seconds. As an extension to POSIX, negative values represent times before the POSIX epoch, using UT ๐Ÿ”™.

UNIX Leap Time: UNIX time plus all preceding leap-second corrections ๐Ÿงฉ. For example, if the first leap-second record in a TZif file occurs at 1972-06-30 23:59:60 UTC, the UNIX leap time for the timestamp 1972-07-01 00:00:00 UTC would be 78796801, which is one greater than the UNIX time for the same timestamp ๐Ÿ˜ญ. Similarly, if the second leap-second record occurs at 1972-12-31 23:59:60 UTC, it accounts for the first leap second. So the UNIX leap time of 1972-12-31 23:59:60 UTC would be 94694401, and the UNIX leap time of 1973-01-01 00:00:00 UTC would be 94694402 ๐Ÿฅณ. If a TZif file specifies no leap-second records, UNIX leap time is equal to UNIX time ๐ŸŒธ.

Wall Time: Another name for local time, short for "wall-clock time" ๐Ÿงฑ.

3. The Time Zone Information Format (TZif) โœจ

okay so TZif starts with a fixed 44-octet version 1 header (Section 3.1) and one of its fields tells you which version of the format the file is using ๐Ÿงš. the cute part is that readers built for version N can usually handle version N+1 files without much drama. the newer stuff either sits after the version N data so older readers can just skip what they don't understand, or it's a small extension to version N that version N readers will probably tolerate just fine ๐Ÿ’–

the version 1 header is followed by a variable-length version 1 data block (Section 3.2). that block holds four-octet (32-bit) transition times and leap-second occurrences ๐Ÿฆ‹ those 32-bit values can only cover time changes from 1901-12-13 20:45:52 through 2038-01-19 03:14:07 UT. the version 1 header and data block are only there for backward compatibility with obsolescent readers, which is covered in "Common Interoperability Issues" (Appendix A) ๐Ÿ™ˆ

version 1 files end right after the version 1 data block ๐Ÿ›‘ files from versions 2 and higher add a second 44-octet version 2+ header, a variable-length version 2+ data block with eight-octet (64-bit) transition times and leap-second occurrences, and a variable-length footer (Section 3.3). those 64-bit values can represent times roughly 292 billion years into the past or future ๐Ÿคฏ literally unhinged scale, iykyk.

NOTE: All multi-octet integer values MUST be stored in network octet order format (high-order octet first, otherwise known as big-endian), with all bits significant. Signed integer values MUST be represented using two's complement. ๐Ÿซถ

this is the layout of a TZif file, bestie ๐ŸŽ€

                     Version 1        Versions 2+
                  +-------------+   +-------------+
                  |  Version 1  |   |  Version 1  |
                  |   Header    |   |   Header    |
                  +-------------+   +-------------+
                  |  Version 1  |   |  Version 1  |
                  |  Data Block |   |  Data Block |
                  +-------------+   +-------------+
                                    |  Version 2+ |
                                    |   Header    |
                                    +-------------+
                                    |  Version 2+ |
                                    |  Data Block |
                                    +-------------+
                                    |   Footer    |
                                    +-------------+

                Figure 1: General Format of TZif Files

3.1. TZif Header ๐Ÿ’…

the TZif header is laid out like this (the lengths of multi-octet fields are in parentheses) ๐Ÿ“ฆ

    +---------------+---+
    |  magic    (4) |ver|
    +---------------+---+---------------------------------------+
    |           [unused - reserved for future use] (15)         |
    +---------------+---------------+---------------+-----------+
    |  isutcnt  (4) |  isstdcnt (4) |  leapcnt  (4) |
    +---------------+---------------+---------------+
    |  timecnt  (4) |  typecnt  (4) |  charcnt  (4) |
    +---------------+---------------+---------------+

                        Figure 2: TZif Header

here's what each field does ๐Ÿ‘‘

  • magic: a four-octet ASCII [RFC20] sequence "TZif" (0x54 0x5A 0x69 0x66), which tells you the file uses the Time Zone Information Format ๐Ÿ”ฅ
  • ver(sion): one octet that identifies the version of the file's format. the value MUST be one of the following:
    • NUL (0x00) Version 1 - the file contains only the version 1 header and data block. Version 1 files MUST NOT contain a version 2+ header, data block, or footer. ๐ŸŒธ
    • '2' (0x32) Version 2 - the file MUST contain the version 1 header and data block, a version 2+ header and data block, and a footer. The TZ string in the footer (Section 3.3), if non-empty, MUST strictly adhere to the requirements for the TZ environment variable as defined in Section 8.3 of the "Base Definitions" volume of [POSIX] and MUST encode the POSIX portable character set as ASCII. The leap-second records MUST NOT be truncated at the start (Section 6.1) and MUST NOT contain an expiration time. ๐Ÿ’œ
    • '3' (0x33) Version 3 - the file MUST conform to all version 2 requirements, except that any TZ string in the footer (Section 3.3) MAY use the TZ string extension described below (Section 3.3.2). โœจ
    • '4' (0x34) Version 4 - the file MUST conform to all version 3 requirements, except that the leap-second records MAY be truncated at the start and MAY contain an expiration time. ๐Ÿฆ‹
  • isutcnt: a four-octet unsigned integer specifying the number of UT/local indicators contained in the data block. It MUST either be zero or equal to "typecnt". ๐Ÿซง
  • isstdcnt: a four-octet unsigned integer specifying the number of standard/wall indicators contained in the data block. It MUST either be zero or equal to "typecnt". ๐ŸŒˆ
  • leapcnt: a four-octet unsigned integer specifying the number of leap-second records contained in the data block. ๐Ÿ“
  • timecnt: a four-octet unsigned integer specifying the number of transition times contained in the data block. โญ
  • typecnt: a four-octet unsigned integer specifying the number of local time type records contained in the data block. It MUST NOT be zero. (Although local time type records convey no useful information in files that have non-empty TZ strings but no transitions, at least one such record is nevertheless required because many TZif readers reject files that have zero time types.) ๐Ÿ’€
  • charcnt: a four-octet unsigned integer specifying the total number of octets used by the set of time zone designations contained in the data block. It MUST NOT be zero. The count includes the trailing NUL (0x00) octet at the end of the last time zone designation. ๐ŸŽ€

ngl the version 1 and 2+ headers have the exact same format, magic number, and version fields ๐Ÿ™Œ but their count fields can be different, because the version 1 data can be a subset of the version 2+ data. main character differences, lowkey ๐Ÿ’…

3.2. TZif Data Block โœจ

okay bestie, a TZif data block is made of seven variable-length elements ๐ŸŽ€, and each one is just a series of items. The header's count fields tell you how many items each series has. Multiply that number by the size of each item and boom, you get the total length of the element ๐Ÿงฎ. This is lowkey so useful, because if you don't wanna parse or use the version 1 data block, you can work out its total length and skip straight to the header of the version 2+ data block ๐Ÿฆ‹.

In the version 1 data block, time values are 32 bits (TIME_SIZE = 4 octets). In the version 2+ data block, which only shows up in version 2 and higher files, time values are 64 bits (TIME_SIZE = 8 octets) ๐Ÿ’œ.

Here's how the data block is laid out (the lengths of multi-octet fields are in parentheses, obviously ๐Ÿ™„):

+---------------------------------------------------------+
|  transition times          (timecnt x TIME_SIZE)        |
+---------------------------------------------------------+
|  transition types          (timecnt)                    |
+---------------------------------------------------------+
|  local time type records   (typecnt x 6)                |
+---------------------------------------------------------+
|  time zone designations    (charcnt)                    |
+---------------------------------------------------------+
|  leap-second records       (leapcnt x (TIME_SIZE + 4))  |
+---------------------------------------------------------+
|  standard/wall indicators  (isstdcnt)                   |
+---------------------------------------------------------+
|  UT/local indicators       (isutcnt)                    |
+---------------------------------------------------------+

Figure 3: TZif Data Block

Now let's go through the elements of the data block, one by one ๐Ÿ’…:

  • transition times: This is a series of four- or eight-octet UNIX leap time values, sorted in strictly ascending order. Each value is used as a transition time, which is a moment when the rules for computing local time may change. The number of time values is set by the "timecnt" field in the header. Each time value SHOULD be at least -2^59. (-2^59 is the greatest negated power of 2 that predates the Big Bang, and avoiding earlier timestamps works around known TZif reader bugs with outlandishly negative timestamps ๐Ÿ’€.)
  • transition types: This is a series of one-octet unsigned integers that tell you the type of local time for the matching transition time. These values act as zero-based indices into the array of local time type records. The number of type indices is set by the "timecnt" field in the header. Each type index MUST be in the range [0, "typecnt" - 1].
  • local time type records: This is a series of six-octet records, each one specifying a local time type. The number of records is set by the "typecnt" field in the header. Each record looks like this (the lengths of multi-octet fields are in parentheses):
+---------------+---+---+
|  utoff (4)    |dst|idx|
+---------------+---+---+
  • utoff: A four-octet signed integer giving the number of seconds to add to UT to get local time. The value MUST NOT be -2^31 and SHOULD be in the range [-89999, 93599], which means it SHOULD be more than -25 hours and less than 26 hours ๐ŸŒˆ. Skipping -2^31 lets 32-bit clients negate the value without overflow. Keeping it inside [-89999, 93599] makes it easy for implementations that already support the POSIX-required range [-24:59:59, 25:59:59] โœจ.
  • (is)dst: A one-octet value saying whether local time should count as Daylight Saving Time (DST). The value MUST be 0 or 1. A one (1) means this time type is DST, and a zero (0) means it's standard time ๐ŸŒธ.
  • (desig)idx: A one-octet unsigned integer that's a zero-based index into the series of time zone designation octets, which picks out one designation string. Each index MUST be in the range [0, "charcnt" - 1]. It points at the NUL-terminated string of octets starting at position "idx" in the time zone designations. (This string MAY be empty.) A NUL octet MUST exist in the time zone designations at or after position "idx". If the designation string is "-00", the time type is a placeholder meaning local time is unspecified ๐Ÿ™ˆ.
  • time zone designations: This is a series of octets that forms an array of NUL-terminated (0x00) time zone designation strings. The total number of octets is set by the "charcnt" field in the header. Two designations MAY overlap if one is a suffix of the other. The character encoding of time zone designation strings isn't specified, but check out Section 4 of this document for more on that ๐Ÿ“.
  • leap-second records: This is a series of eight- or twelve-octet records that specify the corrections that need to be applied to UTC to get TAI, also known as the leap-second table ๐Ÿงš. The records are sorted by occurrence time in strictly ascending order. The number of records is set by the "leapcnt" field in the header. Each record has one of these two structures (the lengths of multi-octet fields are in parentheses):
Version 1 Data Block:
   +---------------+---------------+
   |  occur (4)    |  corr (4)     |
   +---------------+---------------+

version 2+ Data Block:
   +---------------+---------------+---------------+
   |  occur (8)                    |  corr (4)     |
   +---------------+---------------+---------------+
  • occur(rence): A four- or eight-octet UNIX leap time value that marks when a leap-second correction happens, or when the leap-second table expires. The first value, if there is one, MUST be non-negative, and each leap second MUST occur at the end of a UTC month ๐Ÿ‘‘.
  • corr(ection): A four-octet signed integer giving the value of LEAPCORR on or after the occurrence. If "leapcnt" is zero, LEAPCORR is zero for all timestamps. If "leapcnt" is nonzero, then for timestamps before the first occurrence time, LEAPCORR is zero if the first correction is one (1) or minus one (-1). Otherwise it's unspecified, which can only happen in files truncated at the start (Section 6.1) ๐Ÿ˜ญ.

The first leap second is a positive leap second if and only if its correction is positive. Each correction after the first MUST differ from the previous correction by either one (1) for a positive leap second or minus one (-1) for a negative leap second. The exception is version 4 files with two or more leap-second records: there, the correction values of the last two records MAY be the same, and the occurrence of the last record tells you when the leap-second table expires โญ.

The leap-second table expiration time is the point when the table stops recording whether future leap-second corrections happen or don't happen. After that, timestamps can't be calculated accurately. For example, a leap-second table published in January that predicts whether there's a leap second at the end of June might expire in mid-December, because nobody knows yet when the next leap second will happen ๐ŸŒ™.

If leap seconds get permanently discontinued, as the General Conference on Weights and Measures [CGPM-2022-R4] has requested, then leap-second tables published after the discontinuation time SHOULD NOT expire. They won't be updated in the foreseeable future, so expiring them makes no sense ๐Ÿฆ‹.

  • standard/wall indicators: This is a series of one-octet values showing whether the transition times for local time types were specified as standard time or wall-clock time. Each value MUST be 0 or 1. A one (1) means standard time, and a zero (0) means wall time. The value MUST be set to one (1) if the matching UT/local indicator is set to one (1). The number of values is set by the "isstdcnt" field in the header. If "isstdcnt" is zero (0), all transition times for local time types are assumed to be wall time ๐Ÿ“.
  • UT/local indicators: This is a series of one-octet values showing whether the transition times for local time types were specified as UT or local time. Each value MUST be 0 or 1. A one (1) means UT, and the matching standard/wall indicator MUST also be set to one (1). A zero (0) means local time. The number of values is set by the "isutcnt" field in the header. If "isutcnt" is zero (0), all transition times for local time types are assumed to be local time ๐Ÿ’–.

Here's how it all clicks together โœจ: the type matching a transition time tells you the local time for timestamps starting at that transition time and running up to, but not including, the next transition time. Local time for timestamps before the first transition comes from the first time type (time type 0). Local time for timestamps on or after the last transition comes from the TZ string in the footer (Section 3.3) if one is present and non-empty. Otherwise, it's unspecified. If there are no transitions at all, local time for every timestamp comes from the TZ string in the footer if it's present and non-empty. If not, it comes from time type 0. A time type with a designation string of "-00" stands for unspecified local time ๐Ÿซถ.

A given pair of standard/wall and UT/local indicators says whether the matching transition time was specified as UT, standard time, or wall-clock time. There are only three combinations of the two indicators, because the standard/wall value MUST be one (1) whenever the UT/local value is one (1) ๐Ÿ”ฅ. This info helps when transition times in a TZif file need to be turned into transitions for another time zone, like when you're working out transition times for a simple POSIX-like TZ string such as "AKST9AKDT" ๐ŸŒˆ.

To cut out unused space in a TZif file, every nonzero local time type index SHOULD appear at least once in the transition type array. Likewise, every octet in the time zone designations array SHOULD be used by at least one time type record ๐Ÿ’…โœจ.

okay so the TZif footer is structured like this (the lengths of multi-octet fields are in parentheses, bestie ๐ŸŽ€):

                      +---+--------------------+---+
                      | NL|  TZ string (0...)  |NL |
                      +---+--------------------+---+

                           Figure 4: TZif Footer

here's what each piece does ๐Ÿ’…

  • NL: an ASCII new line character (0x0A) ๐Ÿ“
  • TZ string: a rule for computing local time changes after the last transition time stored in the version 2+ data block ๐Ÿ•ฐ๏ธ The string is either empty or uses the expanded format of the TZ environment variable from Section 8.3 of the "Base Definitions" volume of [POSIX], with ASCII encoding. In version 3 and higher files, it can also use the extension in Section 3.3.2. If the string is empty, the info just isn't available. If the string is non-empty and one or more transitions show up in the version 2+ data, the string MUST be consistent with the last version 2+ transition. Put another way, evaluating the TZ string at the time of the last transition should give you the same time type that was specified in the last transition. The string MUST NOT contain NUL octets or be NUL-terminated, and it SHOULD NOT begin with the ":" (colon) character. no notes, just rules ๐Ÿ™…โ€โ™€๏ธ

the footer only shows up in version 2 and higher files, since the old version 1 format was designed before anyone realized a footer was needed ๐Ÿฅน

3.3.1. All-Year Daylight Saving Time ๐ŸŒž

DST counts as in effect all year if its UT offset is less than (i.e., west of) the standard time offset. It starts January 1 at 00:00 and ends December 31 at 24:00 minus the difference between standard and daylight saving time, so there's no room left for standard time on the calendar at all ๐Ÿ˜ญ [POSIX] kinda implies this but never actually says it, so it gets spelled out here for clarity โœจ

Example: XXX3EDT4,0/0,J365/23 This is a time zone that's perpetually 4 hours west of UT, abbreviated "EDT". The "XXX" gets ignored, bestie ๐Ÿ’œ

3.3.2. TZ String Extension ๐Ÿ”ฎ

the TZ string in a version 3 or higher TZif file MAY use the following extension to POSIX TZ strings. It's described using the terminology from Section 8.3 of the "Base Definitions" volume of [POSIX] ๐Ÿง 

the hours part of the transition times may be signed and can range from -167 through 167 (-167 <= hh <= 167), instead of the POSIX-required unsigned values from 0 through 24. so much more flexibility, it's giving main character energy ๐Ÿ‘‘

Example: <-03>3<-02>,M3.5.0/-2,M10.5.0/-1 This is a time zone that observes daylight saving time from 22:00 on the day before March's last Sunday until 23:00 on the day before October's last Sunday. Standard time is 3 hours west of UT and abbreviated "-03", and daylight saving time is 2 hours west of UT and abbreviated "-02" ๐ŸŒธ

a TZif file that uses the extension above MUST be designated as version 3 (or higher), even if a future version of POSIX adopts this extension. no exceptions, periodt ๐Ÿ’…


4. Interoperability Considerations ๐Ÿซถ

these practices help keep TZif applications interoperating, so pay attention ๐Ÿฆ‹

  • Version 1 files are considered a legacy format and SHOULD NOT be generated, since they don't support transition times after the year 2038 ๐Ÿ™ˆ
  • Readers that only understand version 1 MUST ignore any data that extends beyond the calculated end of the version 1 data block.
  • Other than version 1, writers SHOULD generate the lowest version number that a file's data needs. This helps with interoperability with older readers โœจ For example, a writer SHOULD generate a version 4 file only if its leap-second table either expires or gets truncated at the start. Likewise, a writer that isn't generating a version 4 file SHOULD generate a version 3 file only if the TZ string extension is necessary to model transition times accurately.
  • To save space, writers of version 2+ files MAY output a placeholder version 1 data block with all counts at zero, except that "typecnt" and "charcnt" are both one (1). If this is done, obsolescent version-1-only readers MUST interpret these files as lacking time changes and time zone abbreviations ๐Ÿฅบ
  • Unless the version 1 data block is a placeholder, the sequence of timestamps defined by the version 1 header and data block SHOULD be a contiguous sub-sequence of the timestamps defined by the version 2+ header and data block and by the footer. This helps obsolescent version 1 readers agree with current readers about timestamps in that contiguous sub-sequence ๐Ÿค
  • When a TZif file contains a leap-second table expiration time, TZif readers SHOULD either refuse to process post-expiration timestamps or process them as if the expiration time didn't exist (possibly with an error indication). This cuts down on disagreement between implementations when they process far-future timestamps that can't be handled exactly yet ๐Ÿ”ญ
  • Time zone designations MUST consist of at least three (3) and no more than six (6) ASCII characters from the set of alphanumerics, "-", and "+". This is compatible with POSIX requirements for time zone abbreviations ๐Ÿ’–
  • A reader that runs into a time zone designation with bytes other than ASCII alphanumerics, "-", and "+" SHOULD act as if the designation instead contained a signed numeric string derived from the UT offset. For example, "-10" and "+0530" mean 10 hours west and 5.5 hours east of Greenwich, respectively ๐ŸŒ
  • When reading a version 2 or higher file, readers SHOULD ignore the version 1 header and data block, except for skipping over them. This improves compatibility among readers of non-conforming files, where version 2+ data isn't upward compatible with version 1 ๐Ÿงš
  • Readers SHOULD calculate the total lengths of the headers and data blocks and check that they all fit within the actual file size, as part of a validity check for the file โœ…
  • When a TZif file is used in a MIME message entity, it SHOULD be indicated by one of the following media types:
    • application/tzif-leap (Section 9.2) indicates that leap-second records are included in the TZif data as necessary. (None are necessary if the file is truncated to a range that comes before the first leap second.)
    • application/tzif (Section 9.1) indicates that leap-second records are not included in the TZif data. "leapcnt" in the header(s) MUST be zero (0) ๐Ÿซง
  • Common interoperability issues and possible workarounds are described in Appendix A ๐Ÿ“–

5. Internationalization Considerations ๐ŸŒˆ

TZif time zone designations contain only ASCII alphanumerics, "-", and "+". Commonly used designations include numeric strings like "-10" and "+0530" for UT offsets, plus English language abbreviations like "CEST" for Central European Summer Time and "GMT" for Greenwich Mean Time ๐Ÿ‡ฌ๐Ÿ‡ง It's the TZif reader's job to swap in different abbreviations when needed for internationalization, like substituting "HNC" (l'heure normale du Centre) for "CST" (Central Standard Time) in French-speaking regions ๐Ÿฅ– This substitution can get messy, though, because abbreviations can be ambiguous. For example, "CST" commonly stands for China Standard Time and Cuba Standard Time as well as Central Standard Time ๐Ÿ˜ตโ€๐Ÿ’ซ One approach to this issue can be found in the time zone charts of the Unicode Common Locale Data Repository (CLDR) Project [CLDR] ๐Ÿ—บ๏ธ

the original TZif design allowed any nonzero octets in time zone designations, and it was common practice until the mid-1990s for designations to contain ASCII spaces. Designations are now limited to ASCII alphanumerics, "-", and "+" to avoid confusion and to make things more portable across a wide variety of locales ๐ŸŒธ


6. Use with the Time Zone Data Distribution Service ๐Ÿงš

The Time Zone Data Distribution Service (TZDIST) [RFC7808] is a service that delivers time zone data and leap-second rules to client systems, like calendaring and scheduling apps or operating systems, reliably, securely, and fast ๐Ÿš€

a TZDIST service MAY supply time zone data to clients in the Time Zone Information Format. If it does, it MUST indicate that it supports this format by including the media type "application/tzif" (Section 9.1) in its "capabilities" response (Section 5.1 of [RFC7808]). A TZDIST service MAY also include the media type "application/tzif-leap" (Section 9.2) in its "capabilities" response if it can generate TZif files containing leap-second records. A TZDIST service MUST NOT advertise the "application/tzif-leap" media type without also advertising "application/tzif" ๐Ÿ™…โ€โ™€๏ธ

TZDIST clients MUST use the HTTP Accept header field ([RFC9110], Section 12.5.1) to say which formats they'd prefer to receive data in: "application/tzif" and/or "application/tzif-leap" ๐Ÿ’Œ

6.1. Truncating TZif Files โœ‚๏ธ

As described in Section 3.9 of [RFC7808], a TZDIST service MAY truncate time zone transition data. A truncated TZif file is valid from its first transition time up to, but not including, its last version 2+ transition time, if one is present ๐Ÿซถ

when truncating the start of a TZif file, the service MUST supply in the version 2+ data a first transition time that is the start point of the truncation range. Just like untruncated TZif files, time type 0 indicates local time immediately before the start point, and the time type of the first transition indicates local time after that. Time type 0 MUST be a placeholder indicating that local time is unspecified, so the reader knows for sure that truncation happened at the start ๐Ÿซฃ

when truncating the start of a TZif file containing leap-second records, the service MUST keep all leap-second records that govern timestamps within the truncation range, even if the first such record comes before the start point of the truncation range. If the truncated leap-second table is non-empty, its first record MUST have a positive correction if and only if it represents a positive leap second โญ

when truncating the end of a TZif file, the service MUST supply in the version 2+ data a last transition time that is the end point of the truncation range, and MUST supply an empty TZ string. Like untruncated TZif files with empty TZ strings, a truncated TZif file doesn't indicate local time after the last transition. So the time type of the last transition MUST be a placeholder indicating that local time is unspecified ๐Ÿฅ€

all represented information that falls inside the truncation range MUST be the same as the information represented by a corresponding untruncated TZif file. Super important, bestie ๐Ÿ’–

TZDIST clients SHOULD NOT use a truncated TZif file (as described above) to interpret timestamps outside the truncation time range ๐Ÿšซโœจ

6.2. Example TZDIST Request for TZif Data ๐ŸŽ€

okay so this example is giving "client meets server" ๐Ÿ’– The client first asks the server what formats it supports, then asks for one specific time zone identifier and gets it back as TZif. ๐Ÿฆ‹

This example presumes that the time zone context path has been discovered (see [RFC7808], Section 4.2.1) to be /tzdist. ๐Ÿงš

Request <<
GET /tzdist/capabilities HTTP/1.1
Host: tz.example.com
Response <<
HTTP/1.1 200 OK
Date: Fri, 01 Jun 2018 14:52:23 GMT
Content-Type: application/json
Content-Length: xxxx

{
  "version": 1,

  "info": {
    "primary-source": "IANA:2018e",
    "formats": [
      "text/calendar",
      "application/tzif",
      "application/tzif-leap"
    ],
...
  },
...
}
Request <<
GET /tzdist/zones/America%2FNew_York HTTP/1.1
Host: tz.example.com
Accept: application/tzif
Response <<
HTTP/1.1 200 OK
Date: Fri, 01 Jun 2018 14:52:24 GMT
Content-Type: application/tzif
Content-Length: xxxx
ETag: "123456789-000-111"

TZif2...[binary data without leap-second records]...
EST5EDT,M3.2.0,M11.1.0

7. Security Considerations ๐Ÿ”

okay the security part is SERIOUS and I'm not playing ๐Ÿ˜ญ TZif has no executable code, and it doesn't define any extensible areas where code could hide. Very safe, very cute. ๐Ÿ’…

TZif uses counted arrays of data elements. All counts should be checked when processing TZif objects, so nobody reads past the end of the object. ๐Ÿšจ Please count your arrays, bestie. ๐Ÿ’€

TZif provides no confidentiality or integrity protection. Time zone information is normally public, so it doesn't really need confidentiality. But time zone info runs lots of critical apps, so integrity protection may be required, and it must be provided externally. ๐Ÿ›ก๏ธ

As discussed in Section 8 of [RFC7808], sending time zone data over an insecure channel could get it tampered with, and that would mess up calendaring and scheduling. ๐Ÿ˜ฑ So TZif data sent over a public communications channel MUST be protected with a security layer, like the one Transport Layer Security (TLS) [RFC8446] gives you. ๐Ÿ”’ No shortcuts, periodt. ๐Ÿ’œ

8. Privacy Considerations ๐Ÿ™ˆ

TZif contains publicly available data, and it doesn't define any extensible areas that could be used to store private data. โœจ

As discussed in Section 9 of [RFC7808], sending time zone data over an insecure communications channel could leak the past, current, or future location of a device or user. ๐ŸŒ Yikes. So TZif data sent over a public communications channel MUST be protected with a confidentiality layer, like the one Transport Layer Security (TLS) [RFC8446] provides. ๐Ÿซถ

9. IANA Considerations ๐ŸŒธ

IANA has updated the "Media Types" registry (https://www.iana.org/assignments/media-types) as follows. ๐Ÿ“

This document defines two media types [RFC6838] for exchanging data with the Time Zone Information Format. ๐Ÿฆ‹

9.1. application/tzif ๐Ÿ“

Here's the registration template for application/tzif, copied exactly:

Type name:  application

Subtype name:  tzif

Required parameters:  N/A

Optional parameters:  N/A

Encoding considerations:  binary

Security considerations:  See Section 7 of RFC 9636.

Interoperability considerations:  See Section 4 of RFC 9636.

Published specification:  RFC 9636.

Applications that use this media type:  This media type is designed
   for widespread use by applications that need to use or exchange
   time zone information relative to UNIX time, such as the Time Zone
   Information Compiler (zic) [ZIC] and the GNU C Library [GNU-C].
   The Time Zone Distribution Service [RFC7808] can directly use this
   media type.

Fragment identifier considerations:  N/A

Additional information:

   Magic number(s):  The first 4 octets are 0x54, 0x5A, 0x69, 0x66
   File extensions(s):  N/A
   Macintosh file type code(s):  N/A

Person & email address to contact for further information:  Time Zone
   Database mailing list <tz@iana.org>

Intended usage:  COMMON

Restrictions on usage:  N/A

Author:  See the "Authors' Addresses" section of RFC 9636.

Change controller:  IETF

9.2. application/tzif-leap ๐ŸŒˆ

Same vibe, but this one is for the leap-time version. Here's the template, verbatim:

Type name:  application

Subtype name:  tzif-leap

Required parameters:  none

Optional parameters:  none

Encoding considerations:  binary

Security considerations:  See Section 7 of RFC 9636.

Interoperability considerations:  See Section 4 of RFC 9636.

Published specification:  RFC 9636.

Applications that use this media type:  This media type is designed
   for widespread use by applications that need to use or exchange
   time zone information relative to UNIX leap time, such as the Time
   Zone Information Compiler (zic) [ZIC] and the GNU C Library
   [GNU-C].  The Time Zone Distribution Service [RFC7808] can
   directly use this media type.

Fragment identifier considerations:  N/A

Additional information:

   Magic number(s):  The first 4 octets are 0x54, 0x5A, 0x69, 0x66
   File extensions(s):  N/A
   Macintosh file type code(s):  N/A

Person & email address to contact for further information:  Time Zone
   Database mailing list <tz@iana.org>

Intended usage:  COMMON

Restrictions on usage:  N/A

Author:  See the "Authors' Addresses" section of RFC 9636.

Change controller:  IETF

10. References ๐Ÿ“š

10.1. Normative References ๐Ÿ’Ž

These are the must-read ones, the foundations of the whole spec. ๐Ÿง 

[GNU-C]    Free Software Foundation, "The GNU C Library",
           <https://www.gnu.org/software/libc/>.

[ITU-R-TF.460]
           International Telecommunication Union, "Standard-frequency
           and time-signal emissions", ITU-R Recommendation TF.460,
           February 2002, <https://www.itu.int/rec/R-REC-TF.460/en>.

[POSIX]    IEEE, "IEEE Standard for Information Technology--Portable
           Operating System Interface (POSIX(TM)) Base
           Specifications, Issue 7", POSIX.1-2017, IEEE
           Std 1003.1-2017, DOI 10.1109/IEEESTD.2018.8277153, January
           2018, <https://pubs.opengroup.org/onlinepubs/9699919799/>.

[RFC20]    Cerf, V., "ASCII format for network interchange", STD 80,
           RFC 20, DOI 10.17487/RFC0020, October 1969,
           <https://www.rfc-editor.org/info/rfc20>.

[RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
           Requirement Levels", BCP 14, RFC 2119,
           DOI 10.17487/RFC2119, March 1997,
           <https://www.rfc-editor.org/info/rfc2119>.

[RFC6838]  Freed, N., Klensin, J., and T. Hansen, "Media Type
           Specifications and Registration Procedures", BCP 13,
           RFC 6838, DOI 10.17487/RFC6838, January 2013,
           <https://www.rfc-editor.org/info/rfc6838>.

[RFC7808]  Douglass, M. and C. Daboo, "Time Zone Data Distribution
           Service", RFC 7808, DOI 10.17487/RFC7808, March 2016,
           <https://www.rfc-editor.org/info/rfc7808>.

[RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
           2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
           May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[RFC9110]  Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke,
           Ed., "HTTP Semantics", STD 97, RFC 9110,
           DOI 10.17487/RFC9110, June 2022,
           <https://www.rfc-editor.org/info/rfc9110>.

[ZIC]      Kerrisk, M., "zic(8) - Linux manual page",
           <http://man7.org/linux/man-pages/man8/zic.8.html>.

10.2. Informative References ๐Ÿ”

These are the nice-to-know extras that give helpful background. โœจ

[CGPM-2022-R4]
           General Conference on Weights and Measures, "Resolution 4
           of the 27th CGPM (2022)", DOI 10.59161/CGPM2022RES4E,
           November 2022,
           <https://www.bipm.org/en/cgpm-2022/resolution-4>.

[CLDR]     Unicode, Inc., "Unicode CLDR Project",
           <https://cldr.unicode.org/>.

[EGGERT-TZ]
           "History for tz", commit b5318b5, June 2024,
           <https://github.com/eggert/tz/commits/main/tzfile.5>.

[Err6426]  RFC Errata, "Erratum ID 6426", RFC 8536,
           <https://www.rfc-editor.org/errata/eid6426>.

[Err6435]  RFC Errata, "Erratum ID 6435", RFC 8536,
           <https://www.rfc-editor.org/errata/eid6435>.

[Err6757]  RFC Errata, "Erratum ID 6757", RFC 8536,
           <https://www.rfc-editor.org/errata/eid6757>.

[Err7681]  RFC Errata, "Erratum ID 7681", RFC 8536,
           <https://www.rfc-editor.org/errata/eid7681>.

[RFC5545]  Desruisseaux, B., Ed., "Internet Calendaring and
           Scheduling Core Object Specification (iCalendar)",
           RFC 5545, DOI 10.17487/RFC5545, September 2009,
           <https://www.rfc-editor.org/info/rfc5545>.

[RFC6557]  Lear, E. and P. Eggert, "Procedures for Maintaining the
           Time Zone Database", BCP 175, RFC 6557,
           DOI 10.17487/RFC6557, February 2012,
           <https://www.rfc-editor.org/info/rfc6557>.

[RFC8446]  Rescorla, E., "The Transport Layer Security (TLS) Protocol
           Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018,
           <https://www.rfc-editor.org/info/rfc8446>.

[RFC8536]  Olson, A., Eggert, P., and K. Murchison, "The Time Zone
           Information Format (TZif)", RFC 8536,
           DOI 10.17487/RFC8536, February 2019,
           <https://www.rfc-editor.org/info/rfc8536>.

[tz-link]  Eggert, P. and A. Olson, "Time zone and daylight saving
           time data",
           <https://www.iana.org/time-zones/repository/tz-link.html>.

Appendix A. Common Interoperability Issues โœจ

okay bestie, this section is basically the "things that bit people in the wild" list ๐Ÿ’€ Most of these are problems with writing TZif files for readers that follow older versions of the spec [EGGERT-TZ]. The goals are to help:

  1. TZif writers output files that dodge common pitfalls in older or buggy TZif readers,
  2. TZif readers avoid common pitfalls when reading files from future TZif writers, and
  3. any future spec authors see what kinds of problems pop up when the TZif format changes ๐Ÿ‘€

when new TZif versions got defined, the big design goal was that a reader could still use a file even if it's a later version than the reader was built for ๐Ÿซถ when full compatibility wasn't possible, they tried to keep the glitches to rarely used timestamps and let writers make simple partial workarounds so newer-version data is still useful to older-version readers. this section documents those compatibility issues and workarounds, plus other common reader bugs, so nobody has to rediscover them the hard way ๐Ÿ˜ญ

Here are the interoperability problems with TZif:

  • Some readers only look at version 1 data. As a partial workaround, a writer can output as much version 1 data as possible. However, a reader should ignore version 1 data and use version 2+ data, even if the reader's timestamps have only 32 bits. ๐ŸŒธ
  • Some readers designed for version 2 might mishandle timestamps after a version 3 or higher file's last transition, because they can't parse extensions to POSIX in the TZ-like string. As a partial workaround, a writer can output more transitions than necessary, so that only far-future timestamps get mishandled by version 2 readers. ๐Ÿ”ฎ
  • Some readers designed for version 2 don't support permanent daylight saving time with transitions after 24:00. For example, the TZ string EST5EDT,0/0,J365/25 denotes permanent Eastern Daylight Time (-04), and those readers will choke on it ๐Ÿ’€ As a workaround, a writer can substitute standard time for two time zones east. For instance, XXX3EDT4,0/0,J365/23 covers a time zone with a never-used standard time (XXX, -03) and negative daylight saving time (EDT, -04) all year. Alternatively, as a partial workaround, a writer can substitute standard time for the next time zone east, like AST4 for permanent Atlantic Standard Time (-04). ๐Ÿงš
  • Some readers designed for version 2 or 3 that require strict conformance to [RFC8536] reject version 4 files whose leap-second tables are truncated at the start or end in expiration times. ๐Ÿ™ˆ
  • Some readers ignore the footer and instead predict future timestamps from the time type of the last transition. As a partial workaround, a writer can output more transitions than necessary. ๐Ÿ“
  • Some readers don't use time type 0 for timestamps before the first transition, because they infer a time type with a heuristic that doesn't always pick time type 0. As a partial workaround, a writer can output a placeholder (no-op) first transition at an early time. ๐ŸŽ€
  • Some readers mishandle timestamps before the first transition that has a timestamp that is not less than -2^31. Readers that only support 32-bit timestamps are more likely to have this problem, for example when they process 64-bit transitions, only some of which fit in 32 bits. As a partial workaround, a writer can output a placeholder transition at timestamp -2^31. ๐Ÿ’…
  • Some readers mishandle a transition if its timestamp has the minimum possible signed 64-bit value. Timestamps less than -2^59 are not recommended. โญ
  • Some readers mishandle POSIX-style TZ strings that contain "<" or ">". As a partial workaround, a writer can avoid using "<" or ">" for time zone abbreviations that contain only alphabetic characters. ๐ŸŒˆ
  • Many readers mishandle time zone abbreviations that contain non-ASCII characters. These characters are not recommended. ๐Ÿšซ
  • Some readers may mishandle time zone abbreviations that contain fewer than 3 or more than 6 characters, or that contain ASCII characters other than alphanumerics, "-", and "+". These abbreviations are not recommended. ๐Ÿ™ƒ
  • This specification doesn't dictate how readers should deal with timestamps when local time is unspecified. Common practice is for readers to report UT with designation string "-00". A reader could return an error indication instead. ๐Ÿคทโ€โ™€๏ธ
  • Some readers mishandle TZif files that specify daylight saving time UT offsets that are less than the UT offsets for the corresponding standard time. These readers don't support locations like Ireland, which uses the equivalent of the POSIX TZ string IST-1GMT0,M10.5.0,M3.5.0/1, observing standard time (IST, +01) in summer and daylight saving time (GMT, +00) in winter. As a partial workaround, a writer can output data for the equivalent of the POSIX TZ string GMT0IST,M3.5.0/1,M10.5.0, thus swapping standard and daylight saving time. Although this workaround misidentifies which part of the year uses daylight saving time, it records UT offsets and time zone abbreviations correctly. ๐Ÿ€
  • Some readers generate ambiguous timestamps for positive leap seconds that occur when the UTC offset is not a multiple of 60 seconds. For example, with UTC offset +01:23:45 and a positive leap second 78796801 (1972-06-30 23:59:60 UTC), some readers map both 78796800 and 78796801 to 01:23:45 local time the next day instead of mapping the latter to 01:23:46. They also map 78796815 to 01:23:59 instead of to 01:23:60. This hasn't been a practical problem yet, since no civil authority has observed such UTC offsets since leap seconds were introduced in 1972. ๐Ÿ•ฐ๏ธ

Some interoperability problems are reader bugs. They're listed here mostly as warnings to reader developers ๐Ÿ“ฃ

  • Some readers don't support negative timestamps. Developers of distributed applications should keep this in mind if they need to deal with pre-1970 data. ๐Ÿ•ฐ๏ธ
  • Some readers mishandle timestamps before the first transition that has a non-negative timestamp. Readers that don't support negative timestamps are more likely to have this problem. ๐Ÿ˜ฌ
  • Some readers mishandle time zone abbreviations like "-08" that contain "+", "-", or digits. ๐Ÿ™ˆ
  • Some readers mishandle UT offsets that are outside the conventional range of -12 through +12 hours, and so don't support locations like Kiritimati that sit outside this range. ๐Ÿ๏ธ
  • Some readers mishandle UT offsets in the range [-3599, -1] seconds from UT, because they integer-divide the offset by 3600 to get 0 and then display the hour part as "+00". ๐Ÿ’€
  • Some readers mishandle UT offsets that aren't a multiple of one hour, 15 minutes, or 1 minute. ๐Ÿซ 

Appendix B. Example TZif Files ๐Ÿฆ‹

The following sections contain annotated hexadecimal dumps of example TZif files.

These examples should only be considered informative. Although the example data entries are current as of the publication date of this document, the data will likely change in the future as leap seconds are added and changes are made to civil time. ๐Ÿ’œ

B.1. Version 1 File Representing UTC (with Leap Seconds) ๐ŸŒธ

Okay bestie, the leap-second parade keeps going ๐ŸŽ€โœจ

   +========+=============+==================+========================+
   | File   | Hexadecimal | Record Name /    | Field Value            |
   | Offset | Octets      | Field Name       |                        |
   +========+=============+==================+========================+
   | 000    | 54 5a 69 66 | magic            | "TZif"                 |
   +--------+-------------+------------------+------------------------+
   | 004    | 00          | version          | 0 (1)                  |
   +--------+-------------+------------------+------------------------+
   | 005    | 00 00 00 00 |                                           |
   |        | 00 00 00 00 |                                           |
   |        | 00 00 00 00 |                                           |
   |        | 00 00 00    |                                           |
   +--------+-------------+------------------+------------------------+
   | 020    | 00 00 00 01 | isutcnt          | 1                      |
   +--------+-------------+------------------+------------------------+
   | 024    | 00 00 00 01 | isstdcnt         | 1                      |
   +--------+-------------+------------------+------------------------+
   | 028    | 00 00 00 1b | leapcnt          | 27                     |
   +--------+-------------+------------------+------------------------+
   | 032    | 00 00 00 00 | timecnt          | 0                      |
   +--------+-------------+------------------+------------------------+
   | 036    | 00 00 00 01 | typecnt          | 1                      |
   +--------+-------------+------------------+------------------------+
   | 040    | 00 00 00 04 | charcnt          | 4                      |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | localtimetype[0] |                        |
   +--------+-------------+------------------+------------------------+
   | 044    | 00 00 00 00 | utoff            | 0 (+00:00)             |
   +--------+-------------+------------------+------------------------+
   | 048    | 00          | isdst            | 0 (no)                 |
   +--------+-------------+------------------+------------------------+
   | 049    | 00          | desigidx         | 0                      |
   +--------+-------------+------------------+------------------------+
   +--------+-------------+------------------+------------------------+
   | 050    | 55 54 43 00 | designations[0]  | "UTC\0"                |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | leapsecond[0]    |                        |
   +--------+-------------+------------------+------------------------+
   | 054    | 04 b2 58 00 | occurrence       | 78796800               |
   |        |             |                  | (1972-06-30T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 058    | 00 00 00 01 | correction       | 1                      |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | leapsecond[1]    |                        |
   +--------+-------------+------------------+------------------------+
   | 062    | 05 a4 ec 01 | occurrence       | 94694401               |
   |        |             |                  | (1972-12-31T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 066    | 00 00 00 02 | correction       | 2                      |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | leapsecond[2]    |                        |
   +--------+-------------+------------------+------------------------+
   | 070    | 07 86 1f 82 | occurrence       | 126230402              |
   |        |             |                  | (1973-12-31T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 074    | 00 00 00 03 | correction       | 3                      |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | leapsecond[3]    |                        |
   +--------+-------------+------------------+------------------------+
   | 078    | 09 67 53 03 | occurrence       | 157766403              |
   |        |             |                  | (1974-12-31T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 082    | 00 00 00 04 | correction       | 4                      |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | leapsecond[4]    |                        |
   +--------+-------------+------------------+------------------------+
   | 086    | 0b 48 86 84 | occurrence       | 189302404              |
   |        |             |                  | (1975-12-31T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 090    | 00 00 00 05 | correction       | 5                      |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | leapsecond[5]    |                        |
   +--------+-------------+------------------+------------------------+
   | 094    | 0d 2b 0b 85 | occurrence       | 220924805              |
   |        |             |                  | (1976-12-31T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 098    | 00 00 00 06 | correction       | 6                      |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | leapsecond[6]    |                        |
   +--------+-------------+------------------+------------------------+
   | 102    | 0f 0c 3f 06 | occurrence       | 252460806              |
   |        |             |                  | (1977-12-31T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 106    | 00 00 00 07 | correction       | 7                      |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | leapsecond[7]    |                        |
   +--------+-------------+------------------+------------------------+
   | 110    | 10 ed 72 87 | occurrence       | 283996807              |
   |        |             |                  | (1978-12-31T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 114    | 00 00 00 08 | correction       | 8                      |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | leapsecond[8]    |                        |
   +--------+-------------+------------------+------------------------+
   | 118    | 12 ce a6 08 | occurrence       | 315532808              |
   |        |             |                  | (1979-12-31T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 122    | 00 00 00 09 | correction       | 9                      |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | leapsecond[9]    |                        |
   +--------+-------------+------------------+------------------------+
   | 126    | 15 9f ca 89 | occurrence       | 362793609              |
   |        |             |                  | (1981-06-30T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 130    | 00 00 00 0a | correction       | 10                     |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | leapsecond[10]   |                        |
   +--------+-------------+------------------+------------------------+
   | 134    | 17 80 fe 0a | occurrence       | 394329610              |
   |        |             |                  | (1982-06-30T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 138    | 00 00 00 0b | correction       | 11                     |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | leapsecond[11]   |                        |
   +--------+-------------+------------------+------------------------+
   | 142    | 19 62 31 8b | occurrence       | 425865611              |
   |        |             |                  | (1983-06-30T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 146    | 00 00 00 0c | correction       | 12                     |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | leapsecond[12]   |                        |
   +--------+-------------+------------------+------------------------+
   | 150    | 1d 25 ea 0c | occurrence       | 489024012              |
   |        |             |                  | (1985-06-30T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 154    | 00 00 00 0d | correction       | 13                     |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | leapsecond[13]   |                        |
   +--------+-------------+------------------+------------------------+
   | 158    | 21 da e5 0d | occurrence       | 567993613              |
   |        |             |                  | (1987-12-31T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 162    | 00 00 00 0e | correction       | 14                     |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | leapsecond[14]   |                        |
   +--------+-------------+------------------+------------------------+
   | 166    | 25 9e 9d 8e | occurrence       | 631152014              |
   |        |             |                  | (1989-12-31T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 170    | 00 00 00 0f | correction       | 15                     |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | leapsecond[15]   |                        |
   +--------+-------------+------------------+------------------------+
   | 174    | 27 7f d1 0f | occurrence       | 662688015              |
   |        |             |                  | (1990-12-31T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 178    | 00 00 00 10 | correction       | 16                     |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+

Okay bestie, the table keeps going with more leap-second rows, so let's look at how the big table ends ๐Ÿฆ‹โœจ

   |                      | leapsecond[16]   |                        |
   +--------+-------------+------------------+------------------------+
   | 182    | 2a 50 f5 90 | occurrence       | 709948816              |
   |        |             |                  | (1992-06-30T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 186    | 00 00 00 11 | correction       | 17                     |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | leapsecond[17]   |                        |
   +--------+-------------+------------------+------------------------+
   | 190    | 2c 32 29 11 | occurrence       | 741484817              |
   |        |             |                  | (1993-06-30T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 194    | 00 00 00 12 | correction       | 18                     |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | leapsecond[18]   |                        |
   +--------+-------------+------------------+------------------------+
   | 198    | 2e 13 5c 92 | occurrence       | 773020818              |
   |        |             |                  | (1994-06-30T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 202    | 00 00 00 13 | correction       | 19                     |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | leapsecond[19]   |                        |
   +--------+-------------+------------------+------------------------+
   | 206    | 30 e7 24 13 | occurrence       | 820454419              |
   |        |             |                  | (1995-12-31T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 210    | 00 00 00 14 | correction       | 20                     |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | leapsecond[20]   |                        |
   +--------+-------------+------------------+------------------------+
   | 214    | 33 b8 48 94 | occurrence       | 867715220              |
   |        |             |                  | (1997-06-30T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 218    | 00 00 00 15 | correction       | 21                     |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | leapsecond[21]   |                        |
   +--------+-------------+------------------+------------------------+
   | 222    | 36 8c 10 15 | occurrence       | 915148821              |
   |        |             |                  | (1998-12-31T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 226    | 00 00 00 16 | correction       | 22                     |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | leapsecond[22]   |                        |
   +--------+-------------+------------------+------------------------+
   | 230    | 43 b7 1b 96 | occurrence       | 1136073622             |
   |        |             |                  | (2005-12-31T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 234    | 00 00 00 17 | correction       | 23                     |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | leapsecond[23]   |                        |
   +--------+-------------+------------------+------------------------+
   | 238    | 49 5c 07 97 | occurrence       | 1230768023             |
   |        |             |                  | (2008-12-31T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 242    | 00 00 00 18 | correction       | 24                     |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | leapsecond[24]   |                        |
   +--------+-------------+------------------+------------------------+
   | 246    | 4f ef 93 18 | occurrence       | 1341100824             |
   |        |             |                  | (2012-06-30T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 250    | 00 00 00 19 | correction       | 25                     |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | leapsecond[25]   |                        |
   +--------+-------------+------------------+------------------------+
   | 254    | 55 93 2d 99 | occurrence       | 1435708825             |
   |        |             |                  | (2015-06-30T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 258    | 00 00 00 1a | correction       | 26                     |
   +--------+-------------+------------------+------------------------+
   +----------------------+------------------+------------------------+
   |                      | leapsecond[26]   |                        |
   +--------+-------------+------------------+------------------------+
   | 262    | 58 68 46 9a | occurrence       | 1483228826             |
   |        |             |                  | (2016-12-31T23:59:60Z) |
   +--------+-------------+------------------+------------------------+
   | 266    | 00 00 00 1b | correction       | 27                     |
   +--------+-------------+------------------+------------------------+
   +--------+-------------+------------------+------------------------+
   | 270    | 00          | standard/wall[0] | 0 (wall)               |
   +--------+-------------+------------------+------------------------+
   +--------+-------------+------------------+------------------------+
   | 271    | 00          | UT/local[0]      | 0 (local)              |
   +--------+-------------+------------------+------------------------+

                                 Table 1

Now the fun part, the little procedure to figure out TAI ๐Ÿ’… To find TAI for 2000-01-01T00:00:00Z (946684800 in UNIX time), you do this:

  1. Find the latest leap-second occurrence before your time of interest, which is leapsecond[21], and jot down its correction value, LEAPCORR = 22 ๐ŸŽ€
  2. Add LEAPCORR + 10 to your time of interest and boom, you get TAI of 2000-01-01T00:00:32 ๐ŸŒธ

B.2. Version 2 File Representing Pacific/Honolulu ๐ŸŒบ

+========+=============+==================+========================+

FileHexadecimalRecord Name /Field Value
OffsetOctetsField Name

+========+=============+==================+========================+

00054 5a 69 66magic"TZif"

+--------+-------------+------------------+------------------------+

00432version'2' (2)

+--------+-------------+------------------+------------------------+

00500 00 00 00
00 00 00 00
00 00 00 00
00 00 00

+--------+-------------+------------------+------------------------+

02000 00 00 06isutcnt6

+--------+-------------+------------------+------------------------+

02400 00 00 06isstdcnt6

+--------+-------------+------------------+------------------------+

02800 00 00 00leapcnt0

+--------+-------------+------------------+------------------------+

03200 00 00 07timecnt7

+--------+-------------+------------------+------------------------+

03600 00 00 06typecnt6

+--------+-------------+------------------+------------------------+

04000 00 00 14charcnt20

+--------+-------------+------------------+------------------------+ +--------+-------------+------------------+------------------------+

04480 00 00 00trans time[0]-2147483648
(1901-12-13T20:45:52Z)

+--------+-------------+------------------+------------------------+

048bb 05 43 48trans time[1]-1157283000
(1933-04-30T12:30:00Z)

+--------+-------------+------------------+------------------------+

052bb 21 71 58trans time[2]-1155436200
(1933-05-21T21:30:00Z)

+--------+-------------+------------------+------------------------+

056cb 89 3d c8trans time[3]-880198200
(1942-02-09T12:30:00Z)

+--------+-------------+------------------+------------------------+

060d2 23 f4 70trans time[4]-769395600
(1945-08-14T23:00:00Z)

+--------+-------------+------------------+------------------------+

064d2 61 49 38trans time[5]-765376200
(1945-09-30T11:30:00Z)

+--------+-------------+------------------+------------------------+

068d5 8d 73 48trans time[6]-712150200
(1947-06-08T12:30:00Z)

+--------+-------------+------------------+------------------------+ +--------+-------------+------------------+------------------------+

07201trans type[0]1

+--------+-------------+------------------+------------------------+

07302trans type[1]2

+--------+-------------+------------------+------------------------+

07401trans type[2]1

+--------+-------------+------------------+------------------------+

07503trans type[3]3

+--------+-------------+------------------+------------------------+

07604trans type[4]4

+--------+-------------+------------------+------------------------+

07701trans type[5]1

+--------+-------------+------------------+------------------------+

07805trans type[6]5

+--------+-------------+------------------+------------------------+ +----------------------+------------------+------------------------+

localtimetype[0]

+--------+-------------+------------------+------------------------+

079ff ff 6c 02utoff-37886 (-10:31:26)

+--------+-------------+------------------+------------------------+

08300isdst0 (no)

+--------+-------------+------------------+------------------------+

08400desigidx0

+--------+-------------+------------------+------------------------+ +----------------------+------------------+------------------------+

localtimetype[1]

+--------+-------------+------------------+------------------------+

085ff ff 6c 58utoff-37800 (-10:30)

+--------+-------------+------------------+------------------------+

08900isdst0 (no)

+--------+-------------+------------------+------------------------+

09004desigidx4

+--------+-------------+------------------+------------------------+ +----------------------+------------------+------------------------+

localtimetype[2]

+--------+-------------+------------------+------------------------+

091ff ff 7a 68utoff-34200 (-09:30)

+--------+-------------+------------------+------------------------+

09501isdst1 (yes)

+--------+-------------+------------------+------------------------+

09608desigidx8

+--------+-------------+------------------+------------------------+ +----------------------+------------------+------------------------+

localtimetype[3]

+--------+-------------+------------------+------------------------+

097ff ff 7a 68utoff-34200 (-09:30)

+--------+-------------+------------------+------------------------+

10101isdst1 (yes)

+--------+-------------+------------------+------------------------+

1020cdesigidx12

+--------+-------------+------------------+------------------------+ +----------------------+------------------+------------------------+

localtimetype[4]

+--------+-------------+------------------+------------------------+

103ff ff 7a 68utoff-34200 (-09:30)

+--------+-------------+------------------+------------------------+

10701isdst1 (yes)

+--------+-------------+------------------+------------------------+

10810desigidx16

+--------+-------------+------------------+------------------------+ +----------------------+------------------+------------------------+

localtimetype[5]

+--------+-------------+------------------+------------------------+

109ff ff 73 60utoff-36000 (-10:00)

+--------+-------------+------------------+------------------------+

11300isdst0 (no)

+--------+-------------+------------------+------------------------+

11404desigidx4

+--------+-------------+------------------+------------------------+ +--------+-------------+------------------+------------------------+

1154c 4d 54 00designations[0]"LMT\0"

+--------+-------------+------------------+------------------------+

11948 53 54 00designations[4]"HST\0"

+--------+-------------+------------------+------------------------+

12348 44 54 00designations[8]"HDT\0"

+--------+-------------+------------------+------------------------+

12748 57 54 00designations[12]"HWT\0"

+--------+-------------+------------------+------------------------+

13148 50 54 00designations[16]"HPT\0"

+--------+-------------+------------------+------------------------+ +--------+-------------+------------------+------------------------+

13500standard/wall[0]0 (wall)

+--------+-------------+------------------+------------------------+

13600standard/wall[1]0 (wall)

+--------+-------------+------------------+------------------------+

13700standard/wall[2]0 (wall)

+--------+-------------+------------------+------------------------+

13800standard/wall[3]0 (wall)

+--------+-------------+------------------+------------------------+

13901standard/wall[4]1 (standard)

+--------+-------------+------------------+------------------------+

14000standard/wall[5]0 (wall)

+--------+-------------+------------------+------------------------+ +--------+-------------+------------------+------------------------+

14100UT/local[0]0 (local)

+--------+-------------+------------------+------------------------+

14200UT/local[1]0 (local)

+--------+-------------+------------------+------------------------+

14300UT/local[2]0 (local)

+--------+-------------+------------------+------------------------+

14400UT/local[3]0 (local)

+--------+-------------+------------------+------------------------+

14501UT/local[4]1 (UT)

+--------+-------------+------------------+------------------------+

14600UT/local[5]0 (local)

+--------+-------------+------------------+------------------------+ +--------+-------------+------------------+------------------------+

14754 5a 69 66magic"TZif"

+--------+-------------+------------------+------------------------+

15132version'2' (2)

+--------+-------------+------------------+------------------------+

15200 00 00 00
00 00 00 00
00 00 00 00
00 00 00

+--------+-------------+------------------+------------------------+

16700 00 00 06isutcnt6

+--------+-------------+------------------+------------------------+

17100 00 00 06isstdcnt6

+--------+-------------+------------------+------------------------+

17500 00 00 00leapcnt0

+--------+-------------+------------------+------------------------+

17900 00 00 07timecnt7

+--------+-------------+------------------+------------------------+

18300 00 00 06typecnt6

+--------+-------------+------------------+------------------------+

18700 00 00 14charcnt20

+--------+-------------+------------------+------------------------+ +--------+-------------+------------------+------------------------+

191ff ff ff fftrans time[0]-2334101314
74 e0 70 be(1896-01-13T22:31:26Z)

+--------+-------------+------------------+------------------------+

199ff ff ff fftrans time[1]-1157283000
bb 05 43 48(1933-04-30T12:30:00Z)

+--------+-------------+------------------+------------------------+

207ff ff ff fftrans time[2]-1155436200
bb 21 71 58(1933-05-21T21:30:00Z)

+--------+-------------+------------------+------------------------+

215ff ff ff fftrans time[3]-880198200
cb 89 3d c8(1942-02-09T12:30:00Z)

+--------+-------------+------------------+------------------------+

223ff ff ff fftrans time[4]-769395600
d2 23 f4 70(1945-08-14T23:00:00Z)

+--------+-------------+------------------+------------------------+

231ff ff ff fftrans time[5]-765376200
d2 61 49 38(1945-09-30T11:30:00Z)

+--------+-------------+------------------+------------------------+

239ff ff ff fftrans time[6]-712150200
d5 8d 73 48(1947-06-08T12:30:00Z)

+--------+-------------+------------------+------------------------+ +--------+-------------+------------------+------------------------+

24701trans type[0]1

+--------+-------------+------------------+------------------------+

24802trans type[1]2

+--------+-------------+------------------+------------------------+

24901trans type[2]1

+--------+-------------+------------------+------------------------+

25003trans type[3]3

+--------+-------------+------------------+------------------------+

25104trans type[4]4

+--------+-------------+------------------+------------------------+

25201trans type[5]1

+--------+-------------+------------------+------------------------+

25305trans type[6]5

+--------+-------------+------------------+------------------------+ +----------------------+------------------+------------------------+

localtimetype[0]

+--------+-------------+------------------+------------------------+

254ff ff 6c 02utoff-37886 (-10:31:26)

+--------+-------------+------------------+------------------------+

25800isdst0 (no)

+--------+-------------+------------------+------------------------+

25900desigidx0

+--------+-------------+------------------+------------------------+ +----------------------+------------------+------------------------+

localtimetype[1]

+--------+-------------+------------------+------------------------+

260ff ff 6c 58utoff-37800 (-10:30)

+--------+-------------+------------------+------------------------+

26400isdst0 (no)

+--------+-------------+------------------+------------------------+

26504desigidx4

+--------+-------------+------------------+------------------------+ +----------------------+------------------+------------------------+

localtimetype[2]

+--------+-------------+------------------+------------------------+

266ff ff 7a 68utoff-34200 (-09:30)

+--------+-------------+------------------+------------------------+

27001isdst1 (yes)

+--------+-------------+------------------+------------------------+

27108desigidx8

+--------+-------------+------------------+------------------------+ +----------------------+------------------+------------------------+

localtimetype[3]

+--------+-------------+------------------+------------------------+

272ff ff 7a 68utoff-34200 (-09:30)

+--------+-------------+------------------+------------------------+

27601isdst1 (yes)

+--------+-------------+------------------+------------------------+

2770cdesigidx12

+--------+-------------+------------------+------------------------+ +----------------------+------------------+------------------------+

localtimetype[4]

+--------+-------------+------------------+------------------------+

278ff ff 7a 68utoff-34200 (-09:30)

+--------+-------------+------------------+------------------------+

28201isdst1 (yes)

+--------+-------------+------------------+------------------------+

28310desigidx16

+--------+-------------+------------------+------------------------+ +----------------------+------------------+------------------------+

localtimetype[5]

+--------+-------------+------------------+------------------------+

284ff ff 73 60utoff-36000 (-10:00)

+--------+-------------+------------------+------------------------+

28800isdst0 (no)

+--------+-------------+------------------+------------------------+

28904desigidx4

+--------+-------------+------------------+------------------------+ +--------+-------------+------------------+------------------------+

2904c 4d 54 00designations[0]"LMT\0"

+--------+-------------+------------------+------------------------+

29448 53 54 00designations[4]"HST\0"

+--------+-------------+------------------+------------------------+

29848 44 54 00designations[8]"HDT\0"

+--------+-------------+------------------+------------------------+

30248 57 54 00designations[12]"HWT\0"

+--------+-------------+------------------+------------------------+

30648 50 54 00designations[16]"HPT\0"

+--------+-------------+------------------+------------------------+ +--------+-------------+------------------+------------------------+

31000standard/wall[0]0 (wall)

+--------+-------------+------------------+------------------------+

31100standard/wall[1]0 (wall)

+--------+-------------+------------------+------------------------+

31200standard/wall[2]0 (wall)

+--------+-------------+------------------+------------------------+

31300standard/wall[3]0 (wall)

+--------+-------------+------------------+------------------------+

31401standard/wall[4]1 (standard)

+--------+-------------+------------------+------------------------+

31500standard/wall[5]0 (wall)

+--------+-------------+------------------+------------------------+ +--------+-------------+------------------+------------------------+

31600UT/local[0]0 (local)

+--------+-------------+------------------+------------------------+

31700UT/local[1]0 (local)

+--------+-------------+------------------+------------------------+

31800UT/local[2]0 (local)

+--------+-------------+------------------+------------------------+

31900UT/local[3]0 (local)

+--------+-------------+------------------+------------------------+

32001UT/local[4]1 (UT)

+--------+-------------+------------------+------------------------+

32100UT/local[5]0 (local)

+--------+-------------+------------------+------------------------+ +--------+-------------+------------------+------------------------+

3220aNL'\n'

+--------+-------------+------------------+------------------------+

32348 53 54 31TZ string"HST10"
30

+--------+-------------+------------------+------------------------+

3280aNL'\n'

+--------+-------------+------------------+------------------------+

Table 2

Okay bestie, let's decode this file together ๐Ÿซถ Say we want the local time in this zone at 1933-05-04T12:00:00Z (UNIX time = -1156939200). Here's the move:

  1. Find the latest time transition before our time of interest. That's trans time[1] โฐ
  2. Check the matching transition type, trans type[1], to get the local time type index, which is 2 ๐Ÿ’œ
  3. Peek at localtimetype[2] to grab the UTC offset (-09:30), the daylight saving flag (1 = yes), and the index into the time zone designation strings (8) โœจ
  4. Look up designations[8] and you get "HDT" ๐ŸŒบ
  5. Add the UTC offset to our time of interest and boom, you get a local daylight saving time of 1933-05-04T02:30:00-09:30 (HDT) ๐ŸŽ€

Now for the second one, the local time at 2019-01-01T00:00:00Z (UNIX time = 1546300800):

  1. Find the latest transition before it. There isn't one, bestie ๐Ÿ™ˆ
  2. Read the TZ string in the footer, "HST10". That tells us the designation is "HST" year-round and the offset to UTC is 10:00 ๐Ÿ“
  3. Subtract the UTC offset to get a standard local time of 2018-12-31T14:00:00-10:00 (HST) ๐Ÿ’–

B.3. Truncated Version 2 File Representing Pacific/Johnston โœจ

The example file ends on 2004-06-161T00:00:00Z, which is the exact timestamp in the spec, typo and all ๐Ÿซถ. The atoll was abandoned sometime on 2004-06-15, so this file is basically a little time capsule ๐Ÿ๏ธ๐Ÿ’€ literally a ghost island in file form ๐Ÿงš

Here's what's cute about this one:

  • The version 1 header is giving minimum-viable ๐Ÿฅบ It only has the required minimum data, and readers are going to ignore it anyway. Main character energy? Not really, but it does its job ๐Ÿ’…
  • The version 2 header is the real star โœจ By setting isutcnt and isstdcnt to zero, all the transition times that belong to local time types are assumed to be local wall-clock time. It's the kind of trick that's iconic once you get it ๐Ÿ˜ญ (If you want the full details on the UT/local and standard/wall indicators, check out Section 3.2 ๐Ÿฆ‹)
  • The time type of the last transition is labeled "-00", which means local time is unspecified ๐ŸŒธ It's giving "we don't know and we're not pretending to" ๐Ÿ™ˆ
  • The TZ string is empty, so there are no known future transitions. The file is done, nothing else is coming, and honestly that's very on-brand for a tiny abandoned atoll ๐Ÿ๏ธ๐Ÿซ 

Truncation arc complete!! ๐ŸŒˆ

okay bestie, this is the last stretch of the truncated Pacific/Johnston file, and the table is literally giving ๐Ÿงš๐Ÿ’… every byte gets its own row, so no vibes-only guessing ๐Ÿซถ

+========+=============+==================+========================+
| File   | Hexadecimal | Record Name /    | Field Value            |
| Offset | Octets      | Field Name       |                        |
+========+=============+==================+========================+
| 000    | 54 5a 69 66 | magic            | "TZif"                 |
+--------+-------------+------------------+------------------------+
| 004    | 32          | version          | '2' (2)                |
+--------+-------------+------------------+------------------------+
| 005    | 00 00 00 00 |                  |                        |
|        | 00 00 00 00 |                  |                        |
|        | 00 00 00 00 |                  |                        |
|        | 00 00 00    |                  |                        |
+--------+-------------+------------------+------------------------+
| 020    | 00 00 00 00 | isutcnt          | 0                      |
+--------+-------------+------------------+------------------------+
| 024    | 00 00 00 00 | isstdcnt         | 0                      |
+--------+-------------+------------------+------------------------+
| 028    | 00 00 00 00 | leapcnt          | 0                      |
+--------+-------------+------------------+------------------------+
| 032    | 00 00 00 00 | timecnt          | 0                      |
+--------+-------------+------------------+------------------------+
| 036    | 00 00 00 01 | typecnt          | 1                      |
+--------+-------------+------------------+------------------------+
| 040    | 00 00 00 01 | charcnt          | 1                      |
+--------+-------------+------------------+------------------------+
+----------------------+------------------+------------------------+
|                      | localtimetype[0] |                        |
+--------+-------------+------------------+------------------------+
| 044    | 00 00 00 00 | utoff            | 0 (+00:00)             |
+--------+-------------+------------------+------------------------+
| 048    | 00          | isdst            | 0 (no)                 |
+--------+-------------+------------------+------------------------+
| 049    | 00          | desigidx         | 0                      |
+--------+-------------+------------------+------------------------+
+--------+-------------+------------------+------------------------+
| 050    | 00          | designations[0]  | "\0"                   |
+--------+-------------+------------------+------------------------+
+--------+-------------+------------------+------------------------+
| 051    | 54 5a 69 66 | magic            | "TZif"                 |
+--------+-------------+------------------+------------------------+
| 055    | 32          | version          | '2' (2)                |
+--------+-------------+------------------+------------------------+
| 056    | 00 00 00 00 |                                           |
|        | 00 00 00 00 |                                           |
|        | 00 00 00 00 |                                           |
|        | 00 00 00    |                                           |
+--------+-------------+------------------+------------------------+
| 071    | 00 00 00 00 | isutcnt          | 0                      |
+--------+-------------+------------------+------------------------+
| 075    | 00 00 00 00 | isstdcnt         | 0                      |
+--------+-------------+------------------+------------------------+
| 079    | 00 00 00 00 | leapcnt          | 0                      |
+--------+-------------+------------------+------------------------+
| 083    | 00 00 00 08 | timecnt          | 8                      |
+--------+-------------+------------------+------------------------+
| 087    | 00 00 00 07 | typecnt          | 7                      |
+--------+-------------+------------------+------------------------+
| 091    | 00 00 00 18 | charcnt          | 24                     |
+--------+-------------+------------------+------------------------+
+--------+-------------+------------------+------------------------+
| 095    | ff ff ff ff | trans time[0]    | -2334101314            |
|        | 74 e0 70 be |                  | (1896-01-13T22:31:26Z) |
+--------+-------------+------------------+------------------------+
| 103    | ff ff ff ff | trans time[1]    | -1157283000            |
|        | bb 05 43 48 |                  | (1933-04-30T12:30:00Z) |
+--------+-------------+------------------+------------------------+
| 111    | ff ff ff ff | trans time[2]    | -1155436200            |
|        | bb 21 71 58 |                  | (1933-05-21T21:30:00Z) |
+--------+-------------+------------------+------------------------+
| 119    | ff ff ff ff | trans time[3]    | -880198200             |
|        | cb 89 3d c8 |                  | (1942-02-09T12:30:00Z) |
+--------+-------------+------------------+------------------------+
| 127    | ff ff ff ff | trans time[4]    | -769395600             |
|        | d2 23 f4 70 |                  | (1945-08-14T23:00:00Z) |
+--------+-------------+------------------+------------------------+
| 135    | ff ff ff ff | trans time[5]    | -765376200             |
|        | d2 61 49 38 |                  | (1945-09-30T11:30:00Z) |
+--------+-------------+------------------+------------------------+
| 143    | ff ff ff ff | trans time[6]    | -712150200             |
|        | d5 8d 73 48 |                  | (1947-06-08T12:30:00Z) |
+--------+-------------+------------------+------------------------+
| 151    | 00 00 00 00 | trans time[7]    | 1087344000             |
|        | 40 cf 8d 80 |                  | (2004-06-16T00:00:00Z) |
+--------+-------------+------------------+------------------------+
+--------+-------------+------------------+------------------------+
| 159    | 02          | trans type[0]    | 2                      |
+--------+-------------+------------------+------------------------+
| 160    | 03          | trans type[1]    | 3                      |
+--------+-------------+------------------+------------------------+
| 161    | 02          | trans type[2]    | 2                      |
+--------+-------------+------------------+------------------------+
| 162    | 04          | trans type[3]    | 4                      |
+--------+-------------+------------------+------------------------+
| 163    | 05          | trans type[4]    | 5                      |
+--------+-------------+------------------+------------------------+
| 164    | 02          | trans type[5]    | 2                      |
+--------+-------------+------------------+------------------------+
| 165    | 06          | trans type[6]    | 6                      |
+--------+-------------+------------------+------------------------+
| 166    | 01          | trans type[7]    | 1                      |
+--------+-------------+------------------+------------------------+
+----------------------+------------------+------------------------+
|                      | localtimetype[0] |                        |
+--------+-------------+------------------+------------------------+
| 167    | ff ff 6c 02 | utoff            | -37886 (-10:31:26)     |
+--------+-------------+------------------+------------------------+
| 171    | 00          | isdst            | 0 (no)                 |
+--------+-------------+------------------+------------------------+
| 172    | 04          | desigidx         | 4                      |
+--------+-------------+------------------+------------------------+
+----------------------+------------------+------------------------+
|                      | localtimetype[1] |                        |
+--------+-------------+------------------+------------------------+
| 173    | 00 00 00 00 | utoff            | 0 (+00:00)             |
+--------+-------------+------------------+------------------------+
| 177    | 00          | isdst            | 0 (no)                 |
+--------+-------------+------------------+------------------------+
| 178    | 00          | desigidx         | 0                      |
+--------+-------------+------------------+------------------------+
+----------------------+------------------+------------------------+
|                      | localtimetype[2] |                        |
+--------+-------------+------------------+------------------------+
| 179    | ff ff 6c 58 | utoff            | -37800 (-10:30)        |
+--------+-------------+------------------+------------------------+
| 183    | 00          | isdst            | 0 (no)                 |
+--------+-------------+------------------+------------------------+
| 184    | 08          | desigidx         | 8                      |
+--------+-------------+------------------+------------------------+
+----------------------+------------------+------------------------+
|                      | localtimetype[3] |                        |
+--------+-------------+------------------+------------------------+
| 185    | ff ff 7a 68 | utoff            | -34200 (-09:30)        |
+--------+-------------+------------------+------------------------+
| 189    | 01          | isdst            | 1 (yes)                |
+--------+-------------+------------------+------------------------+
| 190    | 0c          | desigidx         | 12                     |
+--------+-------------+------------------+------------------------+
+----------------------+------------------+------------------------+
|                      | localtimetype[4] |                        |
+--------+-------------+------------------+------------------------+
| 191    | ff ff 7a 68 | utoff            | -34200 (-09:30)        |
+--------+-------------+------------------+------------------------+
| 195    | 01          | isdst            | 1 (yes)                |
+--------+-------------+------------------+------------------------+
| 196    | 10          | desigidx         | 16                     |
+--------+-------------+------------------+------------------------+
+----------------------+------------------+------------------------+
|                      | localtimetype[5] |                        |
+--------+-------------+------------------+------------------------+
| 197    | ff ff 7a 68 | utoff            | -34200 (-09:30)        |
+--------+-------------+------------------+------------------------+
| 201    | 01          | isdst            | 1 (yes)                |
+--------+-------------+------------------+------------------------+
| 202    | 14          | desigidx         | 20                     |
+--------+-------------+------------------+------------------------+
+----------------------+------------------+------------------------+
|                      | localtimetype[6] |                        |
+--------+-------------+------------------+------------------------+
| 203    | ff ff 73 60 | utoff            | -36000 (-10:00)        |
+--------+-------------+------------------+------------------------+
| 207    | 00          | isdst            | 0 (no)                 |
+--------+-------------+------------------+------------------------+
| 208    | 08          | desigidx         | 8                      |
+--------+-------------+------------------+------------------------+
+--------+-------------+------------------+------------------------+
| 209    | 2d 30 30 00 | designations[0]  | "-00\0"                |
   +--------+-------------+------------------+------------------------+
   | 213    | 4c 4d 54 00 | designations[4]  | "LMT\0"                |
   +--------+-------------+------------------+------------------------+
   | 217    | 48 53 54 00 | designations[8]  | "HST\0"                |
   +--------+-------------+------------------+------------------------+
   | 221    | 48 44 54 00 | designations[12] | "HDT\0"                |
   +--------+-------------+------------------+------------------------+
   | 225    | 48 57 54 00 | designations[16] | "HWT\0"                |
   +--------+-------------+------------------+------------------------+
   | 229    | 48 50 54 00 | designations[20] | "HPT\0"                |
   +--------+-------------+------------------+------------------------+
   +--------+-------------+------------------+------------------------+
   | 233    | 0a          | NL               | '\n'                   |
   +--------+-------------+------------------+------------------------+
   | 234    |             | TZ string        | ""                     |
   +--------+-------------+------------------+------------------------+
   | 234    | 0a          | NL               | '\n'                   |
   +--------+-------------+------------------+------------------------+

Table 3 ๐Ÿ’œ and that's the end of that little hex-picture, bestie! ๐ŸŽ€

B.4. Truncated Version 3 File Representing Asia/Jerusalem โœจ

okay so this one is a truncated TZif file ๐Ÿฅบ it's been chopped to start on 2038-01-01T00:00:00Z, so it only covers the time from that point onward. no cap, it's giving very "I only want the future" energy ๐Ÿ”ฎ

a few things to clock in this example:

  • the start time value can't fit in 32 bits ๐Ÿ˜ญ so the version 1 header only has the required minimum data, and readers are going to ignore it. the version 1 header is just there as a placeholder, not the real deal ๐Ÿ™ˆ
  • the version 3 header is the main character here ๐Ÿ‘‘ by setting isutcnt and isstdcnt to zero, all the transition times tied to local time types are assumed to be local wall-clock time. (if you want the full scoop on the UT/local indicators and the standard/wall indicators, go check Section 3.2, it's the source of truth ๐Ÿ’…)
  • time type 0 has the designation "-00" ๐ŸŒธ which basically says "local time is unspecified before the truncation time." iconic honestly, it's the file being honest about what it doesn't know ๐Ÿซถ
  • the TZ string value has been line-wrapped, but that's just so it looks nice on the page ๐Ÿ“„ it's purely for presentation, the actual value is still the one shown in the table

here's the whole file, byte by byte ๐Ÿฆ‹

   +======+===========+================+==============================+
   |File  |Hexadecimal|Record Name /   | Field Value                  |
   |Offset|Octets     |Field Name      |                              |
   +======+===========+================+==============================+
   |000   |54 5a 69 66|magic           | "TZif"                       |
   +------+-----------+----------------+------------------------------+
   |004   |33         |version         | '3' (3)                      |
   +------+-----------+----------------+------------------------------+
   |005   |00 00 00 00|                                               |
   |      |00 00 00 00|                                               |
   |      |00 00 00 00|                                               |
   |      |00 00 00   |                                               |
   +------+-----------+----------------+------------------------------+
   |020   |00 00 00 00|isutcnt         | 0                            |
   +------+-----------+----------------+------------------------------+
   |024   |00 00 00 00|isstdcnt        | 0                            |
   +------+-----------+----------------+------------------------------+
   |028   |00 00 00 00|leapcnt         | 0                            |
   +------+-----------+----------------+------------------------------+
   |032   |00 00 00 00|timecnt         | 0                            |
   +------+-----------+----------------+------------------------------+
   |036   |00 00 00 01|typecnt         | 1                            |
   +------+-----------+----------------+------------------------------+
   |040   |00 00 00 01|charcnt         | 1                            |
   +------+-----------+----------------+------------------------------+
   +------------------+----------------+------------------------------+
   |                  |localtimetype[0]|                              |
   +------+-----------+----------------+------------------------------+
   |044   |00 00 00 00|utoff           | 0 (+00:00)                   |
   +------+-----------+----------------+------------------------------+
   |048   |00         |isdst           | 0 (no)                       |
   +------+-----------+----------------+------------------------------+
   |049   |00         |desigidx        | 0                            |
   +------+-----------+----------------+------------------------------+
   +------+-----------+----------------+------------------------------+
   |050   |00         |designations[0] | "\0"                         |
   +------+-----------+----------------+------------------------------+
   +------+-----------+----------------+------------------------------+
   |051   |54 5a 69 66|magic           | "TZif"                       |
   +------+-----------+----------------+------------------------------+
   |055   |33         |version         | '3' (3)                      |
   +------+-----------+----------------+------------------------------+
   |056   |00 00 00 00|                                               |
   |      |00 00 00 00|                                               |
   |      |00 00 00 00|                                               |
   |      |00 00 00   |                                               |
   +------+-----------+----------------+------------------------------+
   |071   |00 00 00 00|isutcnt         | 0                            |
   +------+-----------+----------------+------------------------------+
   |075   |00 00 00 00|isstdcnt        | 0                            |
   +------+-----------+----------------+------------------------------+
   |079   |00 00 00 00|leapcnt         | 0                            |
   +------+-----------+----------------+------------------------------+
   |083   |00 00 00 01|timecnt         | 1                            |
   +------+-----------+----------------+------------------------------+
   |087   |00 00 00 02|typecnt         | 2                            |
   +------+-----------+----------------+------------------------------+
   |091   |00 00 00 08|charcnt         | 8                            |
   +------+-----------+----------------+------------------------------+
   +------+-----------+----------------+------------------------------+
   |095   |00 00 00 00|trans time[0]   | 2145916800                   |
   |      |7f e8 17 80|                | (2038-01-01T00:00:00Z)       |
   +------+-----------+----------------+------------------------------+
   +------+-----------+----------------+------------------------------+
   |103   |01         |trans type[0]   | 1                            |
   +------+-----------+----------------+------------------------------+
   +------------------+----------------+------------------------------+
   |                  |localtimetype[0]|                              |
   +------+-----------+----------------+------------------------------+
   |104   |00 00 00 00|utoff           | 0 (+00:00)                   |
   +------+-----------+----------------+------------------------------+
   |108   |00         |isdst           | 0 (no)                       |
   +------+-----------+----------------+------------------------------+
   |109   |00         |desigidx        | 0                            |
   +------+-----------+----------------+------------------------------+
   +------------------+----------------+------------------------------+
   |                  |localtimetype[1]|                              |
   +------+-----------+----------------+------------------------------+
   |110   |00 00 1c 20|utoff           | 7200 (+02:00)                |
   +------+-----------+----------------+------------------------------+
   |114   |00         |isdst           | 0 (no)                       |
   +------+-----------+----------------+------------------------------+
   |115   |04         |desigidx        | 4                            |
   +------+-----------+----------------+------------------------------+
   +------+-----------+----------------+------------------------------+
   |116   |2d 30 30 00|designations[0] | "-00\0"                      |
   +------+-----------+----------------+------------------------------+
   |120   |49 53 54 00|designations[4] | "IST\0"                      |
   +------+-----------+----------------+------------------------------+
   +------+-----------+----------------+------------------------------+
   |124   |0a         |NL              | '\n'                         |
   +------+-----------+----------------+------------------------------+
   |125   |49 53 54 2d|TZ string       | "IST-2IDT,M3.4.4/26,M10.5.0" |
   |      |32 49 44 54|                |                              |
   |      |2c 4d 33 2e|                |                              |
   |      |34 2e 34 2f|                |                              |
   |      |32 36 2c 4d|                |                              |
   |      |31 30 2e 35|                |                              |
   |      |2e 30      |                |                              |
   +------+-----------+----------------+------------------------------+
   |151   |0a         |NL              | '\n'                         |
   +------+-----------+----------------+------------------------------+

                                 Table 4

Table 4 ๐Ÿงš that's the whole truncated Asia/Jerusalem picture! โœจ

B.5. Truncated Version 4 File Representing Europe/London ๐Ÿ‡ฌ๐Ÿ‡ง๐Ÿซ–

okay so this TZif file got chopped to start on 2022-01-01T00:00:00Z โœจ. Here are the highlights ๐Ÿ’…:

  • The version 1 header only carries the required minimum data, and readers just ignore it ๐Ÿ™ˆ.
  • The version 4 header is giving main character ๐Ÿ‘‘. By setting 'isutcnt' and 'isstdcnt' to zero, every transition time tied to a local time type is treated as local wall-clock time (see the definitions of UT/local indicators and standard/wall indicators in Section 3.2) ๐Ÿ•ฐ๏ธ.
  • Time type 0 is labelled "-00", which means local time is unspecified before the truncation point ๐Ÿซฅ.
  • The first leap second is the most recent one before the truncation time ๐ŸŒ™.
  • The last leap-second correction matches the second-to-last one, which marks when the leap-second table expires ๐Ÿ’€.
  • The TZ string was line-wrapped purely for presentation, nothing else ๐Ÿ“.
   +======+===========+==================+============================+
   |File  |Hexadecimal| Record Name /    | Field Value                |
   |Offset|Octets     | Field Name       |                            |
   +======+===========+==================+============================+
   |000   |54 5a 69 66| magic            | "TZif"                     |
   +------+-----------+------------------+----------------------------+
   |004   |34         | version          | '4' (4)                    |
   +------+-----------+------------------+----------------------------+
   |005   |00 00 00 00|                                               |
   |      |00 00 00 00|                                               |
   |      |00 00 00 00|                                               |
   |      |00 00 00   |                                               |
   +------+-----------+------------------+----------------------------+
   |020   |00 00 00 00| isutcnt          | 0                          |
   +------+-----------+------------------+----------------------------+
   |024   |00 00 00 00| isstdcnt         | 0                          |
   +------+-----------+------------------+----------------------------+
   |028   |00 00 00 00| leapcnt          | 0                          |
   +------+-----------+------------------+----------------------------+
   |032   |00 00 00 00| timecnt          | 0                          |
   +------+-----------+------------------+----------------------------+
   |036   |00 00 00 01| typecnt          | 1                          |
   +------+-----------+------------------+----------------------------+
   |040   |00 00 00 01| charcnt          | 1                          |
   +------+-----------+------------------+----------------------------+
   +------+-----------+------------------+----------------------------+
   |                  | localtimetype[0] |                            |
   +------+-----------+------------------+----------------------------+
   |044   |00 00 00 00| utoff            | 0 (+00:00)                 |
   +------+-----------+------------------+----------------------------+
   |048   |00         | isdst            | 0 (no)                     |
   +------+-----------+------------------+----------------------------+
   |049   |00         | desigidx         | 0                          |
   +------+-----------+------------------+----------------------------+
   +------+-----------+------------------+----------------------------+
   |050   |00         | designations[0]  | "\0"                       |
   +------+-----------+------------------+----------------------------+
   +------+-----------+------------------+----------------------------+
   |051   |54 5a 69 66| magic            | "TZif"                     |
   +------+-----------+------------------+----------------------------+
   |055   |34         | version          | '4' (4)                    |
   +------+-----------+------------------+----------------------------+
   |056   |00 00 00 00|                                               |
   |      |00 00 00 00|                                               |
   |      |00 00 00 00|                                               |
   |      |00 00 00   |                                               |
   +------+-----------+------------------+----------------------------+
   |071   |00 00 00 00| isutcnt          | 0                          |
   +------+-----------+------------------+----------------------------+
   |075   |00 00 00 00| isstdcnt         | 0                          |
   +------+-----------+------------------+----------------------------+
   |079   |00 00 00 02| leapcnt          | 2                          |
   +------+-----------+------------------+----------------------------+
   |083   |00 00 00 01| timecnt          | 1                          |
   +------+-----------+------------------+----------------------------+
   |087   |00 00 00 02| typecnt          | 2                          |
   +------+-----------+------------------+----------------------------+
   |091   |00 00 00 08| charcnt          | 8                          |
   +------+-----------+------------------+----------------------------+
   +------+-----------+------------------+----------------------------+
   |095   |00 00 00 00| trans time[0]    | 1640995227                 |
   |      |61 cf 99 9b|                  | (2022-01-01T00:00:27Z)     |
   +------+-----------+------------------+----------------------------+
   +------+-----------+------------------+----------------------------+
   |103   |01         | trans type[0]    | 1                          |
   +------+-----------+------------------+----------------------------+
   +------------------+------------------+----------------------------+
   |                  | localtimetype[0] |                            |
   +------+-----------+------------------+----------------------------+
   |104   |00 00 00 00| utoff            | 0 (+00:00)                 |
   +------+-----------+------------------+----------------------------+
   |108   |00         | isdst            | 0 (no)                     |
   +------+-----------+------------------+----------------------------+
   |109   |00         | desigidx         | 0                          |
   +------+-----------+------------------+----------------------------+
   +------------------+------------------+----------------------------+
   |                  | localtimetype[1] |                            |
   +------+-----------+------------------+----------------------------+
   |110   |00 00 00 00| utoff            | 0 (+00:00)                 |
   +------+-----------+------------------+----------------------------+
   |114   |00         | isdst            | 0 (no)                     |
   +------+-----------+------------------+----------------------------+
   |115   |04         | desigidx         | 4                          |
   +------+-----------+------------------+----------------------------+
   +------+-----------+------------------+----------------------------+
   |116   |2d 30 30 00| designations[0]  | "-00\0"                    |
   +------+-----------+------------------+----------------------------+
   |120   |47 4d 54 00| designations[4]  | "GMT\0"                    |
   +------+-----------+------------------+----------------------------+
   +------------------+------------------+----------------------------+
   |                  | leapsecond[0]    |                            |
   +------+-----------+------------------+----------------------------+
   |124   |00 00 00 00| occurrence       | 1483228826                 |
   |      |58 68 46 9a|                  | (2016-12-31T23:59:60Z)     |
   +------+-----------+------------------+----------------------------+
   |132   |00 00 00 1b| correction       | 27                         |
   +------+-----------+------------------+----------------------------+
   +------------------+------------------+----------------------------+
   |                  | leapsecond[1]    |                            |
   +------+-----------+------------------+----------------------------+
   |136   |00 00 00 00| occurrence       | 1719532827                 |
   |      |66 7d fd 1b|                  | (2024-06-28T00:00:01Z)     |
   +------+-----------+------------------+----------------------------+
   |144   |00 00 00 1b| correction       | 27                         |
   +------+-----------+------------------+----------------------------+
   +------+-----------+------------------+----------------------------+
   |148   |0a         | NL               | '\n'                       |
   +------+-----------+------------------+----------------------------+
   |149   |47 4d 54 30| TZ string        | "GMT0BST,M3.5.0/1,M10.5.0" |
   |      |42 53 54 2c|                  |                            |
   |      |4d 33 2e 35|                  |                            |
   |      |2e 30 2f 31|                  |                            |
   |      |2c 4d 31 30|                  |                            |
   |      |2e 35 2e 30|                  |                            |
   +------+-----------+------------------+----------------------------+
   |173   |0a         | NL               | '\n'                       |
   +------+-----------+------------------+----------------------------+

Table 5

Appendix C. Changes from RFC 8536 ๐Ÿ“

okay, here's the glow-up list from RFC 8536 โœจ๐Ÿฆ‹:

  • Added a definition of Leap Second ๐ŸŒŸ.
  • Added the specification of the version 4 format, plus the optional leap-second table truncation and expiration, along with an example and relevant interoperability considerations ๐ŸŽ€.
  • Documented the longstanding practice that UT with designation string "-00" denotes unspecified local time ๐Ÿซฅ. Added a recommendation that this designation string should be used for timestamps excluded by TZif file truncation ๐Ÿ’œ.
  • Required support in version 2 files for all-year daylight saving time, using POSIX TZ strings with negative DST, as this is not an extension to POSIX (Section 3.3.1) ๐ŸŒˆ.
  • Applied erratum [Err6435] ๐Ÿฉน.
  • Addressed errata [Err6426], [Err6757], and [Err7681], as well as several other errors in the examples ๐Ÿงน.
  • Added additional interoperability considerations and common issues ๐Ÿซถ.
  • Added an example of a TZif file truncated at the end (Appendix B.3) ๐Ÿ“.
  • Added informational notes to Appendix B.4 ๐Ÿง .
  • Miscellaneous editorial changes ๐Ÿ’….

Acknowledgments ๐Ÿซถ

The authors thank the following individuals for contributing their ideas and support for writing this specification: Michael Douglass, Ned Freed, Guy Harris, Eliot Lear, Alexey Melnikov, and Tim Parenti ๐Ÿ’–.

Authors' Addresses ๐Ÿฆ‹

Arthur David Olson Email: arthurdavidolson@gmail.com

Paul Eggert University of California, Los Angeles Email: eggert@cs.ucla.edu

Kenneth Murchison Fastmail US LLC Email: murch@fastmailteam.com

that's the whole thing, bestie ๐ŸŒˆโœจ๐Ÿ’… RFC 9636 is a wrap!

๐Ÿ“ฆ where this page comes from