Skip to content

xlsx: don't let x15:workbookPr reset the date1904 flag - #708

Merged
jmcnamara merged 1 commit into
tafia:masterfrom
youdie006:fix/date1904-extlst-reset
Aug 26, 2026
Merged

xlsx: don't let x15:workbookPr reset the date1904 flag#708
jmcnamara merged 1 commit into
tafia:masterfrom
youdie006:fix/date1904-extlst-reset

Conversation

@youdie006

Copy link
Copy Markdown
Contributor

Summary

Fixes #706. A genuine 1904-system xlsx workbook is read on the 1900 epoch when its <extLst> contains an <x15:workbookPr> element (which modern Excel writes), shifting every date 1462 days (4 years + 1 day) earlier.

Root cause

read_workbook matches the workbookPr local name:

Ok(Event::Start(e)) if e.local_name().as_ref() == b"workbookPr" => {
    self.is_1904 = match e.raw_attr(b"date1904")? {
        Some(v) => v == b"1" || v == b"true",
        None => false,
    };
}

local_name() strips the namespace prefix, so the extension element <x15:workbookPr> (inside <extLst>) also matches. It never carries date1904 and appears after the real <workbookPr date1904="1"/>, so the None => false arm resets is_1904 back to false. has_1904_epoch() then returns false and the +1462-day offset is dropped.

Fix

Only assign is_1904 when the date1904 attribute is actually present; the field already defaults to false, so a bare <workbookPr/> still means 1900-system.

Test

Added date_xlsx_1904_extlst with a fixture (tests/date_1904_extlst.xlsx) = a 1904 workbook whose extLst also contains <x15:workbookPr>. Before the fix has_1904_epoch() is false (test fails); after, it is true, and the existing date tests still pass.


Disclosure: prepared with AI assistance (Claude); I reviewed it and verified the red-green test and the date test suite.

Comment thread src/xlsx/mod.rs Outdated
Some(v) => v == b"1" || v == b"true",
None => false,
};
// Only update the flag when the attribute is present. The

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is referring to the what the patch is fixing and not to what the code is doing. Change it to something like

// Set the 1904 date flag, if present.

Comment thread tests/test.rs Outdated
// A 1904-system workbook whose extLst also contains an <x15:workbookPr>
// extension element (which shares the "workbookPr" local name but carries
// no date1904 attribute) must still be read on the 1904 epoch. See #706.
let mut xls: Xlsx<_> = wb("date_1904_extlst.xlsx");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't need to be mut. Also the variable should be called xlsx and not xls.

@jmcnamara

jmcnamara commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the fix.

I have made some comments inline. Please address them and rebase and force push the changes to your branch. Then mark the comments as "resolved".

Also, reduce the commit message down to 1-2 lines max.

@jmcnamara jmcnamara self-assigned this Aug 14, 2026
@jmcnamara jmcnamara added next_release needs work for merge The PR needs some rework or clarification. No suitable for merge, yet. labels Aug 14, 2026
@youdie006
youdie006 force-pushed the fix/date1904-extlst-reset branch from b807e50 to 12654b3 Compare August 25, 2026 11:14
@youdie006

Copy link
Copy Markdown
Contributor Author

Pushed a fix for the red CI. The failure was mine: the test I added had a let mut xls that does not need mut (has_1904_epoch() takes &self), which cargo clippy --all-targets --all-features -- -Dwarnings rejects. I had copied the shape from the neighbouring date_xlsx_1904 test, which does need mut because it calls worksheet_range_at.

One-character change, no behaviour difference. Verified locally with the same commands CI runs: cargo clippy --all-targets --all-features -- -Dwarnings clean, cargo test --all-features all green (44 + 162 + 67 passed, 0 failed).

Disclosure: I use AI assistance in my work, and I review and verify everything before it goes out.

read_workbook matched the "workbookPr" local name, but that also matches the
namespaced extension element <x15:workbookPr> that modern Excel writes inside
<extLst>. That element never carries a date1904 attribute, and it appears
after the real <workbookPr> in the stream, so it reset is_1904 back to false.
A genuine 1904-system workbook was then read on the 1900 epoch, shifting every
date 1462 days (4 years and a day) earlier.

Only assign is_1904 when the date1904 attribute is actually present; the field
already defaults to false, so a bare <workbookPr/> still means 1900-system.

Fixes tafia#706
@youdie006
youdie006 force-pushed the fix/date1904-extlst-reset branch from 12654b3 to c605e7b Compare August 25, 2026 17:27
@youdie006

Copy link
Copy Markdown
Contributor Author

Both review comments addressed — apologies, I acted on the CI failure yesterday and only picked up the mut half of your second note.

src/xlsx/mod.rs: the comment now describes what the code does rather than what the patch fixed:

// Set the 1904 date flag, if present. The attribute is
// optional here because `<x15:workbookPr>` inside `<extLst>`
// shares this local name and never carries `date1904`.

I kept one clause on why the attribute is optional, since without it the if let looks like it could just be an unconditional assignment. Happy to trim it to the single line you suggested if you would rather.

tests/test.rs: renamed xls to xlsx, and the mut is gone.

Verified with the same commands CI runs: cargo clippy --all-targets --all-features -- -Dwarnings clean, cargo test --all-features green (44 + 162 + 67 passed, 0 failed).

Disclosure: I use AI assistance in my work, and I review and verify everything before it goes out.

@jmcnamara
jmcnamara merged commit 71af96a into tafia:master Aug 26, 2026
5 of 6 checks passed
@jmcnamara

Copy link
Copy Markdown
Collaborator

Merged. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs work for merge The PR needs some rework or clarification. No suitable for merge, yet. next_release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

xlsx: x15:workbookPr inside extLst resets the date1904 flag (1904-system workbooks read on the 1900 epoch)

2 participants