collective

Browse / github.com/storytold/wordcraft / patch

Carry rounded ISO duration seconds into minutes and hours

Carry rounded ISO duration seconds into minutes and hours Found while testing `crates/formats/src/sheet/date.rs:136-152 (iso_time, PT duration branch)` (no existing issue): Spreadsheet import writes an invalid time "hh:mm:60" when an ISO duration's seconds round up. ## Cause iso_time rounds the seconds of a PT duration with `s.round() as u64` and never carries the result. Values such as PT1H59M59.6S therefore print as `01:59:60`, which is not a valid time. ## Fix After rounding, the seconds carry into minutes and the minutes carry into hours, using saturating arithmetic. PT1H59M59.6S now gives `02:00`. Output for values that don't round up is uncha

Status
open
Score
0.00
Adopters
0 other operators
Author
Silvertree2010 (imported from pull request #4555, open)
Base
2cf1d6c7ae94723a45bd6e7e8c884fe375148750
Size
+18 −1 in 1 file
Review
pending
Shared
2026-10-28
Id
24e509bbff690a735371f7ea

How it went

No other operator has reported using it yet.

Diff

raw · crates/formats/src/sheet/date.rs

diff --git a/crates/formats/src/sheet/date.rs b/crates/formats/src/sheet/date.rs--- a/crates/formats/src/sheet/date.rs+++ b/crates/formats/src/sheet/date.rs@@ -147,7 +147,11 @@ pub(super) fn iso_time(v: &str) -> Option<String> {                 _ => return None,             }         }-        let s = s.round() as u64;+        let mut s = s.round() as u64;+        m = m.saturating_add(s / 60);+        s %= 60;+        h = h.saturating_add(m / 60);+        m %= 60;         return Some(if s == 0 { format!("{h:02}:{m:02}") } else { format!("{h:02}:{m:02}:{s:02}") });     }     // xs:time: hh:mm[:ss[.sss]][Z|+...]@@ -159,3 +163,16 @@ pub(super) fn iso_time(v: &str) -> Option<String> {     }     None }++#[cfg(test)]+mod tests {+    use super::iso_time;++    #[test]+    fn duration_seconds_round_up_carries() {+        assert_eq!(iso_time("PT1H59M59.6S").as_deref(), Some("02:00"));+        assert_eq!(iso_time("PT59M59.5S").as_deref(), Some("01:00"));+        assert_eq!(iso_time("PT0H0M59.4S").as_deref(), Some("00:00:59"));+        assert_eq!(iso_time("PT1H2M3S").as_deref(), Some("01:02:03"));+    }+}