RFC Errata
RFC 9562, "Universally Unique IDentifiers (UUIDs)", May 2024
Source of RFC: uuidrev (art)See Also: RFC 9562 w/ inline errata
Errata ID: 8288
Status: Verified
Type: Technical
Publication Format(s) : TEXT, PDF, HTML
Reported By: Nathan McGarvey
Date Reported: 2025-02-08
Verifier Name: Orie Steele
Date Verified: 2025-02-24
Section 6.1 says:
Length: The length of a given timestamp directly impacts how many timestamp ticks can be contained in a UUID before the maximum value for the timestamp field is reached. Take care to ensure that the proper length is selected for a given timestamp. UUIDv1 and UUIDv6 utilize a 60-bit timestamp valid until 5623 AD; UUIDv7 features a 48-bit timestamp valid until the year 10889 AD.
It should say:
Length: The length of a given timestamp directly impacts how many timestamp ticks can be contained in a UUID before the maximum value for the timestamp field is reached. Take care to ensure that the proper length is selected for a given timestamp. UUIDv1 and UUIDv6 utilize a 60-bit timestamp valid until 5236 AD; UUIDv7 features a 48-bit timestamp valid until the year 10889 AD.
Notes:
I believe the error is the result of a bad calculation that used the Unix epoch as the zero-date instead of the Gregorian calendar's 1582 zero-date. I've seen online references to the following [incorrect] calculation for determining the UUIDv1 maximum date: (2^60 / 10^7 / 60 / 60 / 24 / 365.25 + 1970) = 5623.38778807. Source: https://github.com/uuid6/uuid6-ietf-draft/issues/23#issuecomment-898866487
That is: (bitsOfTimeData / 100 nanoseconds / secondsPerMin / minutesPerHour / hoursPerDay / daysPerYear + unixEpochYear). However, the max date for v1 and v6 is based, not on the Unix epoch year, but on the year 1582 (Ref: section 5.1).
The same calculation, but using 1582 as the trailing year added, is 5235.38778807.
Doing manual math approximation:
60 bits = 2^60 = 1152921504606846976 one-hundred-nano-second-intervals
1152921504606846976 * 100 = 115292150460684697600 nanoseconds
115292150460684697600 nanoseconds / 31557600000000000 nanosecondPerYear (365.25 daysPerYear assumed) =~ 3653.3878 years.
Date math: 1582.7890 + 3653.3878 years = 5236.1768 =~ March of 5236
Exact date math spot checking using a couple of programming languages calculators:
Go:
package main
import (
"fmt"
"time"
)
func main() {
t := time.Date(1582, 10, 15, 0, 0, 0, 0, time.UTC)
for _ = range 100 {
t = t.Add(1152921504606846976)
}
fmt.Println(t)
}
Output: 5236-03-31 21:21:00.6846976 +0000 UTC
Python:
from datetime import datetime, timedelta, timezone
start_date = datetime(1582, 10, 15, tzinfo=timezone.utc)
nanoseconds = 115292150460684697600
seconds = nanoseconds // 1_000_000_000 # Convert to seconds
remaining_nanoseconds = nanoseconds % 1_000_000_000
microseconds = remaining_nanoseconds // 1000 # Convert remaining to microseconds
delta = timedelta(seconds=seconds, microseconds=microseconds)
result_date = start_date + delta
print(result_date)
Output: 5236-03-31 21:21:00.684697+00:00
Javascript:
const startDate = new Date(Date.UTC(1582, 9, 15)); // Month is 0-based in JS
const nanoseconds = BigInt('115292150460684697600');
const milliseconds = Number(nanoseconds / BigInt(1_000_000));
const resultDate = new Date(startDate.getTime() + milliseconds);
console.log(resultDate.toUTCString());
Output: Mon, 31 Mar 5236 21:21:00 GMT