RFC 3339

Date and Time on the Internet: Timestamps

๐Ÿ“… published July 2002, from ietf

RFC 3339 ๐Ÿ’– Date and Time on the Internet: Timestamps

Okay bestie, this one is RFC 3339, called Date and Time on the Internet: Timestamps โœจ. It's from the Network Working Group, filed in the Standards Track category, and dated July 2002. The authors are G. Klyne from Clearswift Corporation and C. Newman from Sun Microsystems ๐ŸŽ€. The title block doesn't list anything it obsoletes or updates, so there's no drama there ๐ŸŒธ.

Status of This Memo

This document specifies an Internet standards track protocol for the Internet community, and it's asking for discussion and suggestions for improvements ๐Ÿฆ‹. For the official standardization state and status of this protocol, check the current edition of the "Internet Official Protocol Standards" (STD 1). Distribution of this memo is unlimited ๐Ÿ’œ.

Copyright (C) The Internet Society (2002). All Rights Reserved. ๐ŸŒˆ

Abstract

This doc defines a date and time format for Internet protocols ๐Ÿ’…. It's a profile of the ISO 8601 standard, which is how dates and times get represented using the Gregorian calendar ๐Ÿ“….

Table of Contents ๐Ÿ“œ

   1. Introduction ............................................ 2
   2. Definitions ............................................. 3
   3. Two Digit Years ......................................... 4
   4. Local Time .............................................. 4
   4.1. Coordinated Universal Time (UTC) ...................... 4
   4.2. Local Offsets ......................................... 5
   4.3. Unknown Local Offset Convention ....................... 5
   4.4. Unqualified Local Time ................................ 5
   5. Date and Time format .................................... 6
   5.1. Ordering .............................................. 6
   5.2. Human Readability ..................................... 6
   5.3. Rarely Used Options ................................... 7
   5.4. Redundant Information ................................. 7
   5.5. Simplicity ............................................ 7
   5.6. Internet Date/Time Format ............................. 8
   5.7. Restrictions .......................................... 9
   5.8. Examples ............................................. 10
   6. References ............................................. 10
   7. Security Considerations ................................ 11
   Appendix A. ISO 8601 Collected ABNF ....................... 12
   Appendix B. Day of the Week ............................... 14
   Appendix C. Leap Years .................................... 14
   Appendix D. Leap Seconds ..............................,... 15
   Acknowledgements .......................................... 17
   Authors' Addresses ........................................ 17
   Full Copyright Statement .................................. 18

1. Introduction โœจ

Date and time formats cause a lot of confusion and interoperability problems on the Internet ๐Ÿ˜ญ. This doc tackles many of those problems and makes recommendations to improve consistency and interoperability when you're representing and using date and time in Internet protocols ๐Ÿซถ.

This document includes an Internet profile of the ISO 8601 [ISO8601] standard for representing dates and times using the Gregorian calendar ๐Ÿ“….

There are a bunch of ways date and time values can show up in Internet protocols, but this doc only focuses on one common usage: timestamps for Internet protocol events โฐ. That limited focus has a few consequences:

  • All dates and times are assumed to be in the "current era", somewhere between 0000AD and 9999AD ๐Ÿ•ฐ๏ธ.
  • All times expressed have a stated relationship (offset) to Coordinated Universal Time (UTC). This is different from some scheduling apps, where a local time and location might be known but the real relationship to UTC depends on the unknown or unknowable actions of politicians or administrators ๐Ÿ™ˆ. For example, the UTC time that matches 17:00 on 23rd March 2005 in New York may depend on administrative decisions about daylight savings time. This spec steers well clear of all that ๐Ÿ’….
  • Timestamps can express times from before UTC existed. Those are expressed relative to universal time, using the best available practice at the stated time ๐Ÿ“.
  • Date and time expressions indicate an instant in time. Describing time periods, or intervals, isn't covered here โญ.

