Skip to content

Read and write an instant as ISO 8601#15

Merged
rhannequin merged 2 commits into
mainfrom
iso8601-representation
Jul 24, 2026
Merged

Read and write an instant as ISO 8601#15
rhannequin merged 2 commits into
mainfrom
iso8601-representation

Conversation

@rhannequin

Copy link
Copy Markdown
Owner

Add the ISO 8601 representation. instant.as(:iso8601, scale:) writes an instant as an extended ISO 8601 date and time, and Instant.from_iso8601 reads one back. It formats the calendar date the civil representation reads, so their fields match.

The scale is not part of the string. There is no ISO 8601 designator for TAI or TT, and Z means UTC, so a bare time is a coordinate in the scale passed to the call. This matches astropy.time, which keeps the scale on the object rather than in the string. UTC will write Z when it lands.

The fraction of a second is written to nanosecond resolution. The instant is rounded onto the nanosecond grid first, so a fraction that would round up moves into the next second. The parser reads a strict subset: a full date, an optional time after a T, a fraction of any length, and an optional Z or numeric offset applied as arithmetic. Anything else raises ParseError.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an ISO 8601 string representation for Horologium::Instant, enabling round-trippable serialization via instant.as(:iso8601, scale:) and parsing via Instant.from_iso8601, aligned with the library’s “scale lives on the object, not the string” model.

Changes:

  • Introduces Representations::Iso8601 to render instants as extended ISO 8601 with nanosecond resolution and parse a strict subset (date, optional time, optional fraction, optional offset).
  • Adds Instant.from_iso8601 and registers :iso8601 as a ScaleReading representation.
  • Adds comprehensive ISO 8601 tests and updates README and RBS signatures accordingly.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
test/test_scale_reading.rb Updates known representations list to include :iso8601.
test/representations/test_iso8601.rb Adds coverage for ISO 8601 rendering/parsing behavior and refusal cases.
sig/horologium/scale_reading.rbs Extends REPRESENTATIONS type union to include Iso8601.
sig/horologium/representations/iso8601.rbs Adds RBS for the new ISO 8601 representation API.
sig/horologium/instant.rbs Adds Instant.from_iso8601 signature.
README.md Documents ISO 8601 usage and the supported parsing subset.
lib/horologium/scale_reading.rb Registers the new :iso8601 representation.
lib/horologium/representations/iso8601.rb Implements ISO 8601 rendering/parsing logic.
lib/horologium/instant.rb Adds Instant.from_iso8601 entry point.
lib/horologium/data/barycentric_model.rb Minor documentation wording change.
lib/horologium.rb Requires the new representation file.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/horologium/representations/iso8601.rb
Comment thread lib/horologium/representations/iso8601.rb
@rhannequin
rhannequin force-pushed the iso8601-representation branch from 98e0cd9 to 8100378 Compare July 24, 2026 13:18
Base automatically changed from civil-representation to main July 24, 2026 14:29
Add the ISO 8601 representation. `instant.as(:iso8601, scale:)` writes an
instant as an extended ISO 8601 date and time, and `Instant.from_iso8601`
reads one back. It formats the calendar date the civil representation
reads, so their fields match.

The scale is not part of the string. There is no ISO 8601 designator for
TAI or TT, and `Z` means UTC, so a bare time is a coordinate in the scale
passed to the call. This matches astropy.time, which keeps the scale on
the object rather than in the string. UTC will write `Z` when it lands.

The fraction of a second is written to nanosecond resolution. The instant
is rounded onto the nanosecond grid first, so a fraction that would round
up moves into the next second. The parser reads a strict subset: a full
date, an optional time after a T, a fraction of any length, and an
optional Z or numeric offset applied as arithmetic. Anything else raises
ParseError.
@rhannequin
rhannequin force-pushed the iso8601-representation branch from 8100378 to 7348c29 Compare July 24, 2026 14:30
@rhannequin
rhannequin merged commit 82db24a into main Jul 24, 2026
44 checks passed
@rhannequin
rhannequin deleted the iso8601-representation branch July 24, 2026 14:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants