Merge pull request #742 from marcoarnulfo:fix/edate-eomonth-1900
This commit is contained in:
commit
5144bd5b17
|
|
@ -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, serial_in_system};
|
||||
use gridcraft_core::date::{DateTime, datetime_from_serial, days_in_month, is_leap, serial_from_ymd, serial_in_system};
|
||||
use gridcraft_core::parse::parse_input;
|
||||
use gridcraft_core::{CellError, DateSystem, Value};
|
||||
|
||||
|
|
@ -164,7 +164,9 @@ fn edate(a: &[Arg], c: &mut dyn Ctx) -> R<Value> {
|
|||
if !(1900..=9999).contains(&y) {
|
||||
return Err(CellError::Num);
|
||||
}
|
||||
let dd = (d.day.max(1) as i64).min(days_in_month_in(sys, y as i32, mo as u32) as i64);
|
||||
// Excel keeps serial 0's day 0 and gives February 1900 its real 28 days here, though the
|
||||
// sheet's calendar has a 29 February 1900 (serial 60).
|
||||
let dd = (d.day as i64).min(days_in_month(y as i32, mo as u32) as i64);
|
||||
num_val(ymd_serial(sys, y, mo, dd)? as f64)
|
||||
}
|
||||
|
||||
|
|
@ -177,7 +179,8 @@ fn eomonth(a: &[Arg], c: &mut dyn Ctx) -> R<Value> {
|
|||
if !(1900..=9999).contains(&y) {
|
||||
return Err(CellError::Num);
|
||||
}
|
||||
num_val(ymd_serial(sys, y, mo, days_in_month_in(sys, y as i32, mo as u32) as i64)? as f64)
|
||||
// Like EDATE, February 1900 ends on the 28th (serial 59).
|
||||
num_val(ymd_serial(sys, y, mo, days_in_month(y as i32, mo as u32) as i64)? as f64)
|
||||
}
|
||||
|
||||
fn datedif(a: &[Arg], c: &mut dyn Ctx) -> R<Value> {
|
||||
|
|
@ -680,17 +683,35 @@ mod tests {
|
|||
close(ev("DATEVALUE", vec![t("2/29/1900")]), 60.0);
|
||||
close(ev("DATEVALUE", vec![t("3/1/1900")]), 61.0);
|
||||
is_err(ev("DATEVALUE", vec![t("2/29/1901")]), CellError::Value);
|
||||
// EDATE and EOMONTH land on it as the end of February 1900.
|
||||
close(ev("EOMONTH", vec![n(d(1900.0, 1.0, 15.0)), n(1.0)]), 60.0);
|
||||
close(ev("EOMONTH", vec![n(60.0), n(0.0)]), 60.0);
|
||||
close(ev("EOMONTH", vec![n(d(1900.0, 3.0, 15.0)), n(-1.0)]), 60.0);
|
||||
// EDATE and EOMONTH read it as 29 February, but end February 1900 on the 28th.
|
||||
close(ev("EOMONTH", vec![n(d(1900.0, 1.0, 15.0)), n(1.0)]), 59.0);
|
||||
close(ev("EOMONTH", vec![n(60.0), n(0.0)]), 59.0);
|
||||
close(ev("EOMONTH", vec![n(d(1900.0, 3.0, 15.0)), n(-1.0)]), 59.0);
|
||||
close(ev("EOMONTH", vec![n(60.0), n(12.0)]), d(1901.0, 2.0, 28.0));
|
||||
close(ev("EDATE", vec![n(d(1900.0, 1.0, 31.0)), n(1.0)]), 60.0);
|
||||
close(ev("EDATE", vec![n(d(1900.0, 3.0, 31.0)), n(-1.0)]), 60.0);
|
||||
close(ev("EDATE", vec![n(d(1900.0, 1.0, 31.0)), n(1.0)]), 59.0);
|
||||
close(ev("EDATE", vec![n(d(1900.0, 3.0, 31.0)), n(-1.0)]), 59.0);
|
||||
close(ev("EDATE", vec![n(60.0), n(1.0)]), d(1900.0, 3.0, 29.0));
|
||||
close(ev("EDATE", vec![n(60.0), n(12.0)]), d(1901.0, 2.0, 28.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn edate_eomonth_early_1900() {
|
||||
// Excel 365: serial 0 is 0 January 1900 and February 1900 has 28 days here.
|
||||
close(ev("EDATE", vec![n(0.0), n(0.0)]), 0.0);
|
||||
close(ev("EDATE", vec![n(0.0), n(1.0)]), 31.0);
|
||||
close(ev("EDATE", vec![n(0.0), n(12.0)]), 366.0);
|
||||
close(ev("EOMONTH", vec![n(0.0), n(1.0)]), 59.0);
|
||||
close(ev("EDATE", vec![n(31.0), n(1.0)]), 59.0);
|
||||
close(ev("EOMONTH", vec![n(59.0), n(0.0)]), 59.0);
|
||||
// Unchanged, and the same as Excel.
|
||||
close(ev("EOMONTH", vec![n(0.0), n(0.0)]), 31.0);
|
||||
is_err(ev("EOMONTH", vec![n(0.0), n(-1.0)]), CellError::Num);
|
||||
close(ev("EDATE", vec![n(59.0), n(1.0)]), 88.0);
|
||||
close(ev("EDATE", vec![n(60.0), n(1.0)]), 89.0);
|
||||
close(ev("EDATE", vec![n(61.0), n(-1.0)]), 32.0);
|
||||
close(ev("EOMONTH", vec![n(31.0), n(0.0)]), 31.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn datedif_units() {
|
||||
let s = n(d(2001.0, 6.0, 1.0));
|
||||
|
|
|
|||
Loading…
Reference in New Issue