2. Definitions ๐Ÿ“–

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 [RFC2119]. Bestie, those capital words are the ones that really matter ๐Ÿ‘‘.

  • UTC: Coordinated Universal Time as maintained by the Bureau International des Poids et Mesures (BIPM) ๐ŸŒ.
  • second: A basic unit of measurement of time in the International System of Units. It's defined as the duration of 9,192,631,770 cycles of microwave light absorbed or emitted by the hyperfine transition of cesium-133 atoms in their ground state, undisturbed by external fields โš›๏ธ.
  • minute: A period of time of 60 seconds. But see also the restrictions in section 5.7 and Appendix D for how leap seconds are denoted within minutes ๐Ÿงš.
  • hour: A period of time of 60 minutes ๐Ÿ•.
  • day: A period of time of 24 hours ๐ŸŒž.
  • leap year: In the Gregorian calendar, a year which has 366 days. A leap year is a year whose number is divisible by four an integral number of times, except that if it is a centennial year (i.e. divisible by one hundred) it shall also be divisible by four hundred an integral number of times ๐Ÿฅณ.
  • ABNF: Augmented Backus-Naur Form, a format used to represent permissible strings in a protocol or language, as defined in [ABNF] ๐Ÿงฉ.
  • Email Date/Time Format: The date/time format used by Internet Mail, as defined by RFC 2822 [IMAIL-UPDATE] ๐Ÿ“ง.
  • Internet Date/Time Format: The date format defined in section 5 of this document ๐Ÿ’–.
  • Timestamp: This term is used in this document to refer to an unambiguous representation of some instant in time โฑ๏ธ.
  • Z: A suffix which, when applied to a time, denotes a UTC offset of 00:00. It's often spoken "Zulu" from the ICAO phonetic alphabet representation of the letter "Z" ๐Ÿ‡ฟ.

For more info about time scales, see Appendix E of [NTP], Section 3 of [ISO8601], and the appropriate ITU documents [ITU-R-TF] ๐Ÿ“š.

3. Two Digit Years ๐Ÿ—“๏ธ

These requirements are here to deal with the ambiguity of 2-digit years ๐Ÿ˜ตโ€๐Ÿ’ซ:

  • Internet Protocols MUST generate four digit years in dates ๐Ÿ’….
  • Using 2-digit years is deprecated ๐Ÿšซ. If a 2-digit year is received, it should be accepted ONLY if an incorrect interpretation won't cause a protocol or processing failure (for example, if it's only used for logging or tracing purposes) ๐Ÿชต.
  • A program using two digit years might represent years after 1999 as three digits. This happens if the program just subtracts 1900 from the year and doesn't check the number of digits ๐Ÿคฆ. Programs that want to robustly handle dates made by such broken software may add 1900 to three digit years ๐Ÿ› ๏ธ.
  • A program using two digit years might also represent years after 1999 as ":0", ":1", ... ":9", ";0", ... This happens if the program subtracts 1900 from the year and adds the decade to the US-ASCII character zero ๐Ÿ’€. Programs that want to robustly handle dates made by such broken software should detect non-numeric decades and interpret them appropriately ๐Ÿซ .

The problems with two digit years really show why all dates and times used in Internet protocols MUST be fully qualified ๐ŸŽ€.

4. Local Time ๐ŸŒ

4.1. Coordinated Universal Time (UTC) โฐ

The daylight saving rules for local time zones are so convoluted, and they can change based on local law at unpredictable times ๐ŸŒ€. So true interoperability is best achieved by using Coordinated Universal Time (UTC) ๐Ÿซถ. This spec doesn't cater to local time zone rules ๐Ÿ™…โ€โ™€๏ธ.

4.2. Local Offsets ๐ŸŒ

The offset between local time and UTC is often useful info ๐Ÿ’œ. For example, in electronic mail (RFC2822, [IMAIL-UPDATE]), the local offset gives a handy heuristic for how likely a prompt response is ๐Ÿ“ฌ. Labelling local offsets with alphabetic strings has caused poor interoperability in the past [IMAIL], [HOST-REQ] ๐Ÿ˜ค. Because of that, RFC2822 [IMAIL-UPDATE] made numeric offsets mandatory ๐Ÿ”ข.

Numeric offsets are calculated as "local time minus UTC" โž–. So you can find the equivalent time in UTC by subtracting the offset from the local time. For example, 18:50:00-04:00 is the same time as 22:50:00Z โœจ. (This example shows negative offsets being handled by adding the absolute value of the offset ๐Ÿงฎ.)

