-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Do not use local-timezone dates for doing date to string conversions to specific timezones. #1155
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
Conversation
…to specific timezones. This is certainly not valid because, if your local timezone includes daylight saving time, there is no possible Javascript date value which could return the string, for instance, "2015-03-08 02:30". Instead, use the getUTC methods of the Date object after simply adjusting the timestamp by the desired timezone offset. I had difficultly understanding what in the world the test_timezone.js test was doing, so I wrote a new one. The new test is specifically: No matter what date is used, no matter what system timezone, no matter what node-mysql timezone, no matter what server-side timezone, if you insert a Javascript Date object, you should get the same Date object back (this was previously failing if that date object happened to be near daylight saving time boundaries in the local system timezone). Additionally, the string representation of the date in MySQL should be in the timezone specified by the node-mysql timezone. As far as I know the server-side MySQL timezone variable doesn't affect DATETIME objects (however it does affect TIMESTAMP objects, which will currently fail a bunch of these tests, but that's probably a more significant change for another PR another day...). After doing all of this, I went back to read through the old test_timezone, and saw it was suffering from the same general issues as SqlString.js - it was using the local timezone string representation of a date to store arbitrary dates (that typeCast function would just generate an invalid date object if run during one of the selected timezone offsets from 2:30am on the day daylight saving time kicks in, among other problems). Rule of thumb with Javascript dates: if you're calling .getTimezoneOffset() on a date object, you're probably doing it wrong.
Thank you so much! Sorry it took me a while to get back to you. So oddly the test you add does not fail with the current code (see Travis CI build https://travis-ci.org/felixge/node-mysql/builds/74812812). Would it be possible to include a test that fails without your changes and passes with them? |
So, my test fails on the current code depending on what timezone the system you're running the tests on (the previous tests would fail, I think, based on a combination of both system timezone and actual time of running the test). I'll look into if there's a way to tell node/V8 (or some kind of mock) to use a specific timezone, so that the test would reproduce on any system. If you know of a good way of doing that, please let me know =). |
Ah, gotcha. I think the changes are definitely good :) My worry here is that if they are not at least failing on Travis CI without the change, we could very well break timezone handling again with the 3.0 refactor and not know since the tests won't fail. I see you have |
Yeah, I completely agree, I do not want some other change to break this again =). I was hoping that, since the tests previously failed, that maybe Travis CI's local timezone was one with daylight saving time, but perhaps only some hosts that run tests are (or if it's not in one of the US timezones, the particular date values to try inserting that would fail might not be in my dates I put in my test). So, first, the SET TIME_ZONE commands change the timezone on the communications channel with MySQL, that was not the source of the bug (but I still think it's good to test that regardless of that setting that dates work). The particular thing that was broken previously was based on the local system timezone (the timezone of V8 Date objects), not this. Second, there's no MySQL command to set the communications time zone to Pacific without first inserting a whole bunch of stuff into the mysql.timezone tables. There are shell scripts to populate those tables, but on my local vanilla installation of MySQL they tables were empty (or just had the handful or UTC timezones). |
…h daylight saving time. Also fix bug where test was inserting multiple rows with effectively the same keys and reading back the wrong row.
This reverts commit c14a26a.
This reverts commit f22f432. Doing this, and pushing it so, we can see in the log that it fails on TravisCI
This reverts commit c14a26a.
So, apparently, as far as I could tell, none of the date mocking libraries in Node handle mocking dates in a timezone with daylight saving time, so I had to write one. Can see in the commit log of this branch that the the new tests failed on TravisCI on the old code (date_fix~1). I think this PR is now ready to go. |
Thank you so much! |
This change is now published to npm as 2.9.0 |
Great, looks good! |
This should not change any general behavior, but fixes issues when you try to insert dates which are within your timezone offset of a daylight saving time switchover time.
Using the locale-specific Date accessor functions is certainly not valid because, if your local timezone includes daylight saving time, there is no possible Javascript date value which could return the string, for instance, "2015-03-08 02:30".
Instead, use the getUTC methods of the Date object after simply adjusting the timestamp by the desired timezone offset.
I had difficultly understanding what in the world the test_timezone.js test was doing, so I wrote a new one. The new test is specifically:
No matter what date is used, no matter what system timezone, no matter what node-mysql timezone, no matter what server-side timezone, if you insert a Javascript Date object, you should get the same Date object back (this was previously failing if that date object happened to be near daylight saving time boundaries in the local system timezone).
Additionally, the string representation of the date in MySQL should be in the timezone specified by the node-mysql timezone (I believe that is what the old test was trying to check). As far as I know the server-side MySQL TIME_ZONE variable doesn't affect DATETIME objects (however it does affect TIMESTAMP objects, which would currently fail these same tests, but that's probably a more significant change for another PR another day...).
After doing all of this, I went back to read through the old test_timezone, and saw it was suffering from the same general issues as SqlString.js - it was using the local timezone string representation of a date to store arbitrary dates (that typeCast function would just generate an invalid date object if run during one of the selected timezone offsets from 2:30am on the day daylight saving time kicks in, among other problems).
Rule of thumb with Javascript dates: if someone is calling .getTimezoneOffset() on a date object, they're probably doing it wrong.
This should fix #1045