In order to track removals as well as changes, we need to store the underlying file instance itself, not just a list of additions. As a bonus, the file is now read once in the initializer instead of every time a property is queried.
The date property is now optional. There is no date that can serve as a meaningful implicit default.
year() has been removed as a separate property (along with all its tests). It was redundant.
Dates can be read from both modern and deprecated formats. Writing always uses the modern format. Files are automatically updated upon loading (in the initializer) to match the version that might eventually be written.
We don’t actually need a date formatter in the library itself, since neither underlying library represents dates as strings. We do need to convert back and forth to components. Those use Calendar and also need a fixed time zone. They are in the extension to Date.
For ease of testing, I did put a formatter to use in the Date extension, which allows you to write Date(us: "01/02/0003") as much as you want in tests and be devoid time zone offsets.
I removed all the calendar component tests. The were redundant, following verification of the millisecond‐precise dates they were derived from. Meaningless though they were, I would have just left them had the calendars they were using not been applying user time zones. It was simply easier to remove them than to fix them.
Hopefully this won't create any conflicts with anything you've changed.
...okay, apparently a lot.
year()
has been removed as a separate property (along with all its tests). It was redundant.Calendar
and also need a fixed time zone. They are in the extension toDate
.Date
extension, which allows you to writeDate(us: "01/02/0003")
as much as you want in tests and be devoid time zone offsets.It did. You can sort that out.