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

Migrate to datefns #5065

Merged
merged 16 commits into from Jul 27, 2022
Merged

Conversation

TheTrio
Copy link
Contributor

@TheTrio TheTrio commented Jul 23, 2022

This removes moment-js as a dependency.

With this, vendors.js goes from 1.42MB to 1.37MB

To make the tests pass, I've made it so that the toDate function emulates some of momentjs' questionable choices
like using undefined and null to indicate current time. MomentJS also converted undefined and null to 0
in the add and subtract functions. date-fns returns an invalid date in such cases, which caused another
test to fail. This is a workaround for that.
I didn't read the comment above and accidentally removed the timezone information.
Earlier, the timeline length was being calculated by moment(end - start).weeks()
This would give incorrect results because end - start returns an integer - the number of
milliseconds between the two dates(which can then be converted to weeks).
Calling moment on it converts it to a date instead of a duration.
While doing some more reading about dates in Javascript, I found that the Date constructor always returns dates in
the local timezone. So having a date object in a different timezone is not really possible. Since moment-js had its
own wrapper Date object, it didn't have this problem. date-fns operates on the native Date object, so it limited in that
regard.

So while we can't get a Date object with UTC timezone, getting a string with UTC timezone is possible. This is what toISOString()
does
Most of these methods didn't need to be in UTC since they were only comparing dates. So I've used local time for these. The only place where we display the time in UTC was in the StatisticsUpdateModal. I've kept it this way.
@ragesoss
Copy link
Member

Are there any UX changes you know of from this? If so, can you provide before/after screenshots?

@TheTrio
Copy link
Contributor Author

TheTrio commented Jul 25, 2022

Well, the only thing I can think of is in app/assets/javascripts/components/uploads/upload.jsx where there were several conflicting formats for AM and PM(and the same for / vs -).

Before

image

image

Now, its all consistent.

image

Other than that, there shouldn't be any major differences if I've done everything right

@@ -8,5 +8,48 @@ export const toDate = (date) => {
if (date instanceof Date) {
return date;
}
return parseISO(date);
// should not really happen in production, but it's here for making the tests pass
Copy link
Member

Choose a reason for hiding this comment

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

How hard would it be to fix the tests so that this isn't necessary? If it shouldn't happen in production, hopefully it doesn't... but it this would probably prevent us from discovering it if it was happening in production.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm, I think this affects one or two React tests so shouldn't be too difficult to fix. Should I just raise an Error if this ever happens? That would fail the CI so if it is happening right now we would have an idea where and how.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, I think raising a console error (and then returning the new Date, so that it would still work the same way as with moment.js) would be a good way to flush out any places where this happens in production.

return parsedDate;
};

export const formatWithTime = (date) => {
Copy link
Member

Choose a reason for hiding this comment

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

I think formatWithTime and formatWithoutTime might have room for improvement in the names. Format what? A Date? A DateTime? I think this works for a Date or a DateTime, right?

Maybe formatDateAndTime and formatDate (or formatDateWithoutTime)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It works for any valid ISO 8601 string or a Date object. I'll improve the function names to reflect that.

return parsedDate;
};

export const formatWithTime = (date) => {
Copy link
Member

Choose a reason for hiding this comment

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

Comments documenting the expected constraints on the date input (strings? Date objects?) would be helpful for all these functions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

All the functions here should work for valid ISO 8601 strings or Date objects. I'll add a comment for that.

this should tell us if this happens in production
A couple of tests were failing because we were accessing the incorrect attribute, while in another one we weren't setting the date.
There's still a JS error for the user profile page but that will require a bit more work and refactoring to solve satisfactorily.
For now, this suppresses that error.
I've also changed the output format for datetime strings. Now, everything is 0 padded. This just makes it
easier to test
Moment did this by default but date-fns requires you to pass an option.
@ragesoss ragesoss merged commit e90d12f into WikiEducationFoundation:master Jul 27, 2022
@TheTrio TheTrio deleted the migrateToDatefns branch July 31, 2022 19:57
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