date-time-wars · itu-1.16.0

69 benchmarks · 10 candidates · ns/op, lower is better · 25.0.4 · 13th Gen Intel(R) Core(TM) i9-13900H · 2026-09-21

Summary

ITU against JDK java.time, one row per operation. Spans cover the inputs of that operation; the speed-up is JDK java.time time divided by ITU time, per input. The other candidates are in the sections below.

ITU speed-up over JDK java.time per operation, log scale 0.5× parity 2× 5× 10× 20× 50× 100× 200× 500× 1,000× × faster than JDK java.time, log scale parse 21–30× parseLenient 46–67× isValid 43–669× formatSeconds 6.3× formatMillis 6.1× formatNanos 3.5× parseDuration 4.8–5.4× formatDuration 0.7–1.2×
OperationWhatInputsITUJDK java.timeSpeed-upFastest overall
Date-time parsing
parsestrict RFC-3339 / ISO-8601 date-time318–28542–57721–30×ITU
parseLenientlenient date-time (optional fields)311–17755–78846–67×ITU (char[] buffer)
isValidstrict RFC-3339 validity check, valid and invalid inputs72–13536–2,39743–669×ITU
Date-time formatting
formatSecondsformat UTC, second resolution1161006.3×ITU
formatMillisformat UTC, millisecond resolution1191156.1×ITU
formatNanosformat UTC, nanosecond resolution1331153.5×ITU
Duration
parseDurationISO-8601 duration225–52134–2474.8–5.4×ITU
formatDurationISO-8601 duration214–2710–310.7–1.2×ITU

Times in ns/op. “Fastest overall” counts every candidate except the reference rows, which are not date-time parsers.

Candidates

CandidateLibraryVersionUnder test
ITUITU - Internet Time Utility1.16.0ITU.parseDateTime, parseLenient, isValid, formatUtc*, parseDuration and Duration.normalized()
ITU (configurable)ITU - Internet Time Utility1.16.0ConfigurableDateTimeParser with a token layout of yyyy-MM-ddTHH:mm:ss[.fff]+offset, the same inputs as the fixed parser
ITU (char[] buffer)ITU - Internet Time Utility1.16.0ITU.parseLenient over a char[] window into a reusable MutableDateTimeBuffer - the zero-allocation path
ITU (hours)ITU - Internet Time Utility1.16.0Duration.normalized(HOURS), so it decomposes a duration the way java.time.Duration.toString() does
JDK java.timeJDK java.time25.0.4OffsetDateTime.parse, a DateTimeFormatterBuilder layout with optional parts for lenient parsing, parse-and-catch for isValid, Duration.parse / toString
JDK InstantJDK java.time25.0.4Instant.parse - the fastest built-in path for RFC-3339 input
Google HTTP clientGoogle HTTP client1.46.1DateTime.parseRfc3339ToSecondsAndNanos
Epoch millisreferenceJDK java.time25.0.4Long.parseLong / Long.toString on the epoch count - the number an API would carry instead of a date-time string. Not a parser; a reference for the “epoch is faster” argument
ITU (epoch millis)referenceITU - Internet Time Utility1.16.0ITU.parseEpochMilli on the same epoch-millis text, into the same DateTime the string parsers produce - the epoch argument measured to a temporal value, not to a long
ITU (epoch millis, char[] buffer)referenceITU - Internet Time Utility1.16.0ITU.parseEpochMilli over a char[] window into a reusable MutableDateTimeBuffer - the zero-allocation path for epoch text, the like-for-like of the char[] buffer row

Date-time parsing

parse strict RFC-3339 / ISO-8601 date-time

