From 330a018202e565a3bc5c9319590fb9155edfb904 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Hatcher=20Andr=C3=A9s?= Date: Sun, 19 Oct 2025 15:38:11 +0200 Subject: [PATCH] FIX: Adds test for TIME/HOUR/MINUTE/SECOND (#456) --- base/src/functions/date_and_time.rs | 12 ++++++------ .../calc_tests/TIME_HOUR_MINUTE_SECOND.xlsx | Bin 0 -> 10385 bytes 2 files changed, 6 insertions(+), 6 deletions(-) create mode 100644 xlsx/tests/calc_tests/TIME_HOUR_MINUTE_SECOND.xlsx diff --git a/base/src/functions/date_and_time.rs b/base/src/functions/date_and_time.rs index 788695a..1d8ceb2 100644 --- a/base/src/functions/date_and_time.rs +++ b/base/src/functions/date_and_time.rs @@ -66,6 +66,7 @@ use crate::formatter::dates::date_to_serial_number; use crate::formatter::dates::permissive_date_to_serial_number; use crate::formatter::dates::DATE_OUT_OF_RANGE_MESSAGE; use crate::model::get_milliseconds_since_epoch; +use crate::number_format::to_precision; use crate::{ calc_result::CalcResult, constants::EXCEL_DATE_BASE, @@ -1001,17 +1002,16 @@ impl Model { Ok(f) => f, Err(e) => return e, }; - if hour < 0.0 || minute < 0.0 || second < 0.0 { + let total_seconds = hour.floor() * 3600.0 + minute.floor() * 60.0 + second.floor(); + if total_seconds < 0.0 { return CalcResult::Error { error: Error::NUM, origin: cell, message: "Invalid time".to_string(), }; } - let total_seconds = hour.floor() * 3600.0 + minute.floor() * 60.0 + second.floor(); - let day_seconds = 24.0 * 3600.0; - let secs = total_seconds.rem_euclid(day_seconds); - CalcResult::Number(secs / day_seconds) + let secs = total_seconds.rem_euclid(SECONDS_PER_DAY_F64); + CalcResult::Number(secs / SECONDS_PER_DAY_F64) } // ----------------------------------------------------------------------- @@ -1024,7 +1024,7 @@ impl Model { ((total_seconds / 60.0) as i64 % 60) as f64 }); time_part_fn!(fn_second, |v: f64| { - let total_seconds = (v.rem_euclid(1.0) * SECONDS_PER_DAY_F64).floor(); + let total_seconds = to_precision(v.rem_euclid(1.0) * SECONDS_PER_DAY_F64, 15).floor(); (total_seconds as i64 % 60) as f64 }); diff --git a/xlsx/tests/calc_tests/TIME_HOUR_MINUTE_SECOND.xlsx b/xlsx/tests/calc_tests/TIME_HOUR_MINUTE_SECOND.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..b29d643af0999a336b3f1dc3807088b26ce6b322 GIT binary patch literal 10385 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