Open swift-ci opened 5 years ago
I cant replicate this any of Ubuntu 14.04, 16.04 or 18.04 using 4.2.1. All three versions return Feb 28
Comment by Steven Van Impe (JIRA)
That code example was based on my project's code, but I can't reproduce the issue with that either. I want as far as copy-pasting all my code into a new project, with only minimal adjustments and still couldn't reproduce the issue. I then copy pasted my full files into a new project, and finally, I can reproduce the issue. See the attached project, and run `swift test` to reproduce it.
This also pinpointed the cause of the issue: the only difference between this project and the previous ones I made in an attempt to reproduce the issue, is that in this project, the source and test files both declare `let calendar = Calendar(identifier: .gregorian)`. If I share the same calendar object between source and test, the issue goes away.
Is this an error on my part? Should I use a single Calendar object for my entire application? Or is there an issue with Calendar on Linux?
I think this might be a timezone issue. On both macOS and Linux if I run:
TZ=CET swift test
I get all tests passed, but with
TZ=UTC swift test
I get the same 2 test failures.
Are your macOS and Linux Docker images set to different timezones?
Comment by Steven Van Impe (JIRA)
I think you're right. My Mac is set to CET. Docker seems to use UTC.
Since this is a server-side Swift app, I explicitly set the time zone for all dates to CET, as all my users are in that timezone. I had hoped that would get rid of time zone issues.
What seems to happen here is that, with a system time zone set to CET, a test with Jan. 31 00:00 CET returns Feb 28. 00:00 CET (the expected result). However, with a system time zone of UTC, the calculation first subtracts one hour to get Jan. 30 23:00 UTC. Then, it adds one month and gets Feb. 28 23:00 UTC. Finally, it adds one hour again, which results in Mar. 1.
Is this the normal behavior? If so, how do you recommend I solve this issue, so my code is independent of where it is deployed?
@millenomi, who's the calendar expert for corelibs Foundation?
My bad, I misread. Disregard the deleted comment.
Did you try this with master lately? We have overhauled Calendar and fixed ICU to a single release so that you should get consistent behavior now.
Comment by Steven Van Impe (JIRA)
@millenomi As per your deleted comment, explicitly setting the time zone of the `calendar` object resolves the issue as well. So I now have three possible solutions:
Share a single, global calendar object across both the app and the tests. For some reason (I don't understand), this fixes the issue for me, even if I don't set a time zone on it.
Set the TZ environment variable. This feels like a clean solution to me, but adds an additional configuration step that is easy to forget.
Always set the time zone property on calendars. If this does what I assume it does (set the time zone to use when performing calculations), this also feels like a clean solution, and doesn't require additional configuration steps.
Should I go with option #3?
I think it's a solid workaround. You can get the timezone via TimeZone.current if needed.
Have you checked with master? I'm curious to see if this is an issue that goes away with the rework I landed.
Comment by Steven Van Impe (JIRA)
Unfortunately, no. I only have the version(s) installed I run in production.
I just checked against swift-DEVELOPMENT-SNAPSHOT-2019-01-15-a-ubuntu18.04
and it has the same behaviour as 4.2.1 on Linux and macOS. I take it this is as intended. So I don't think this bug is valid since Linux and macOS both work the same way.
Comment by Steven Van Impe (JIRA)
@spevans Can you explain why option #1 works as well? As far as I can tell, this has nothing to do with time zones, and yet, it also resolves the issue.
Attachment: Download
Environment
Swift 4.2.1Additional Detail from JIRA
| | | |------------------|-----------------| |Votes | 0 | |Component/s | Foundation | |Labels | Bug | |Assignee | None | |Priority | Medium | md5: b5cd101c9fb210b5c8555f3e1539b89bIssue Description:
My unit tests unfortunately detected a difference in behavior on Mac vs Linux:
On Mac, adding one month to Jan. 31 returns Feb. 28 (which is what I hoped it would do). On Linux however, this returns March 1.