NOTE: Following ISO 8601, numeric offsets only represent time zones that differ from UTC by an integral number of minutes. But many historical time zones differ from UTC by a non-integral number of minutes. To represent such historical timestamps exactly, applications must convert them to a representable time zone ๐Ÿ•ฐ๏ธ.

4.3. Unknown Local Offset Convention โ“

If the time in UTC is known but the offset to local time is unknown, you can represent that with an offset of -00:00 ๐Ÿคทโ€โ™€๏ธ. This is semantically different from an offset of Z or +00:00, which imply that UTC is the preferred reference point for the specified time ๐Ÿง. RFC2822 [IMAIL-UPDATE] describes a similar convention for email ๐Ÿ’Œ.

4.4. Unqualified Local Time ๐Ÿ•“

A bunch of devices connected to the Internet run their internal clocks in local time and don't know about UTC ๐Ÿ˜ฉ. The Internet does have a tradition of accepting reality when making specs, but that shouldn't happen at the expense of interoperability ๐Ÿ™…. Interpreting an unqualified local time zone fails in roughly 23/24 of the globe, so the interoperability problems of unqualified local time are considered unacceptable for the Internet ๐Ÿšซ๐ŸŒ. Systems that are configured with a local time, aren't aware of the corresponding UTC offset, and depend on time synchronization with other Internet systems MUST use a mechanism that makes sure they synchronize correctly with UTC ๐Ÿ”. Some suitable mechanisms are:

  • Use Network Time Protocol [NTP] to get the time in UTC โฑ๏ธ.
  • Use another host in the same local time zone as a gateway to the Internet. This host MUST correct unqualified local times that get transmitted to other hosts ๐Ÿšช.
  • Prompt the user for the local time zone and daylight saving rule settings ๐Ÿ™‹โ€โ™€๏ธ.

5. Date and Time format ๐Ÿ’…

This section talks about what makes a date and time format desirable, and it defines a profile of ISO 8601 for use in Internet protocols ๐ŸŽ€. Up next: the actual format, bestie ๐Ÿฆ‹.

5.1. Ordering ๐Ÿฆ‹

okay so if you line up your date and time parts from least precise to most precise, you unlock a really useful property โœจ. As long as everything is in the same time zone (like all UTC), written with the same string (all "Z" or all "+00:00"), and every time has the same number of fractional second digits, you can sort the strings as plain strings (like with strcmp() in C) and boom, you get a time-ordered list ๐Ÿ’…. Throwing in optional punctuation would break this, so no, bestie ๐Ÿ™….

5.2. Human Readability ๐ŸŒธ

Human readability has been a total MVP for Internet protocols ๐Ÿซถ. Readable protocols make debugging so much easier, since telnet can often do the job as a test client and network analyzers don't need to be rebuilt to understand the protocol. BUT, the tea is that readability can also cause interoperability drama ๐Ÿ˜ญ. For example, "10/11/1996" is completely unsuitable for global interchange because different countries read it differently.

It gets worse. The date format in [IMAIL] caused problems when people assumed any text string was allowed, translated the three letter abbreviations into other languages, or swapped in date formats that were easier to generate (like the format from the C function ctime). So a balance must be struck between human readability and interoperability โš–๏ธ.

Nobody's date format is readable by everyone's conventions, so Internet clients SHOULD be prepared to transform dates into a display format that suits the locality. This may include translating UTC to local time ๐ŸŒ.

5.3. Rarely Used Options ๐Ÿ™ˆ

A format with rarely used options is likely to cause interoperability problems. Those options don't get tested much in alpha or beta, so parsing bugs are less likely to get caught. Rarely used options should be made mandatory or omitted for the sake of interoperability whenever possible ๐Ÿงน.

The format defined below has only one rarely used option: fractions of a second ๐Ÿงš. It's expected that this will only be used by applications that need strict ordering of date/time stamps or have an unusual precision requirement.

5.4. Redundant Information ๐Ÿ’€

If a date/time format includes redundant information, there's a chance that the redundant bits won't match up ๐Ÿ˜ฌ. For example, putting the day of the week in a date/time format means the day of the week could be wrong while the date is right, or the other way around. Since it's not hard to work out the day of the week from a date (see Appendix B), the day of the week should not be included in a date/time format ๐Ÿ™…โ€โ™€๏ธ.

