-
Notifications
You must be signed in to change notification settings - Fork 3
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
fix: support non-gregory calendars [DHIS2-17617] #397
Conversation
🚀 Deployed on https://pr-397--dhis2-data-entry.netlify.app |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code LGTM! I love the extensive testing 😍
No change requests, just a couple of comments.
Will test in browser later
Once suggestion I have is to introduce a hook (e.g. useCalendar
) so we don't have to do const { systemInfo = {} } = useConfig(); const { calendar = 'gregory' } = systemInfo
all the time
This is just a thought we could explore in the future: What if we introduced a Zustand store that persists the calendar and timezone during runtime which gets populated before we display the app.
Then we abstract and move all date-related logic into src/shared/date
, let these functions get the calendar value, so the app doesn't have to deal with that anymore.
The last piece would be to have date components that render the date appropriately.
Then we'd have isolated all the date-complexity into the date modules (src/shared/date
& src/components/date/
) and the rest off the application is unaware that different date format exist.
Another thought: Maybe we can move all the (non-period related) date logic into the multi-calendar-dates library as well. Especially if we do what I mentioned above, that code could result in something that could be useful to a lot more apps
// equivalents of 1970, except for Nepali which is 3 years later | ||
// we don't have calendar details for nepali calendar from 1970 and back | ||
|
||
export const startingYears = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Is this an exhaustive list?
- Or does it cover all starting years relevant to dhis2?
- Should this be moved to the multi-calendar-dates library or stay here?
} | ||
|
||
// returns string in either 'YYYY-MM-DD' or 'YYYY-MM-DDTHH:MM.SSS' format (depending on input) | ||
// if non-gregory calendar, returns null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add a Jira ticket for this? Maybe there's one already..
<Tooltip content={lastUpdatedString}> | ||
{/* timeAgo will be null if non-Gregory calendar. TO DO: update */} | ||
{i18n.t( | ||
'Last updated {{- timeAgo}} by {{- name}}', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just out of curiousity, what is the {{- ...}}
syntax? I only know {{...}}
}, [periodType, currentDay, year, dateLimit, locale, openFuturePeriods]) | ||
}, [ | ||
periodType, | ||
currentDayString, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there's an eslint rule we can disable here to prevent the warning
onYearChange, | ||
calendar, | ||
}) { | ||
// console.log('maxYear', maxYear) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// console.log('maxYear', maxYear) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Deleted because unused I suppose?
UPDATE: Since we have period start/end dates in the non-gregorian calendars, we need to, for example, compare dates between calendars (e.g. check that the org unit closing date (ISO) is after the period end date (ethiopian)). This also means that some of the assumptions I had about relative time and displaying date/time stamps were not appropriate. I've gone through and refactored and made use of the conversion functions from the multi-calendar-dates conversion functions, so with the most recent commit, there should no longer be anything that is "to do" for non-gregory calendars. I've also created a component |
src/bottom-bar/form-expiry-info.js
Outdated
calendar: 'gregory', | ||
timezone, | ||
}) | ||
const dateTime = `${lockDate} (${timezone})` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand this code correctly, then there's a good chance that the lockDate will be a server-date, so the dateTime
that's being constructed (and displayed in the tooltip) here will always be a Gregorian date, regardless of the user's calendar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Fixed to use the component and hence convert to system calendar.
const { calendar = 'gregory', dateFormat } = systemInfo | ||
const { fromServerDate } = useTimeZoneConversion() | ||
|
||
// NOTE: the passed date is assumed to be in ISO |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add validation for this and console.error in case it's not?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah. I don't know if there's much we can do if we pass the wrong date because an Ethiopian date like 2016-03-14
is also a valid Gregorian date. But, I've added a step to check that the date is parsable as ISO, so a date like 2016-13-04
will fail and then I've set it to return Invalid date ({{date you passed}})
## [100.8.3](v100.8.2...v100.8.3) (2024-10-16) ### Bug Fixes * support non-gregory calendars [DHIS2-17617] ([#397](#397)) ([7c3e0c8](7c3e0c8))
🎉 This PR is included in version 100.8.3 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Background
This PR adds periods for non-Gregory calendars and updates the date logic throughout the app such that non-Gregorian dates "work" throughout the app to the extent that we can avoid logic problems when working with non-ISO dates.
This addresses the following tickets:
Additionally the following will be fixed by this PR:
pt_BR
where java code is invalid format (due to amendment in multi-calendar-dates)Some common themes
Period generation
Avoiding use of Date()
date manipulation
To-do: https://dhis2.atlassian.net/browse/LIBS-692
Handling time zones
new Date()
) and needed to compare it with a server date. This is now not necessary as we can make use of multi-calendar-datesgetNowInCalendar
and then get a date/time string that reflects the wall clock time for the server. This allows us to refactor to remove a lot of code we had in the app for this.for example:
To-do : https://dhis2.atlassian.net/browse/LIBS-693
relative time
last updated 2016-13-03
instead oflast updated 5 minutes ago
with non ISO calendars).for example:
gregory:
ethiopian:
To-do: https://dhis2.atlassian.net/browse/LIBS-691
Testing
I have primarily tested with automated testing by trying to add/expand coverage for any code that is affected by these changes.
I have done some light manual testing (e.g. checked that the period generation works okay and that data entry seems to work). It's a bit hard to test some of these things manually as the