Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Overhaul Dates #74

Merged
merged 1 commit into from
Jun 13, 2021
Merged

Overhaul Dates #74

merged 1 commit into from
Jun 13, 2021

Conversation

nickbabcock
Copy link
Contributor

This PR sees the introduction of 3 new public date types for a total of
4 date types. In parentheses is the game that a particular date can
handle.

  • RawDate (any)
  • Date (EU4, CK3, Imperator)
  • DateHour (HOI4)
  • UniformDate (Stellaris)

Previously Date was only implemented which required copy+pasted with
slight tweaks for the HOI4 module
.
The same would have been needed for Stellaris. Maintaining separate date
implementations would require any bugs or improvements to be copied
around which I would be susceptible to forgetting.

This PR creates the RawDate which the 3 other date types are based
around. A RawDate is space optimized so that even dates with hours
(eg: HOI4) still consume 32 bits. And while a RawDate can handle any
date format it has the least validation and won't check if the number of
days in a given month makes sense. That is why it is recommended to use
the date type of the data you are parsing. The RawDate is still
publicly exposed for the times when parsing dates with unknown origins.

And instead of exposing that all dates are based around the raw date, a
PdsDate trait was introduced that allows one to query a dates year,
month, and day just in case the internals need to be switched out again.

There is a breaking change in the API introduced with this PR. The new
API should feel more like chrono. The thought was that it is better to
conform to existing rust date APIs instead of reinventing:

  • Date::new replaced with Date::from_ymd_opt which emulates
    chrono's: NaiveDate::from_ymd_opt
  • Add Date::from_ymd which is a panicing version of from_ymd_opt
    which should allow better creation ergonomics for constant dates and
    emulates chrono's: NaiveDate::from_ymd
  • Date::parse_from_str replaced with Date::parse which takes a byte
    slice instead and returns a result.
  • Dates implement FromStr so one can do "1444.11.11".parse::<Date>().
    Chrono dates also implement FromStr
  • Dates implement Hash much like chrono dates.
  • Date::from_binary keeps the same return API to match chrono's
    NaiveDateTime::from_timestamp_opt
  • Date::game_fmt and Date::iso_8601 now return an intermediate
    object instead of an allocated string, much like chrono's NaiveDateTime::format

Additional changes:

  • Happy path parsing throughput increased 10%
  • Date::to_binary now returns what the date would look like when
    encoded in the binary format.
  • Improved heuristics for detecting binary dates as now the hour
    component is used and only dates with zero hours will be detected as
    dates.

This PR sees the introduction of 3 new public date types for a total of
4 date types. In parentheses is the game that a particular date can
handle.

- RawDate (any)
- Date (EU4, CK3, Imperator)
- DateHour (HOI4)
- UniformDate (Stellaris)

Previously `Date` was only implemented which required [copy+pasted with
slight tweaks for the HOI4 module](https://github.com/rakaly/hoi4save/blob/e97ea29ee4f655d812a3eca3770a3115810c893f/src/date.rs).
The same would have been needed for Stellaris. Maintaining separate date
implementations would require any bugs or improvements to be copied
around which I would be susceptible to forgetting.

This PR creates the `RawDate` which the 3 other date types are based
around. A `RawDate` is space optimized so that even dates with hours
(eg: HOI4) still consume 32 bits. And while a `RawDate` can handle any
date format it has the least validation and won't check if the number of
days in a given month makes sense. That is why it is recommended to use
the date type of the data you are parsing. The `RawDate` is still
publicly exposed for the times when parsing dates with unknown origins.

And instead of exposing that all dates are based around the raw date, a
`PdsDate` trait was introduced that allows one to query a dates year,
month, and day just in case the internals need to be switched out again.

There is a breaking change in the API introduced with this PR. The new
API should feel more like chrono. The thought was that it is better to
conform to existing rust date APIs instead of reinventing:

- `Date::new` replaced with `Date::from_ymd_opt` which emulates
chrono's: [`NaiveDate::from_ymd_opt`](https://docs.rs/chrono/0.4.19/chrono/naive/struct.NaiveDate.html#method.from_ymd_opt)
- Add `Date::from_ymd` which is a panicing version of `from_ymd_opt`
which should allow better creation ergonomics for constant dates and
emulates chrono's: [`NaiveDate::from_ymd`](https://docs.rs/chrono/0.4.19/chrono/naive/struct.NaiveDate.html#method.from_ymd)
- `Date::parse_from_str` replaced with `Date::parse` which takes a byte
slice instead and returns a result.
- Dates implement `FromStr` so one can do `1444.11.11`.parse::<Date>()`.
Chrono dates also implement `FromStr`
- Dates implement `Hash` much like chrono dates.
- `Date::from_binary` keeps the same return API to match chrono's
`NaiveDateTime::from_timestamp_opt`
- `Date::game_fmt` and `Date::iso_8601` now return an intermediate
object instead of an allocated string, much like chrono's [`NaiveDateTime::format`](https://docs.rs/chrono/0.4.19/chrono/naive/struct.NaiveDateTime.html#method.format)

Additional changes:

- Happy path parsing throughput increased 10%
- `Date::to_binary` now returns what the date would look like when
encoded in the binary format.
- Improved heuristics for detecting binary dates as now the hour
component is used and only dates with zero hours will be detected as
dates.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant