-
Notifications
You must be signed in to change notification settings - Fork 262
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): format observation datetime to accurate local time to prevent inaccurate timestamps #2208
base: main
Are you sure you want to change the base?
(fix): format observation datetime to accurate local time to prevent inaccurate timestamps #2208
Conversation
test?.obs?.map((entry) => { | ||
const isoFormattedString = entry.obsDatetime.replace(' ', 'T').replace('.0', '.000').concat('Z'); | ||
const date = new Date(isoFormattedString); | ||
return format(date, 'yyyy-MM-dd HH:mm:ss'); |
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.
Why not use the framework formatDatetime
here?
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 did not want to break the existing functionality. In my investigation using formatDatetime
returns dates like Today 06:50 am
which was not my intention. I wanted to return a string like this 2024-09-04 06:23:23.0
so that wherever the value is being used it doesn't break anything. In short I wanted to return the original date but formatted correctly,
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 vote for consistency across the system and I vote for the formatters provided by the framework. Is there a strong reason not to go with the formatted date from the framework's function?
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.
Yes @ojwanganto that date object at that point is not for display but rather to make sure it is in the correct timezone and that approach is what made it possible. using formatDateTime
or any other format function from the framework did not quite fit the use case.
I am open to suggestions though.
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 it's fine to operate on time objects, but please use dayjs()
, which supports everything you're trying to do here in a much cleaner way and is already part of the framework.
const formatObsDatetime = (obsDatetime: string) => { | ||
const isoFormattedString = obsDatetime.replace(' ', 'T').replace('.0', '.000').concat('Z'); | ||
return isoFormattedString; | ||
}; |
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.
const formatObsDatetime = (obsDatetime: string) => { | |
const isoFormattedString = obsDatetime.replace(' ', 'T').replace('.0', '.000').concat('Z'); | |
return isoFormattedString; | |
}; | |
const formatObsDatetime = (obsDatetime: string) => { | |
return dayjs(obsDatetime).toISOString(); | |
}; |
dayjs already provides this conversion to ISO format.
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.
The obsDatetime
parameter is weird. It's an already formatted date string like this: 2025-01-22 05:28:00.0
Following your suggestion rolls back the date by 3 hours (probably because I am on EAT).
obsDatetime - 2025-01-22 05:28:00.0
isoFormattedString - 2025-01-22T05:28:00.000Z
formattedWithDayJS - 2025-01-22T02:28:00.000Z
thanks for highlighting though I have seen a use case for it on the tooltip for accuracy purposes
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.
So, yes, because dayjs
interprets it as a local timestamp (which is what that format claims it is). Instead, you're adding an adjustment so this is treated as if it were in UTC, which is not something we should be deciding here, but on the backend.
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.
Agree with @ibacher ... I'm forgetting, when does the server return something like "2025-01-22 05:28:00.0" (ie without specifying time zone).
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.
@mogoodrich highly likely that it does not. This is a modification that is most certainly done at the front end, somewhere up the "callstack".
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.
We should certainly consider fixing that @amosmachora @denniskigen , where does the obstree resource live?
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'm referring to this guy in the REST-WS module. And this is not in response to Amos' comments from above, but rather about this ticket in general. Per Ian, this specific issue is just another pointer to the known wider issue of how dates and time (specifically timezones) are handled in the backend.
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 @denniskigen !
@ibacher @dkayiwa @mseaton I'm thinking we want to fix this? specifically, when generating the value_datetime and obs_datetime here:
... just format in the standard ISO string format instead?
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.
@mogoodrich Yep. We do need to make allowance for, e.g., implementations that have been storing time in UTC rather than local time. But, yeah, ideally, all conversations through the API are done in ISO timestamps and the ambiguity should mostly go away.
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 @ibacher ... isn't that even more of a reason to include an ISO string here? Stripping off the timezone seems to assume that the server time zone is the facility timezone, and we just want to display that time to the user, regardless of what timezone their client is in. (We've done that in the past with things like this: https://github.com/openmrs/openmrs-module-uicommons/blob/master/omod/src/main/webapp/resources/scripts/filters/serverDate.js but this has become problematic when the server is in UTC or some timezone that don't correspond to the clinic timezone)
test?.obs?.map((entry) => { | ||
const isoFormattedString = entry.obsDatetime.replace(' ', 'T').replace('.0', '.000').concat('Z'); | ||
const date = new Date(isoFormattedString); | ||
return format(date, 'yyyy-MM-dd HH:mm:ss'); |
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 it's fine to operate on time objects, but please use dayjs()
, which supports everything you're trying to do here in a much cleaner way and is already part of the framework.
packages/esm-patient-tests-app/src/test-results/filter/filter-context.tsx
Outdated
Show resolved
Hide resolved
const formatObsDatetime = (obsDatetime: string) => { | ||
const isoFormattedString = obsDatetime.replace(' ', 'T').replace('.0', '.000').concat('Z'); | ||
return isoFormattedString; | ||
}; |
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.
So, yes, because dayjs
interprets it as a local timestamp (which is what that format claims it is). Instead, you're adding an adjustment so this is treated as if it were in UTC, which is not something we should be deciding here, but on the backend.
…-chart into fix/inaccurate-test-timestamp
@amosmachora did you see Ian's latest comments on the ticket? |
Yes I did Dennis, not gonna lie worked out perfectly for me because I had no clue how to rewrite the code with the dayjs implementation that Ian was suggesting : ) |
Requirements
Summary
This PR formats the test timestamp in the results panel using the openmrs framework
formatDatetime
function that accurately handles the users locale. Since the date we had was already formatted to a certain format we first convert it to an ISO string (which was the original format) then format it correctly to the users local time removing the inconsistency.Screenshots
Results
Visits
Related Issue
https://openmrs.atlassian.net/browse/O3-4297
Other