diff --git a/crates/js/src/formcalc.rs b/crates/js/src/formcalc.rs index 78314637e..21a41f52e 100644 --- a/crates/js/src/formcalc.rs +++ b/crates/js/src/formcalc.rs @@ -2305,8 +2305,11 @@ impl Interp<'_> { } let num = self.to_num(&v); let decimals = pic.split_once('.').map_or(0, |(_, f)| f.chars().filter(|c| matches!(c, '9' | 'z' | 'Z')).count()).min(20); + // `9` in the integer part forces a digit; `z` does not. + let min_int = pic.split('.').next().map_or(0, |i| i.chars().filter(|c| *c == '9').count()).min(20); + let width = min_int + if decimals > 0 { decimals + 1 } else { 0 }; let grouped = pic.contains(','); - let mut text = fixed(num.abs(), decimals); + let mut text = format!("{:0>width$}", fixed(num.abs(), decimals)); if grouped { let (int, frac) = text.split_once('.').map_or((text.as_str(), ""), |(a, b)| (a, b)); let mut g = String::new(); diff --git a/crates/js/src/tests.rs b/crates/js/src/tests.rs index 8fd7bf13b..804341b16 100644 --- a/crates/js/src/tests.rs +++ b/crates/js/src/tests.rs @@ -734,6 +734,15 @@ mod formcalc { assert!(go("Nope(1)", "form1[0].page1[0].total[0]", "calculate").error.unwrap().contains("unknown function")); } + #[test] + fn format_nine_pads_the_integer_part() { + assert_eq!(calc(r#"Format("99999", 42)"#), "00042"); + assert_eq!(calc(r#"Format("9999", 5)"#), "0005"); + assert_eq!(calc(r#"Format("999.99", 4.5)"#), "004.50"); + assert_eq!(calc(r#"Format("zzz9", 42)"#), "42"); + assert_eq!(calc(r#"Format("99", 12345)"#), "12345"); + } + #[test] fn date2num_rejects_days_past_the_end_of_the_month() { assert_eq!(calc(r#"Date2Num("2023-02-30")"#), "0");