Merge PR #2963: Keep seconds in FormCalc Time2Num/IsoTime2Num for ISO 8601 times

This commit is contained in:
aiongg
2026-10-22 01:44:49 +00:00
2 changed files with 13 additions and 3 deletions
+10 -3
View File
@@ -2394,9 +2394,16 @@ impl Interp<'_> {
}
"time2num" | "isotime2num" => {
let s = self.arg_str(args, 0)?;
let parts: Vec<u64> = s.split(':').filter_map(|p| p.trim().parse::<u64>().ok()).map(|v| v.min(1_000_000)).collect();
let (h, m, sec) = (parts.first().copied().unwrap_or(0), parts.get(1).copied().unwrap_or(0), parts.get(2).copied().unwrap_or(0));
Val::Num(((h * 3600 + m * 60 + sec) * 1000) as f64)
// ISO 8601 allows a leading "T", a trailing "Z" and fractional seconds.
let t = s.trim();
let t = t.strip_prefix(['T', 't']).unwrap_or(t);
let t = t.strip_suffix(['Z', 'z']).unwrap_or(t);
let mut parts = t.split(':');
let mut whole = || parts.next().and_then(|p| p.trim().parse::<u64>().ok()).unwrap_or(0).min(1_000_000);
let (h, m) = (whole(), whole());
let sec =
parts.next().and_then(|p| p.trim().parse::<f64>().ok()).filter(|v| v.is_finite() && *v >= 0.0).unwrap_or(0.0).min(1_000_000.0);
Val::Num(((h * 3600 + m * 60) * 1000) as f64 + (sec * 1000.0).round())
}
// ── financial
"fv" => {
+3
View File
@@ -719,6 +719,9 @@ mod formcalc {
assert_eq!(calc(r#"Num2Date(45350, "YYYY-MM-DD")"#), "2024-02-29");
assert_eq!(calc(r#"Num2Date(Date2Num("2024-02-29") + 1, "MMMM D, YYYY")"#), "March 1, 2024");
assert_eq!(calc(r#"Time2Num("01:00:00")"#), "3600000");
assert_eq!(calc(r#"IsoTime2Num("12:30:45Z")"#), "45045000");
assert_eq!(calc(r#"IsoTime2Num("12:30:45.250")"#), "45045250");
assert_eq!(calc(r#"IsoTime2Num("T12:30:45")"#), "45045000");
assert_eq!(calc(r#"Num2Time(3661000)"#), "01:01:01");
assert_eq!(calc("Round(Pmt(10000, 0.01, 12), 2)"), "888.49");
assert_eq!(calc("Round(FV(100, 0.01, 12), 2)"), "1268.25");