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

WIP: Cookbook example showing how to do Hijri days adjustments (without custom calendar) #2912

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

khawarizmus
Copy link
Contributor

@khawarizmus khawarizmus commented Jul 6, 2024

This PR implements the AdjustableHijriTemporal class for customizing Hijri date display.

This class allows for adjustment of Hijri dates by shifting days forward or backward. It's designed to:

  • Help users synchronize displayed Hijri dates with their local Hijri calendar.
  • Facilitate the use of alternative Hijri calendar epochs.

Key points:

  • It adjusts the display of Hijri dates without modifying the underlying calendar system.
  • The adjustment is a simple day shift and does not alter month lengths or other calendar rules.
  • This approach is useful for visual alignment but does not implement comprehensive calendar customization or detailed Hijri calendar variants.

Notes to maintainers: The implementation uses composition instead of inheritance and I have made it so that one class can accommodate for PlainDate, PlainDateTime and ZonedDateTime as such the class doesn't implement the following functions:

  • with the exception of toPlainYearMonth and toPlainMonthDay that exist in all the Temporal objects aforementioned. the rest of toX functions are not implemented here and would like to hear your thoughts on how the implementation would look like. for example how would toZonedDateTime behave on a ZonedDateTime underlying object.
  • from and fromX where not implemented because of the same complexity mentioned above. but if there is an agreement on how they should behave I can proceed with the implementation.

Copy link
Collaborator

@ptomato ptomato left a comment

Choose a reason for hiding this comment

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

Thanks for the example!

You had some questions, I'll try to answer them here:

with the exception of toPlainYearMonth and toPlainMonthDay that exist in all the Temporal objects aforementioned. the rest of toX functions are not implemented here and would like to hear your thoughts on how the implementation would look like. for example how would toZonedDateTime behave on a ZonedDateTime underlying object.

If you don't need them directly, I'd consider leaving them out. If you do need them, then I'd suggest to decide first whether e.g. toZonedDateTime should return Temporal.ZonedDateTime or AdjustableHijriTemporal with underlying ZonedDateTime. I could imagine good reasons for either one.

The question of how would toZonedDateTime behave on a ZonedDateTime underlying object, I'd say it depends on your use case. It could return the same object or it could throw.

from and fromX where not implemented because of the same complexity mentioned above. but if there is an agreement on how they should behave I can proceed with the implementation.

Same, if you don't need them directly, I'd consider leaving them out. I'd say this example is meant as a starting point for readers to customize for their own use cases, not as an API specification that they must implement. The AdjustableHijriTemporal constructor seems pretty comprehensive to me; if you want to construct an AdjustableHijriTemporal object from a string or property bag, there's always the option of new AdjustableHijriTemporal(Temporal.PlainDate.from(...), ...).

If readers need a from() method that behaves differently, they can write it according to their use cases, or simplify the problem by splitting AdjustableHijriTemporal into separate PlainDate/PlainDateTime/ZonedDateTime classes, or whatever.

Comment on lines 83 to 97
add(durationLike, options) {
return this.#getAdjustedDate().add(durationLike, options);
}

subtract(durationLike, options) {
return this.#getAdjustedDate().subtract(durationLike, options);
}

until(other, options) {
return this.#getAdjustedDate().until(other, options);
}

since(other, options) {
return this.#getAdjustedDate().since(other, options);
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Depending on how your use case is intended to work, I might suggest deleting these arithmetic methods and saving them for the advanced use case where the user can edit month lengths.

The reason is because if you adjust +1 day for display, that doesn't give the information about when the local Hijri calendar diverged from the underlying CLDR one. You just know that now the shift is +1 day, and some time in the past the calendars were equal. So if you call .subtract({ days: 7 }) you might get a date that wasn't the date 7 days ago.

But this is my uninformed guess about how it is supposed to work; you are the expert here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am not sure if I totally understand your concern here. but the adjustment for display shifts the whole calendar forward or backward with X number of days. so the arithmetics would stay consistent in this case. However, I do agree that for the advanced use case (where month lengths are adjusted independent of each other and of the underlying CLDR data) that would make the arithmetic part more complicated.

Does this sound right to you @ptomato ?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes of course, like I said my question is uninformed, you are the one who knows how this is supposed to work 😄

docs/cookbook/hijriDaysAdjustments.mjs Outdated Show resolved Hide resolved
docs/cookbook/hijriDaysAdjustments.mjs Outdated Show resolved Hide resolved
docs/cookbook/hijriDaysAdjustments.mjs Outdated Show resolved Hide resolved
Comment on lines 75 to 81
toPlainYearMonth() {
return this.#getAdjustedDate().toPlainYearMonth();
}

toPlainMonthDay() {
return this.#getAdjustedDate().toPlainMonthDay();
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

For a PlainDateTime or ZonedDateTime this.#temporal, these will require an extra step, because as part of shrinking the API we removed the direct conversions toPlainYearMonth and toPlainMonthDay from PlainDateTime and ZonedDateTime. There now has to be 2 steps, going through PlainDate.

Here's one way to do it:

let base = this.#getAdjustedDate();
return base.toPlainYearMonth?.() ?? base.toPlainDate().toPlainYearMonth();

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was thinking to remove the toX functions and leave it to the user to decided how best to implement them. What do you think about that?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think that sounds good.

@khawarizmus khawarizmus marked this pull request as ready for review July 29, 2024 19:19
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

2 participants