ITUITU (configurable)JDK java.timeJDK InstantGoogle HTTP client
parse - ns/op, lower is better 0 200 400 600 800 ns/op 2023-01-01T23:38:34.987654321+06:00 27.7 79.4 577 437 674 3074-07-01T12:02:01Z 18.3 60.4 542 407 499 5050-01-01T12:02:01.123Z 20.0 63.4 549 433 587
InputITUITU (configurable)JDK java.timeJDK InstantGoogle HTTP client
2023-01-01T23:38:34.987654321+06:0027.7 ±0.4fastest96 B/op-15.3% vs baseline79.4 ±2.12.87×248 B/opnew577 ±17.420.84×1,592 B/opnew437 ±7.415.79×1,760 B/opnew674 ±20.524.35×1,572 B/opnew
3074-07-01T12:02:01Z18.3 ±0.3fastest96 B/op-8.9% vs baseline60.4 ±1.33.30×224 B/opnew542 ±9.929.55×1,480 B/opnew407 ±6.222.19×1,568 B/opnew499 ±11.727.24×1,272 B/opnew
5050-01-01T12:02:01.123Z20.0 ±0.3fastest96 B/op-24.0% vs baseline63.4 ±0.93.17×224 B/opnew549 ±10.827.46×1,536 B/opnew433 ±6.921.65×1,680 B/opnew587 ±15.929.34×1,480 B/opnew

parseLenient lenient date-time (optional fields)

ITUITU (char[] buffer)JDK java.timeEpoch millisITU (epoch millis)ITU (epoch millis, char[] buffer)
parseLenient - ns/op, lower is better 0 200 400 600 800 1,000 ns/op 2023-01-01T23:38:34.987654321+06:00 17.0 14.8 787 12.1 18.6 17.5 3074-07-01T12:02:01Z 11.3 9.11 755 12.8 19.0 18.9 5050-01-01T12:02:01.123Z 12.8 10.0 788 12.8 19.1 18.9
InputITUITU (char[] buffer)JDK java.timeEpoch millisITU (epoch millis)ITU (epoch millis, char[] buffer)
2023-01-01T23:38:34.987654321+06:0017.0 ±0.31.40×80 B/op-30.9% vs baseline14.8 ±0.21.22×0 B/opnew787 ±10.664.87×2,808 B/opnew12.1 ±0.2fastest0 B/opnew18.6 ±0.31.53×56 B/opnew17.5 ±0.31.45×0 B/opnew
3074-07-01T12:02:01Z11.3 ±0.21.24×56 B/op-18.8% vs baseline9.11 ±0.1fastest0 B/opnew755 ±15.682.86×2,616 B/opnew12.8 ±0.21.40×0 B/opnew19.0 ±0.22.09×56 B/opnew18.9 ±0.32.07×0 B/opnew
5050-01-01T12:02:01.123Z12.8 ±0.21.27×56 B/op-37.9% vs baseline10.0 ±0.1fastest0 B/opnew788 ±14.178.50×2,784 B/opnew12.8 ±0.21.27×0 B/opnew19.1 ±0.31.91×56 B/opnew18.9 ±0.21.88×0 B/opnew

isValid strict RFC-3339 validity check, valid and invalid inputs

ITUJDK java.time
isValid - ns/op, lower is better 0 500 1,000 1,500 2,000 2,500 ns/op 2023-01-01T23:38:34.987654321+06:00 12.9 559 3074-07-01T12:02 1.59 1,065 3074-07-01T12:02:01Z 7.68 545 3074-07-01T12:02:01Zjunk 7.75 1,253 3074-13-01T12:02:01Z 6.94 2,397 5050-01-01T12:02:01.123Z 10.5 536 not-a-date 1.60 809
InputITUJDK java.time
2023-01-01T23:38:34.987654321+06:0012.9 ±0.2fastest0 B/op-60.5% vs baseline559 ±11.343.22×1,592 B/opnew
3074-07-01T12:021.59 ±0.0fastest0 B/op-99.8% vs baseline1,065 ±23.4669.26×1,640 B/opnew
3074-07-01T12:02:01Z7.68 ±0.1fastest0 B/op-62.0% vs baseline545 ±10.170.93×1,480 B/opnew
3074-07-01T12:02:01Zjunk7.75 ±0.1fastest0 B/op-99.2% vs baseline1,253 ±21.8161.73×2,176 B/opnew
3074-13-01T12:02:01Z6.94 ±0.1fastest0 B/op-99.3% vs baseline2,397 ±39.3345.41×3,596 B/opnew
5050-01-01T12:02:01.123Z10.5 ±0.1fastest0 B/op-56.8% vs baseline536 ±14.551.22×1,536 B/opnew
not-a-date1.60 ±0.0fastest0 B/op-99.9% vs baseline809 ±11.9506.43×1,040 B/opnew

