Skip to content

Fix DateFormatter TimeZone Setter #1704

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

Merged
merged 4 commits into from
Oct 11, 2018
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CoreFoundation/NumberDate.subproj/CFTimeZone.c
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,7 @@ static CFTimeZoneRef __CFTimeZoneCreateSystem(void) {
size_t zoneInfoDirLen = CFStringGetLength(__tzZoneInfo);
if (strncmp(linkbuf, tzZoneInfo, zoneInfoDirLen) == 0) {
name = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (uint8_t *)linkbuf + zoneInfoDirLen,
strlen(linkbuf) - zoneInfoDirLen + 1, kCFStringEncodingUTF8, false);
strlen(linkbuf) - zoneInfoDirLen, kCFStringEncodingUTF8, false);
} else {
name = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (uint8_t *)linkbuf, strlen(linkbuf), kCFStringEncodingUTF8, false);
}
Expand Down
6 changes: 3 additions & 3 deletions Foundation/DateFormatter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -176,13 +176,13 @@ open class DateFormatter : Formatter {
/*@NSCopying*/ internal var _timeZone: TimeZone? { willSet { _reset() } }
open var timeZone: TimeZone! {
get {
guard let timeZone = _timeZone else {
guard let tz = _timeZone else {
return (CFDateFormatterCopyProperty(_cfObject, kCFDateFormatterTimeZone) as! NSTimeZone)._swiftObject
}
return timeZone
return tz
}
set {
_timeZone = timeZone
_timeZone = newValue
}
}

Expand Down
52 changes: 52 additions & 0 deletions TestFoundation/TestDateFormatter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class TestDateFormatter: XCTestCase {
("test_dateFormatString", test_dateFormatString),
("test_setLocaleToNil", test_setLocaleToNil),
("test_setTimeZoneToNil", test_setTimeZoneToNil),
("test_setTimeZone", test_setTimeZone),
("test_ExpectedTimeZone", test_ExpectedTimeZone),
]
}

Expand Down Expand Up @@ -356,4 +358,54 @@ class TestDateFormatter: XCTestCase {
// Time zone should go back to the system one.
XCTAssertEqual(f.timeZone, NSTimeZone.system)
}

func test_setTimeZone() {
// Test two different time zones. Should ensure that if one
// happens to be TimeZone.current, we still get a valid test.
let newYork = TimeZone(identifier: "America/New_York")!
let losAngeles = TimeZone(identifier: "America/Los_Angeles")!

XCTAssertNotEqual(newYork, losAngeles)

// Case 1: New York
let f = DateFormatter()
f.timeZone = newYork
XCTAssertEqual(f.timeZone, newYork)

// Case 2: Los Angeles
f.timeZone = losAngeles
XCTAssertEqual(f.timeZone, losAngeles)
}

func test_ExpectedTimeZone() {
let gmt = TimeZone(abbreviation: DEFAULT_TIMEZONE)
let newYork = TimeZone(identifier: "America/New_York")!
let losAngeles = TimeZone(identifier: "America/Los_Angeles")!

XCTAssertNotEqual(newYork, losAngeles)

let now = Date()

let f = DateFormatter()
f.dateFormat = "z"

// Case 1: TimeZone.current
f.timeZone = TimeZone.current
XCTAssertEqual(f.string(from: now), f.timeZone.abbreviation())

// Case 2: New York
f.timeZone = newYork
XCTAssertEqual(f.string(from: now), f.timeZone.abbreviation())

// Case 3: Los Angeles
f.timeZone = losAngeles
XCTAssertEqual(f.string(from: now), f.timeZone.abbreviation())

guard gmt != TimeZone.current else {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not 100% happy with the way this test works, which pretty much is trying to make sure that we can use "TimeZone.current" for zones other than GMT and get what we expect when we then run it through DateFormatter.

If this is too much, I can try to write a more targeted test, although I'm not entirely sure that would be any less fragile.

print("Inconclusive: This test checks to see if the formatter produces the same TZ as TimeZone.current")
print("When it fails, TimeZone.current formats as GMT instead of normal.")
print("Unfortunately, we can't use GMT as TimeZone.current for this test to be conclusive.")
return
}
}
}