Dates: add `Timestamp{P}` and fractional-second format code `n` (#62994)
* Dates: add nanosecond-precision `Timestamp` and fractional-second format code `n`
`Timestamp` is an `AbstractDateTime` wrapping `UTInstant{Nanosecond}`: an
`Int64` count of nanoseconds since the unix epoch 1970-01-01T00:00:00 — the
physical representation shared by Apache Arrow's timestamp[ns], numpy's
datetime64[ns], and pandas — making it 8 bytes, isbits, and buffer-compatible
with nanosecond-timestamp columns from those systems. Nanosecond resolution
in 64 bits bounds the representable range to 1677-09-21 through 2262-04-11;
constructors validate the range with an Int64 comparison of
(days, nanoseconds-of-day) against the type's bounds, while arithmetic is
fixed-point and wraps at the ends of the range exactly as `DateTime`'s does.
The type plugs into the existing generic machinery rather than duplicating
it: calendrical accessors and query functions flow through `days`; calendar
period arithmetic (Year/Quarter/Month) and rounding to date periods go
through `Date`, so end-of-month clamping and rounding results match
`DateTime`; rounding to time periods is anchored at the ISO epoch
0000-01-01, again matching `DateTime`; adjusters, function-based adjuster
constructors, ranges, and `DateFormat` parsing/formatting are supported.
`Timestamp` promotes with `Date` and `DateTime`; equality and ordering
against those types bypass promotion and compare (day, time-of-day) pairs so
comparisons against instants outside the `Timestamp` range cannot throw, and
`hash` is now defined consistently with `==` across `Date`, `DateTime`, and
`Timestamp`, so equal instants of different types hash alike.
`now(Timestamp)` and `now(Timestamp, UTC)` read the system clock at full
resolution via libuv's `uv_clock_gettime`.
A new `n` format code parses and formats fractional seconds at up to
nanosecond resolution (".5" is 500 milliseconds, ".123456789" is 123456789
nanoseconds; digits past the ninth must be zero, and fixed-width fields
truncate to their declared width). The default `Time` format now uses it,
fixing the round-trip failure where `Time` printed sub-millisecond values
that its own default format could not re-parse, and the `Time`
constructor's nanosecond argument may now carry a full fractional second.
Parsing a `DateTime` with `n` requires the fraction to be exactly
representable in milliseconds. The `firstdayof*`/`lastdayof*` adjusters and
the `Time(dt)` constructor funnel are generalized from `::DateTime` to
`::AbstractDateTime` so any `AbstractDateTime` subtype inherits them.
Assisted-by: Claude Code (Fable 5)
Assisted-by: Claude Code (Fable 5.1)
Assisted-by: Codex CLI (gpt-5.6-sol)
* Dates: tighten the `Timestamp` docstring
Lead with the representation — an Int64 count of nanoseconds since the Unix
epoch — followed by the range, the overflow behavior, and the guidance
relative to `DateTime`, and move the Arrow, numpy, and pandas
interoperability notes into extended help, dropping the time zone remark.
Assisted-by: Claude Code (Fable 5.1)
* Dates: make the `Timestamp` tests 32-bit clean
The `validargs` probe passed bare integer literals, which are `Int32` on
32-bit hosts and match no `Int64`-typed method, and `2^55` overflowed
`Int32` so the exact range-length check was vacuous there. Failed in CI on
i686 Linux and Windows:
https://buildkite.com/julialang/julia-pr/builds/2035#01a067f0-8c34-426c-a7cc-13304fccb9a9
https://buildkite.com/julialang/julia-pr/builds/2035#01a067f0-8c36-4932-9801-10317cbf3a9f
Assisted-by: Claude Code (Fable 5.1)
* Dates: parameterize Timestamp by resolution
Support second, millisecond, microsecond, and nanosecond timestamps with
Int64 Unix counts. Preserve resolution through construction and arithmetic,
and require exact representation when converting to a coarser unit.
Keep epoch and storage fixed while sharing calendar operations, parsing,
formatting, and promotion across the four resolutions. Check rounding and
range lengths at storage boundaries, and retain wrapping ordinary arithmetic.
Assisted-by: Codex (GPT-6)
Assisted-by: Claude Desktop (Fable 5.1)
* Dates: simplify `Timestamp` docs, comments, and helpers
Rewrite the `Timestamp` docstrings, the manual section, and the NEWS entries
to say what the type does in fewer words. Drop text that described the change
instead of the API, and drop compat notes on functions that only gained
`Timestamp` methods. Code comments now describe the code next to them; one
test comment said that rounding wraps, but it throws.
Reuse existing machinery where it gives the same results: `Period`
conversions for raw counts, period promotion to pick the finer resolution,
and one (day, nanosecond of day) key for mixed comparisons and hashing.
Calendar-period arithmetic wraps in plain `Int64`, which gives the same bits
as the former `Int128` path. The `DateFormat` docs now advise escaping every
literal letter, because new codes such as `n` can be added.
Assisted-by: Claude Code (Opus 5.5)
* Dates: allow package-defined Timestamp periods
Let the period supply its count width and exact scale so packages can add resolutions such as Int128 picoseconds without another Timestamp representation. Use the same scale interface for conversion, promotion, arithmetic, and bounds.
Assisted-by: Codex (GPT-6)
* Dates: make the package-period `Timestamp` test 32-bit clean
The year `10^18` is `Int32` arithmetic on 32-bit hosts and wraps to
-1486618624, a year that `Date` can represent, so `Date(T(10^18))` did not
throw. Use `Int64(10)^18`. Failed in CI on i686 Windows:
https://buildkite.com/julialang/julia-pr/builds/2861#01a0d5b6-d424-4a7f-9de1-47ec5f4f5f55
Assisted-by: Claude Code (Opus 5.5)
* Dates: plain wording for the package-defined `Timestamp` period docs
Rewrite the docs and comments added for package-defined periods in plain
words. The docstring said a package period needs `timestamp_scale`, but
arithmetic, rounding, and ranges with the period call `Dates.tons`, and
`timestamp_scale` falls back to `tons`. The package-period tests pass with
`tons` alone, so the docstring now names `tons`. The rounding comment no
longer says that the bounds are always `Int128`: they are `Rational` for
periods shorter than a nanosecond.
Assisted-by: Claude Code (Opus 5.5)
* Dates: round sub-nanosecond digits down when printing a `Timestamp`
A `Timestamp` of a package-defined period finer than a nanosecond could not
be printed: `subsecond_nanoseconds` returned a `Rational`, which the
fractional-second formatter cannot pad, so `show`, `string`, and the `n`
format code threw a `MethodError`, even for a whole number of nanoseconds.
Round down to whole nanoseconds, the precision of the `n` code, as the `s`
code already does with digits finer than a millisecond.
Assisted-by: Claude Code (Opus 5.5)
* Dates: simplify `Timestamp` docs and comments
Another plain-wording pass over the docstrings, comments, and NEWS added for
`Timestamp`. Say "has more precision than `P`" instead of four variants of
"is not a whole number of `P`", say "a full fraction of a second" for the
`ns` argument, and shorten the adjuster docstring and the rounding, fraction,
and field comments.
Assisted-by: Claude Code (Opus 5.5)
* Dates: tighten Timestamp extension and conversion boundaries
Resolve equal-resolution promotion using count width and period promotion, reject unsupported timestamp scales, and avoid intermediate overflow for rational Unix seconds. Preserve millisecond formatting and expose Timestamp as a public, unexported API.
Assisted-by: Codex (GPT-6)
* Dates: link the manual's `Timestamp` references to `Dates.Timestamp`
`Timestamp` is public but no longer exported, so `[`Timestamp`](@ref)` in the
Dates manual cannot resolve and `makedocs` stops the docs build. Name the
target explicitly. Failed in CI on the macOS aarch64 build:
https://buildkite.com/julialang/julia-pr/builds/3096#01a0e901-d841-4811-bb62-add30c40c7d5
Assisted-by: Claude Code (Opus 5.5)
* Dates: plain wording for the `Timestamp` period rules
Say that one unit must divide a second evenly, and how promotion chooses
between two periods with the same unit, in plain words.
Assisted-by: Claude Code (Opus 5.5)
* Dates: make the `Timestamp` helpers public but not exported
`Timestamp` is public but not exported, so exporting `unix2timestamp`,
`timestamp2unix`, and `ISOTimestampFormat` let `using Dates` code create
values whose type it cannot name without the `Dates.` prefix. Make the three
helpers public and unexported like `Timestamp`, and qualify or import them in
the manual, the docstring examples, and the tests.
Assisted-by: Claude Code (Opus 5.5)
* Dates: preserve exact Timestamp arithmetic and wide counts
Compute custom-period arithmetic and calendar fields using the complete
nanosecond scale, including fractional scales. Widen stored counts before
conversion, rounding, and range estimates so supported Int128 periods retain
exact results and reject out-of-range conversions. Construct the local clock
from whole seconds and raw ticks to support fractional resolutions.
Assisted-by: Codex (GPT-6.1 Sol)
* Dates: keep Timestamp constructor errors compatible with trim
Describe the period resolution and calendar bounds with concrete string
operations instead of printing Timestamp types and values. This ports the
constructor-error approach from JuliaData/Durations.jl and allows native
Timestamp construction errors to compile under safe trimming.
Assisted-by: Codex (GPT-6.1 Sol)
* Dates: require exact Timestamp period scale representations
Require Integer or Rational nanoseconds per physical period unit, rejecting
floating-point metadata even when it is 1.0. A floating unit previously
rounded counts above 2^53 during conversion and other Timestamp operations.
Apply the same validation to raw conversions, period arithmetic, rounding,
and physical range steps. Preserve the calendar range estimate used for
months, quarters, and years.
Assisted-by: Codex (GPT-6.1 Sol)