Date-time formatting

formatSeconds · formatMillis · formatNanos one operation per row

ITUJDK java.timeEpoch millis
Date-time formatting - ns/op, lower is better 0 25 50 75 100 125 ns/op formatSeconds 15.9 100 8.80 formatMillis 19.0 115 11.5 formatNanos 33.4 115 17.5
OperationITUJDK java.timeEpoch millis
formatSeconds15.9 ±0.21.81×136 B/op-0.1% vs baseline100 ±1.411.40×256 B/opnew8.80 ±0.1fastest56 B/opnew
formatMillis19.0 ±0.21.65×144 B/op-0.4% vs baseline115 ±2.610.01×256 B/opnew11.5 ±0.7fastest56 B/opnew
formatNanos33.4 ±0.61.91×160 B/op-0.0% vs baseline115 ±1.76.59×264 B/opnew17.5 ±0.5fastest64 B/opnew

Duration

parseDuration ISO-8601 duration

ITUJDK java.time
parseDuration - ns/op, lower is better 0 100 200 300 ns/op -P180DT23H27M19.193964536S 51.6 247 PT2H30M 24.7 134
InputITUJDK java.time
-P180DT23H27M19.193964536S51.6 ±0.9fastest80 B/op+1.1% vs baseline247 ±22.64.79×312 B/opnew
PT2H30M24.7 ±0.4fastest80 B/op-0.1% vs baseline134 ±3.05.45×264 B/opnew

formatDuration ISO-8601 duration

ITUITU (hours)JDK java.time
formatDuration - ns/op, lower is better 0 10 20 30 40 ns/op -P180DT23H27M19.193964536S 27.1 32.3 31.2 PT2H30M 13.8 12.8 9.87
InputITUITU (hours)JDK java.time
-P180DT23H27M19.193964536S27.1 ±0.4fastest168 B/op-0.1% vs baseline32.3 ±0.51.20×160 B/opnew31.2 ±0.61.15×184 B/opnew
PT2H30M13.8 ±0.31.40×144 B/op+1.3% vs baseline12.8 ±0.21.29×144 B/opnew9.87 ±0.1fastest88 B/opnew

Other

parseLenientToEpochSecond

ITU (char[] buffer)
parseLenientToEpochSecond - ns/op, lower is better 0 5 10 15 20 ns/op 2023-01-01T23:38:34.987654321+06:00 17.6 3074-07-01T12:02:01Z 11.7 5050-01-01T12:02:01.123Z 13.3
InputITU (char[] buffer)
2023-01-01T23:38:34.987654321+06:0017.6 ±0.3fastest0 B/opnew
3074-07-01T12:02:01Z11.7 ±0.2fastest0 B/opnew
5050-01-01T12:02:01.123Z13.3 ±0.2fastest0 B/opnew

ns/op per operation; ± is JMH’s 99.9% confidence interval over all measurement iterations. The small figure under each value is the ratio to the fastest candidate on that input.

Environment

Date2026-09-21T18:17:22+02:00 Runitu-1.16.0 JDK25.0.4 (OpenJDK 64-Bit Server VM 25.0.4+7-1-26.04-Ubuntu) JVM args-XX:+UnlockDiagnosticVMOptions -XX:+TieredCompilation -XX:+AlwaysPreTouch Iterations2 fork(s), 3 × 1 s warmup, 10 × 1 s measurement (--thorough) CPU13th Gen Intel(R) Core(TM) i9-13900H OSUbuntu 26.04.1 LTS Git5490c17 Harness floor0.54 ns/op - the JMH loop, state loads and Blackhole with no parsing at all; subtract it from a parse score for the parser's own cost

JMH 1.37. Each run records this in run.properties next to its results; library versions are read from the jar that ran, not from the pom.