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.