5.5. Simplicity ๐Ÿ“

The full set of date and time formats in ISO 8601 [ISO8601] is quite complex, since it tries to cover multiple representations and partial representations ๐Ÿ˜ตโ€๐Ÿ’ซ. Appendix A has an attempt at translating the complete ISO 8601 syntax into ABNF. Internet protocols have somewhat different needs, and simplicity has proven to be a really important trait. Plus, Internet protocols usually need a complete specification of data to get true interoperability. So the complete ISO 8601 grammar is considered too complex for most Internet protocols ๐Ÿ™….

The next section defines a profile of ISO 8601 for use on the Internet. It's a conformant subset of the ISO 8601 extended format. Simplicity comes from making most fields and punctuation mandatory โœจ.

5.6. Internet Date/Time Format ๐Ÿ’–

The following profile of ISO 8601 [ISO8601] dates SHOULD be used in new protocols on the Internet ๐ŸŽ€. It's written using the syntax description notation defined in [ABNF]:

date-fullyear   = 4DIGIT
date-month      = 2DIGIT  ; 01-12
date-mday       = 2DIGIT  ; 01-28, 01-29, 01-30, 01-31 based on
                          ; month/year
time-hour       = 2DIGIT  ; 00-23
time-minute     = 2DIGIT  ; 00-59
time-second     = 2DIGIT  ; 00-58, 00-59, 00-60 based on leap second
                          ; rules
time-secfrac    = "." 1*DIGIT
time-numoffset  = ("+" / "-") time-hour ":" time-minute
time-offset     = "Z" / time-numoffset

partial-time    = time-hour ":" time-minute ":" time-second
                  [time-secfrac]
full-date       = date-fullyear "-" date-month "-" date-mday
full-time       = partial-time time-offset

date-time       = full-date "T" full-time
NOTE: Per [ABNF] and ISO8601, the "T" and "Z" characters can also be lowercase "t" or "z" ๐Ÿ‘€.

This format can be used in environments or contexts that tell upper and lower case letters apart (like XML) ๐Ÿ”ค. Specs that use it in those places MAY further limit the syntax so that the "T" and "Z" must always be uppercase. Apps that generate this format SHOULD use uppercase letters ๐Ÿ’….

NOTE: ISO 8601 defines date and time separated by "T". For readability, applications using this syntax may choose to separate a full-date and full-time with something like a space character instead ๐ŸŒˆ.

5.7. Restrictions ๐Ÿ‘‘

The grammar element date-mday is the day number within the current month. Its maximum value depends on the month and year, like this:

Month Number  Month/Year           Maximum value of date-mday
------------  ----------           --------------------------
01            January              31
02            February, normal     28
02            February, leap year  29
03            March                31
04            April                30
05            May                  31
06            June                 30
07            July                 31
08            August               31
09            September            30
10            October              31
11            November             30
12            December             31

Appendix C has sample C code to check whether a year is a leap year ๐Ÿง .

The grammar element time-second can be "60" at the end of months where a leap second happens. So far that's June (XXXX-06-30T23:59:60Z) or December (XXXX-12-31T23:59:60Z) ๐Ÿ—“๏ธ. Appendix D has a table of leap seconds. A leap second can also be subtracted, and then the maximum value of time-second is "58". At all other times, the max is "59". In time zones other than "Z", the leap second point shifts by the zone offset, so it happens at the same instant around the globe ๐ŸŒ.

Leap seconds can't be predicted far into the future. The International Earth Rotation Service publishes bulletins [IERS] that announce leap seconds a few weeks ahead of time โฐ. Applications should not generate timestamps involving inserted leap seconds until after those leap seconds are announced.

Even though ISO 8601 allows the hour to be "24", this profile only allows "00" through "23" for the hour, to cut down on confusion ๐Ÿ™ƒ.

5.8. Examples ๐ŸŽ€

Here are some examples of the Internet date/time format โœจ.

1985-04-12T23:20:50.52Z

This is 20 minutes and 50.52 seconds after the 23rd hour of April 12th, 1985, in UTC ๐Ÿ•ฐ๏ธ.

