diff --git a/crates/core/src/date.rs b/crates/core/src/date.rs index 3b126b7..29bd4b5 100644 --- a/crates/core/src/date.rs +++ b/crates/core/src/date.rs @@ -59,6 +59,14 @@ pub fn serial_from_unix_ms(ms: f64) -> f64 { 25569.0 + ms / 86_400_000.0 } +/// Converts a 1900-system serial (as the clock supplies it) to the serial of the same instant in `sys`. +pub fn serial_in_system(sys: DateSystem, serial_1900: f64) -> f64 { + match sys { + DateSystem::D1900 => serial_1900, + DateSystem::D1904 => serial_1900 - 1462.0, + } +} + pub fn civil_from_days(z: i64) -> (i32, u32, u32) { let z = z + 719468; let era = if z >= 0 { z } else { z - 146096 } / 146097; diff --git a/crates/engine/src/cf.rs b/crates/engine/src/cf.rs index 21a32dd..b71ddb8 100644 --- a/crates/engine/src/cf.rs +++ b/crates/engine/src/cf.rs @@ -184,7 +184,7 @@ impl CfCache { }, CfRule::TimePeriod { period, style } => match v.as_f64() { Some(n) => { - let today = gridcraft_calc::now_serial().floor(); + let today = gridcraft_core::date::serial_in_system(wb.date_system, gridcraft_calc::now_serial()).floor(); let d = n.floor(); let wd = gridcraft_core::date::datetime_from_serial(wb.date_system, today).map(|x| x.weekday as f64).unwrap_or(0.0); let week_start = today - wd; diff --git a/crates/engine/src/cmd/print.rs b/crates/engine/src/cmd/print.rs index 986351e..8ede4e2 100644 --- a/crates/engine/src/cmd/print.rs +++ b/crates/engine/src/cmd/print.rs @@ -391,7 +391,7 @@ pub struct HfContext { /// Today's date and the current time as headers and footers show them (`&D`, `&T`). pub fn hf_date_time(wb: &Workbook) -> (String, String) { - let now = gridcraft_calc::now_serial(); + let now = gridcraft_core::date::serial_in_system(wb.date_system, gridcraft_calc::now_serial()); let date = crate::display::format(&Value::Number(now.floor()), "m/d/yyyy", wb).text; let time = crate::display::format(&Value::Number(now), "h:mm AM/PM", wb).text; (date, time) @@ -1765,6 +1765,14 @@ mod tests { } } + #[test] + fn header_footer_date_follows_the_workbook_date_system() { + let mut wb = Workbook::new(); + let date_1900 = hf_date_time(&wb).0; + wb.date_system = gridcraft_core::DateSystem::D1904; + assert_eq!(hf_date_time(&wb).0, date_1900); + } + #[test] fn header_footer_section_edits_are_undoable_and_views_are_per_sheet() { let mut s = s(); diff --git a/crates/functions/src/date.rs b/crates/functions/src/date.rs index 29aeb47..f68f26d 100644 --- a/crates/functions/src/date.rs +++ b/crates/functions/src/date.rs @@ -1,6 +1,6 @@ //! Date and time functions. -use gridcraft_core::date::{DateTime, datetime_from_serial, days_in_month, days_in_month_in, is_leap, serial_from_ymd}; +use gridcraft_core::date::{DateTime, datetime_from_serial, days_in_month, days_in_month_in, is_leap, serial_from_ymd, serial_in_system}; use gridcraft_core::parse::parse_input; use gridcraft_core::{CellError, DateSystem, Value}; @@ -98,10 +98,10 @@ fn second(a: &[Arg], _c: &mut dyn Ctx) -> R { } fn now(_a: &[Arg], c: &mut dyn Ctx) -> R { - num_val(c.now_serial()) + num_val(serial_in_system(c.date_system(), c.now_serial())) } fn today(_a: &[Arg], c: &mut dyn Ctx) -> R { - num_val(c.now_serial().floor()) + num_val(serial_in_system(c.date_system(), c.now_serial()).floor()) } fn weekday(a: &[Arg], c: &mut dyn Ctx) -> R { @@ -794,6 +794,11 @@ mod tests { close(crate::call(spec, &[n(0.0)], &mut ctx), 6.0); let spec = crate::lookup("YEAR").unwrap(); close(crate::call(spec, &[n(0.0)], &mut ctx), 1904.0); + // The clock is 2026-10-07 12:00; in the 1904 system that is serial 44840.5. + close(crate::call(crate::lookup("NOW").unwrap(), &[], &mut ctx), 44840.5); + let today = crate::call(crate::lookup("TODAY").unwrap(), &[], &mut ctx); + close(today.clone(), 44840.0); + close(crate::call(spec, &[crate::Arg::val(today)], &mut ctx), 2026.0); // No fictitious day here: 1904 is a real leap year and 1900 is before the epoch. let spec = crate::lookup("DATE").unwrap(); close(crate::call(spec, &[n(1904.0), n(2.0), n(29.0)], &mut ctx), 59.0); diff --git a/crates/ui-egui/src/keymap.rs b/crates/ui-egui/src/keymap.rs index 21bf41f..3372e1d 100644 --- a/crates/ui-egui/src/keymap.rs +++ b/crates/ui-egui/src/keymap.rs @@ -179,12 +179,14 @@ pub(crate) fn dispatch(app: &mut SheetApp, ctx: &egui::Context, key: Key, physic } Shortcut::Dialog(name, params) => app.open_dialog(name, params), Shortcut::Date | Shortcut::Time => { - let now = gridcraft_engine::calc::now_serial(); - let (value, format) = if shortcut == Shortcut::Date { (now.floor(), "m/d/yyyy") } else { (now.fract(), "h:mm AM/PM") }; let text = app .session .active() - .map(|d| gridcraft_engine::display::format(&gridcraft_engine::core::Value::Number(value), format, &d.wb).text) + .map(|d| { + let now = gridcraft_engine::core::date::serial_in_system(d.wb.date_system, gridcraft_engine::calc::now_serial()); + let (value, format) = if shortcut == Shortcut::Date { (now.floor(), "m/d/yyyy") } else { (now.fract(), "h:mm AM/PM") }; + gridcraft_engine::display::format(&gridcraft_engine::core::Value::Number(value), format, &d.wb).text + }) .unwrap_or_default(); edit_with(app, text); } diff --git a/crates/ui-egui/src/ribbon.rs b/crates/ui-egui/src/ribbon.rs index e8291ac..e84be82 100644 --- a/crates/ui-egui/src/ribbon.rs +++ b/crates/ui-egui/src/ribbon.rs @@ -2447,11 +2447,13 @@ pub fn shortcut(app: &mut SheetApp, key: Key, m: Modifiers) { } Key::Semicolon => { // Insert today's date. - let today = gridcraft_engine::calc::now_serial().floor(); let text = app .session .active() - .map(|d| gridcraft_engine::display::format(&gridcraft_engine::core::Value::Number(today), "m/d/yyyy", &d.wb).text) + .map(|d| { + let today = gridcraft_engine::core::date::serial_in_system(d.wb.date_system, gridcraft_engine::calc::now_serial()).floor(); + gridcraft_engine::display::format(&gridcraft_engine::core::Value::Number(today), "m/d/yyyy", &d.wb).text + }) .unwrap_or_default(); app.begin_edit(Some(text), false); None