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");
}