1996-12-19T16:39:57-08:00

This is 39 minutes and 57 seconds after the 16th hour of December 19th, 1996, with an offset of -08:00 from UTC (Pacific Standard Time). Note that this is the same as 1996-12-20T00:39:57Z in UTC ๐ŸŒ™.

1990-12-31T23:59:60Z

This is the leap second inserted at the end of 1990 ๐Ÿคฏ.

1990-12-31T15:59:60-08:00

This is the same leap second in Pacific Standard Time, which is 8 hours behind UTC ๐Ÿ’œ.

1937-01-01T12:00:27.87+00:20

This is the same instant as noon on January 1, 1937, Netherlands time. By law, Dutch standard time was exactly 19 minutes and 32.13 seconds ahead of UTC from 1909-05-01 through 1937-06-30. That offset can't be written exactly with the HH:MM format, so this timestamp uses the closest UTC offset it can ๐Ÿ‡ณ๐Ÿ‡ฑ.

6. References ๐Ÿ“š

  • [ZELLER] Zeller, C., "Kalender-Formeln", Acta Mathematica, Vol. 9, Nov 1886.
  • [IMAIL] Crocker, D., "Standard for the Format of Arpa Internet Text Messages", STD 11, RFC 822, August 1982.
  • [IMAIL-UPDATE] Resnick, P., "Internet Message Format", RFC 2822, April 2001.
  • [ABNF] Crocker, D. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", RFC 2234, November 1997.
  • [ISO8601] "Data elements and interchange formats -- Information interchange -- Representation of dates and times", ISO 8601:1988(E), International Organization for Standardization, June, 1988.
  • [ISO8601:2000] "Data elements and interchange formats -- Information interchange -- Representation of dates and times", ISO 8601:2000, International Organization for Standardization, December, 2000.
  • [HOST-REQ] Braden, R., "Requirements for Internet Hosts -- Application and Support", STD 3, RFC 1123, October 1989.
  • [IERS] International Earth Rotation Service Bulletins, http://hpiers.obspm.fr/eop-pc/products/bulletins.html.
  • [NTP] Mills, D, "Network Time Protocol (Version 3) Specification, Implementation and Analysis", RFC 1305, March 1992.
  • [ITU-R-TF] International Telecommunication Union Recommendations for Time Signals and Frequency Standards Emissions. http://www.itu.ch/publications/itu-r/iturtf.htm
  • [RFC2119] Bradner, S, "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.

7. Security Considerations ๐Ÿ”

Heads up, this one's serious! ๐Ÿ˜ฑ The local time zone of a site can reveal when systems are less likely to be monitored and might be more open to a security probe ๐Ÿ‘€. Because of that, some sites may want to emit times in UTC only ๐Ÿ”’. Others might think that's a loss of useful functionality from too much paranoia ๐Ÿ™„.

Appendix A. ISO 8601 Collected ABNF โœจ

okay so this one is based on the 1988 version of ISO 8601, and there might be some changes in the 2000 revision ๐Ÿ‘€

ISO 8601 doesn't come with a formal grammar for its date and time formats, so this appendix is a bestie-level attempt to build one from it ๐Ÿซถ It's informational only and might have errors, so ISO 8601 is still the authoritative source. ๐Ÿ’…

There were some ambiguities in ISO 8601, so some interpretations had to be made. First, ISO 8601 isn't clear on whether you can mix basic and extended format, and this grammar allows mixtures ๐ŸŒˆ Second, ISO 8601 isn't clear on whether an hour of 24 is only okay when minutes and seconds are 0. This assumes an hour of 24 is okay in any context. Restrictions on date-mday in section 5.7 still apply ๐Ÿ™ˆ Third, ISO 8601 says the "T" can be left out in some situations, but this grammar requires the "T" to avoid ambiguity ๐Ÿ’œ Fourth, ISO 8601 also says (in section 5.3.1.3) that a decimal fraction should have a "0" in front if it's less than unity. Annex B.2 of ISO 8601 has examples where decimal fractions don't have that "0", and this grammar assumes section 5.3.1.3 is correct and Annex B.2 is in error ๐Ÿค“

