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

[SR-9668] Adding one month returns a different date on Linux vs Mac. #3558

Open
swift-ci opened this issue Jan 15, 2019 · 11 comments
Open

[SR-9668] Adding one month returns a different date on Linux vs Mac. #3558

swift-ci opened this issue Jan 15, 2019 · 11 comments

Comments

@swift-ci
Copy link
Contributor

Previous ID SR-9668
Radar None
Original Reporter svanimpe (JIRA User)
Type Bug

Attachment: Download

Environment

Swift 4.2.1

Additional Detail from JIRA
Votes 0
Component/s Foundation
Labels Bug
Assignee None
Priority Medium

md5: b5cd101c9fb210b5c8555f3e1539b89b

Issue Description:

My unit tests unfortunately detected a difference in behavior on Mac vs Linux:

let calendar = Calendar(identifier: .gregorian)
var dateComponents = DateComponents()
dateComponents.calendar = calendar
dateComponents.day = 31
dateComponents.month = 1
dateComponents.year = 2019
let start = calendar.date(from: dateComponents)!
let end = calendar.date(byAdding: .month, value: 1, to: start)!

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.

@spevans
Copy link
Collaborator

spevans commented Jan 15, 2019

I cant replicate this any of Ubuntu 14.04, 16.04 or 18.04 using 4.2.1. All three versions return Feb 28

@swift-ci
Copy link
Contributor Author

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?

@spevans
Copy link
Collaborator

spevans commented Jan 16, 2019

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?

@swift-ci
Copy link
Contributor Author

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?

@belkadan
Copy link

@millenomi, who's the calendar expert for corelibs Foundation?

@millenomi
Copy link
Contributor

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.

@swift-ci
Copy link
Contributor Author

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?

@millenomi
Copy link
Contributor

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.

@swift-ci
Copy link
Contributor Author

Comment by Steven Van Impe (JIRA)

Unfortunately, no. I only have the version(s) installed I run in production.

@spevans
Copy link
Collaborator

spevans commented Jan 16, 2019

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.

@swift-ci
Copy link
Contributor Author

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.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@shahmishal shahmishal transferred this issue from apple/swift May 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants