From c9fa6a76278c78ea2dc6dd7711528881d6bcd580 Mon Sep 17 00:00:00 2001 From: Eric Kaden <608341+EricKaden@users.noreply.github.com> Date: Thu, 22 Oct 2026 09:01:48 -0400 Subject: [PATCH] M12: a date pattern whose date the first can't keep gives way to a later one --- crates/xfa/src/fixtures.rs | 4 +++- crates/xfa/src/picture.rs | 13 ++++++++----- crates/xfa/src/tests.rs | 7 +++++-- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/crates/xfa/src/fixtures.rs b/crates/xfa/src/fixtures.rs index 9b4988aef3..cf9bf7ff56 100644 --- a/crates/xfa/src/fixtures.rs +++ b/crates/xfa/src/fixtures.rs @@ -507,7 +507,8 @@ pub fn fields_template(data: &str) -> String { /// Date fields whose edit pictures list alternatives, as forms let a date be typed several ways /// (`date{YYYYMMDD}|date{YYMMDD}|…`); one with a single pattern; a text field; `code`, whose -/// only alternative is a text clause; and `short`, whose first pattern has a two-digit year. +/// only alternative is a text clause; `short`, whose first pattern has a two-digit year; and +/// `pick`, where two later patterns read some dates and only one gives a year the first keeps. pub fn date_alternatives_template() -> String { r##" @@ -519,6 +520,7 @@ pub fn date_alternatives_template() -> String { date{YYYYMMDD}|text{YYMMDD} date{YYMMDD}|date{YYYYMMDD} + date{YYMMDD}|date{DDMMYYYY}|date{YYYYMMDD} diff --git a/crates/xfa/src/picture.rs b/crates/xfa/src/picture.rs index 2da57a2b0d..3ddb392114 100644 --- a/crates/xfa/src/picture.rs +++ b/crates/xfa/src/picture.rs @@ -43,11 +43,14 @@ pub fn typed_date(tpl: &Template, som: &str, text: &str) -> Option { if reads(&first).is_some() { return None; } - let iso = alternatives(picture).into_iter().skip(1).filter(|a| is_date_clause(a)).filter_map(date_letters).find_map(|p| reads(&p))?; - // Written in the first pattern only when it reads back as the same date: a year a two-digit - // year can't hold would otherwise become another century's. - let shown = iso_to_pattern(&iso, &first); - (pattern_to_iso(&shown, &first).as_deref() == Some(iso.as_str())).then_some(shown) + // The first later date pattern that reads the text and gives a date the first pattern keeps: + // written in the first, it must read back as the same date (a two-digit year can't hold 1901 + // or 1203), else the next pattern is tried. + alternatives(picture).into_iter().skip(1).filter(|a| is_date_clause(a)).filter_map(date_letters).find_map(|p| { + let iso = reads(&p)?; + let shown = iso_to_pattern(&iso, &first); + (pattern_to_iso(&shown, &first).as_deref() == Some(iso.as_str())).then_some(shown) + }) } /// Whether picture clause `clause` is a date pattern: a `date{…}` clause (with or without a diff --git a/crates/xfa/src/tests.rs b/crates/xfa/src/tests.rs index da9c8832ec..24872b35d9 100644 --- a/crates/xfa/src/tests.rs +++ b/crates/xfa/src/tests.rs @@ -2677,8 +2677,9 @@ fn a_date_typed_by_another_of_its_edit_pictures_patterns_is_written_in_the_first } /// Only date clauses are other ways to type a date, and a date is rewritten only when the first -/// pattern keeps it: a later `text{…}` clause is no date pattern, and a year a two-digit first -/// pattern can't hold leaves the text as typed instead of becoming another date. +/// pattern keeps it: a later `text{…}` clause is no date pattern, a year a two-digit first +/// pattern can't hold leaves the text as typed instead of becoming another date, and a pattern +/// whose date the first can't keep gives way to a later one whose date it can. #[test] fn a_typed_date_is_rewritten_only_by_date_clauses_into_a_first_pattern_that_keeps_it() { let (tpl, _) = crate::parse(&crate::fixtures::date_alternatives_template()).unwrap(); @@ -2687,4 +2688,6 @@ fn a_typed_date_is_rewritten_only_by_date_clauses_into_a_first_pattern_that_keep let short = "form[0].short[0]"; assert_eq!(typed(short, "20261018").as_deref(), Some("261018"), "a year the first pattern keeps"); assert_eq!(typed(short, "19011018"), None, "1901 as 01 would read back as 2001"); + // DDMMYYYY reads 20011203 as 1203-01-20, which YYMMDD can't keep; YYYYMMDD reads 2001-12-03. + assert_eq!(typed("form[0].pick[0]", "20011203").as_deref(), Some("011203"), "the next pattern that the first keeps"); }