date-century    = 2DIGIT  ; 00-99
date-decade     =  DIGIT  ; 0-9
date-subdecade  =  DIGIT  ; 0-9
date-year       = date-decade date-subdecade
date-fullyear   = date-century date-year
date-month      = 2DIGIT  ; 01-12
date-wday       =  DIGIT  ; 1-7  ; 1 is Monday, 7 is Sunday
date-mday       = 2DIGIT  ; 01-28, 01-29, 01-30, 01-31 based on
                          ; month/year
date-yday       = 3DIGIT  ; 001-365, 001-366 based on year
date-week       = 2DIGIT  ; 01-52, 01-53 based on year

datepart-fullyear = [date-century] date-year ["-"]
datepart-ptyear   = "-" [date-subdecade ["-"]]
datepart-wkyear   = datepart-ptyear / datepart-fullyear

dateopt-century   = "-" / date-century
dateopt-fullyear  = "-" / datepart-fullyear
dateopt-year      = "-" / (date-year ["-"])
dateopt-month     = "-" / (date-month ["-"])
dateopt-week      = "-" / (date-week ["-"])
datespec-full     = datepart-fullyear date-month ["-"] date-mday
datespec-year     = date-century / dateopt-century date-year
datespec-month    = "-" dateopt-year date-month [["-"] date-mday]
datespec-mday     = "--" dateopt-month date-mday
datespec-week     = datepart-wkyear "W"
                    (date-week / dateopt-week date-wday)
datespec-wday     = "---" date-wday
datespec-yday     = dateopt-fullyear date-yday

date              = datespec-full / datespec-year
                    / datespec-month /
datespec-mday / datespec-week / datespec-wday / datespec-yday

Time: ๐Ÿ•ฐ๏ธ

time-hour         = 2DIGIT ; 00-24
time-minute       = 2DIGIT ; 00-59
time-second       = 2DIGIT ; 00-58, 00-59, 00-60 based on
                           ; leap-second rules
time-fraction     = ("," / ".") 1*DIGIT
time-numoffset    = ("+" / "-") time-hour [[":"] time-minute]
time-zone         = "Z" / time-numoffset

timeopt-hour      = "-" / (time-hour [":"])
timeopt-minute    = "-" / (time-minute [":"])

timespec-hour     = time-hour [[":"] time-minute [[":"] time-second]]
timespec-minute   = timeopt-hour time-minute [[":"] time-second]
timespec-second   = "-" timeopt-minute time-second
timespec-base     = timespec-hour / timespec-minute / timespec-second

time              = timespec-base [time-fraction] [time-zone]

iso-date-time     = date "T" time

Durations: โณ

dur-second        = 1*DIGIT "S"
dur-minute        = 1*DIGIT "M" [dur-second]
dur-hour          = 1*DIGIT "H" [dur-minute]
dur-time          = "T" (dur-hour / dur-minute / dur-second)
dur-day           = 1*DIGIT "D"
dur-week          = 1*DIGIT "W"
dur-month         = 1*DIGIT "M" [dur-day]
dur-year          = 1*DIGIT "Y" [dur-month]
dur-date          = (dur-day / dur-month / dur-year) [dur-time]

duration          = "P" (dur-date / dur-time / dur-week)

Periods: ๐ŸŽ€

period-explicit   = iso-date-time "/" iso-date-time
period-start      = iso-date-time "/" duration
period-end        = duration "/" iso-date-time

period            = period-explicit / period-start / period-end

Appendix B. Day of the Week ๐Ÿ“…

here's a sample C subroutine, loosely based on Zeller's Congruence [Zeller], that you can use to get the day of the week for dates on or after 0000-03-01 ๐Ÿงš

char *day_of_week(int day, int month, int year)
{
   int cent;
   char *dayofweek[] = {
      "Sunday", "Monday", "Tuesday", "Wednesday",
      "Thursday", "Friday", "Saturday"
   };

   /* adjust months so February is the last one */
   month -= 2;
   if (month < 1) {
      month += 12;
      --year;
   }
   /* split by century */
   cent = year / 100;
   year %= 100;
   return (dayofweek[((26 * month - 2) / 10 + day + year
                     + year / 4 + cent / 4 + 5 * cent) % 7]);
}

Appendix C. Leap Years ๐ŸŒธ

