Skip to main content

Appendix D. Leap Seconds

This appendix details the concept, history, and handling of leap seconds in RFC 3339.

What are Leap Seconds?

A leap second is occasionally added to Coordinated Universal Time (UTC) to keep UTC synchronized with Earth's rotation.

Why Leap Seconds?

Atomic Time (TAI):

  • Based on atomic clocks, extremely stable
  • 1 second = 9,192,631,770 cesium atom oscillations
  • Never changes

Earth's Rotation:

  • Not perfectly uniform
  • Affected by tidal friction
  • Gradually slowing (~1.4ms/day per century)
  • Rate unpredictable

How Leap Seconds Work

Positive Leap Second Example

Normal month end:
23:59:58
23:59:59
00:00:00 (next day)

With positive leap second:
23:59:58
23:59:59
23:59:60 ← Leap second!
00:00:00 (next day)

RFC 3339 Representation

1990-12-31T23:59:60Z  ✅ Valid (leap second on Dec 31, 1990)
2012-06-30T23:59:60Z ✅ Valid (leap second on Jun 30, 2012)
2015-06-30T23:59:60Z ✅ Valid (leap second on Jun 30, 2015)
2016-12-31T23:59:60Z ✅ Valid (leap second on Dec 31, 2016)

Historical Leap Seconds

Since UTC introduction in 1972:

Date          UTC Time         TAI-UTC
1972-06-30 23:59:60Z +11s
1972-12-31 23:59:60Z +12s
1990-12-31 23:59:60Z +26s
2012-06-30 23:59:60Z +35s
2015-06-30 23:59:60Z +36s
2016-12-31 23:59:60Z +37s (most recent)

Note:

  • Leap seconds only added on June 30 or December 31
  • 27 leap seconds added since 1972
  • Latest was December 31, 2016

Programming Considerations

Problem: Most Systems Don't Support Leap Seconds

# Lenient parsing for leap seconds
def parse_rfc3339_with_leap_seconds(timestamp_str):
if ':60' in timestamp_str:
# Replace 60 seconds with 59
timestamp_str = timestamp_str.replace(':60', ':59')
dt = datetime.fromisoformat(timestamp_str.replace('Z', '+00:00'))
return dt + timedelta(seconds=1)
else:
return datetime.fromisoformat(timestamp_str.replace('Z', '+00:00'))

RFC 3339 Specification

Syntax Requirement

time-second = 2DIGIT  ; 00-58, 00-59, 00-60 based on leap second rules
  • Second value MAY be 60
  • Only at month end
  • Must be a published leap second

Key Point: RFC 3339 allows leap seconds but most implementations map them to the following second for practical compatibility.