here's a sample C subroutine that works out whether a year is a leap year ๐Ÿฆ‹

/* This returns non-zero if year is a leap year.  Must use 4 digit
   year.
 */
int leap_year(int year)
{
    return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
}

Appendix D. Leap Seconds โฐ

there's info about leap seconds at <http://tycho.usno.navy.mil/leapsec.html>, and it's giving very important energy โœจ It specifically says:

The decision to introduce a leap second in UTC is the responsibility of the International Earth Rotation Service (IERS). According to the CCIR Recommendation, first preference is given to the opportunities at the end of December and June, and second preference to those at the end of March and September.

when a leap second does get added, it's an extra second at the end of a day in UTC, shown with a timestamp like YYYY-MM-DDT23:59:60Z ๐Ÿซ  A leap second happens at the same moment in every time zone, so the time zone relationships don't get messed up. Check section 5.8 for some examples of leap second times ๐Ÿ’–

here's an excerpt from the table kept by the United States Naval Observatory. The source data lives at <ftp://maia.usno.navy.mil/ser7/tai-utc.dat> ๐Ÿ›ฐ๏ธ The table shows the date of each leap second, along with the difference between TAI (which doesn't get adjusted for leap seconds) and UTC after that leap second.

UTC Date  TAI - UTC After Leap Second
--------  ---------------------------
1972-06-30     11
1972-12-31     12
1973-12-31     13
1974-12-31     14
1975-12-31     15
1976-12-31     16
1977-12-31     17
1978-12-31     18
1979-12-31     19
1981-06-30     20
1982-06-30     21
1983-06-30     22
1985-06-30     23
1987-12-31     24
1989-12-31     25
1990-12-31     26
1992-06-30     27
1993-06-30     28
1994-06-30     29
1995-12-31     30
1997-06-30     31
1998-12-31     32

Acknowledgements ๐Ÿซถ

thank you to these legends who gave helpful advice on an earlier version of this doc: Ned Freed, Neal McBurnett, David Keegel, Markus Kuhn, Paul Eggert and Robert Elz ๐Ÿ’œ Thanks also to everyone on the IETF Calendaring/Scheduling working group mailing list, and the folks on the time zone mailing list ๐ŸŒˆ

for this revision, the reviewers who helped with suggestions were Tom Harsch, Markus Kuhn, Pete Resnick and Dan Kohn ๐Ÿ‘‘ Paul Eggert made lots of careful observations about the subtleties of leap seconds and time zone offsets ๐Ÿคฏ And these people pointed out corrections and improvements to earlier drafts: Dr John Stockton, Jutta Degener, Joe Abley, and Dan Wing ๐Ÿ“


Authors' Addresses ๐Ÿ’Œ

Chris Newman
Sun Microsystems
1050 Lakes Drive, Suite 250
West Covina, CA 91790 USA

EMail: chris.newman@sun.com


Graham Klyne (editor, this revision)
Clearswift Corporation
1310 Waterside
Arlington Business Park
Theale, Reading  RG7 4SA
UK

Phone: +44 11 8903 8903
Fax:   +44 11 8903 9000
EMail: GK@ACM.ORG

the legal bit is kept word for word below so nothing gets lost in translation ๐Ÿ™

Copyright (C) The Internet Society (2002).  All Rights Reserved.

This document and translations of it may be copied and furnished to
others, and derivative works that comment on or otherwise explain it
or assist in its implementation may be prepared, copied, published
and distributed, in whole or in part, without restriction of any
kind, provided that the above copyright notice and this paragraph are
included on all such copies and derivative works.  However, this
document itself may not be modified in any way, such as by removing
the copyright notice or references to the Internet Society or other
Internet organizations, except as needed for the purpose of
developing Internet standards in which case the procedures for
copyrights defined in the Internet Standards process must be
followed, or as required to translate it into languages other than
English.

The limited permissions granted above are perpetual and will not be
revoked by the Internet Society or its successors or assigns.

This document and the information contained herein is provided on an
"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.

Acknowledgement ๐Ÿ’–

the RFC Editor function is currently funded by the Internet Society ๐ŸŽ€ and that's the end of the doc, bestie! ๐ŸŒˆโœจ

๐Ÿ“ฆ where this page comes from