Skip to content

Commit 44de731

Browse files
authored
Merge pull request #2080 from millenomi/timezone-local
Parity: TimeZone.local, TimeZone.timeZoneDataVersion
2 parents 6f73f0e + 2ccf9d1 commit 44de731

File tree

5 files changed

+130
-38
lines changed

5 files changed

+130
-38
lines changed

CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ CF_EXPORT _Nullable CFErrorRef CFWriteStreamCopyError(CFWriteStreamRef _Null_uns
393393

394394
CF_CROSS_PLATFORM_EXPORT CFStringRef _Nullable _CFBundleCopyExecutablePath(CFBundleRef bundle);
395395
CF_CROSS_PLATFORM_EXPORT Boolean _CFBundleSupportsFHSBundles(void);
396+
CF_CROSS_PLATFORM_EXPORT CFStringRef __CFTimeZoneCopyDataVersionString(void);
396397

397398
// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
398399
// Version 0.8

CoreFoundation/NumberDate.subproj/CFTimeZone.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1537,4 +1537,8 @@ static CFDictionaryRef __CFTimeZoneCopyCompatibilityDictionary(void) {
15371537
return dict;
15381538
}
15391539

1540-
1540+
CF_CROSS_PLATFORM_EXPORT CFStringRef __CFTimeZoneCopyDataVersionString(void) {
1541+
UErrorCode err = U_ZERO_ERROR;
1542+
const char *cstr = ucal_getTZDataVersion(&err);
1543+
return (U_SUCCESS(err)) ? CFStringCreateWithCString(kCFAllocatorSystemDefault, cstr, kCFStringEncodingUTF8) : CFRetain(CFSTR(""));
1544+
}

Foundation/NSTimeZone.swift

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,6 @@ open class NSTimeZone : NSObject, NSCopying, NSSecureCoding, NSCoding {
178178
}
179179
return Date(timeIntervalSinceReferenceDate: CFTimeZoneGetNextDaylightSavingTimeTransition(_cfObject, aDate.timeIntervalSinceReferenceDate))
180180
}
181-
}
182-
183-
extension NSTimeZone {
184181

185182
open class var system: TimeZone {
186183
return CFTimeZoneCopySystem()._swiftObject
@@ -199,7 +196,9 @@ extension NSTimeZone {
199196
}
200197
}
201198

202-
open class var local: TimeZone { NSUnimplemented() }
199+
open class var local: TimeZone {
200+
return TimeZone(adoptingReference: __NSLocalTimeZone.shared, autoupdating: true)
201+
}
203202

204203
open class var knownTimeZoneNames: [String] {
205204
guard let knownNames = CFTimeZoneCopyKnownNames() else { return [] }
@@ -212,12 +211,13 @@ extension NSTimeZone {
212211
return dictionary._nsObject._bridgeToSwift() as! [String : String]
213212
}
214213
set {
215-
// CFTimeZoneSetAbbreviationDictionary(newValue._cfObject)
216-
NSUnimplemented()
214+
CFTimeZoneSetAbbreviationDictionary(newValue._cfObject)
217215
}
218216
}
219217

220-
open class var timeZoneDataVersion: String { NSUnimplemented() }
218+
open class var timeZoneDataVersion: String {
219+
return __CFTimeZoneCopyDataVersionString()._swiftObject
220+
}
221221

222222
open var secondsFromGMT: Int {
223223
let currentDate = Date()
@@ -296,3 +296,53 @@ extension NSTimeZone {
296296
extension NSNotification.Name {
297297
public static let NSSystemTimeZoneDidChange = NSNotification.Name(rawValue: kCFTimeZoneSystemTimeZoneDidChangeNotification._swiftObject)
298298
}
299+
300+
internal class __NSLocalTimeZone: NSTimeZone {
301+
static var shared = __NSLocalTimeZone()
302+
303+
private init() {
304+
super.init(_name: "GMT+0000")
305+
}
306+
307+
public convenience required init?(coder aDecoder: NSCoder) {
308+
// We do not encode details of the local time zone, merely the placeholder object.
309+
self.init()
310+
}
311+
312+
override func encode(with aCoder: NSCoder) {
313+
// We do not encode details of the local time zone, merely the placeholder object.
314+
}
315+
316+
private var system: NSTimeZone {
317+
return NSTimeZone.system._nsObject
318+
}
319+
320+
override var name: String { return system.name }
321+
override var data: Data { return system.data }
322+
override func secondsFromGMT(for aDate: Date) -> Int {
323+
return system.secondsFromGMT(for: aDate)
324+
}
325+
override func abbreviation(for aDate: Date) -> String? {
326+
return system.abbreviation(for: aDate)
327+
}
328+
override func isDaylightSavingTime(for aDate: Date) -> Bool {
329+
return system.isDaylightSavingTime(for: aDate)
330+
}
331+
override func daylightSavingTimeOffset(for aDate: Date) -> TimeInterval {
332+
return system.daylightSavingTimeOffset(for: aDate)
333+
334+
}
335+
override func nextDaylightSavingTimeTransition(after aDate: Date) -> Date? {
336+
return system.nextDaylightSavingTimeTransition(after: aDate)
337+
}
338+
override func localizedName(_ style: NSTimeZone.NameStyle, locale: Locale?) -> String? {
339+
return system.localizedName(style, locale: locale)
340+
}
341+
override var description: String {
342+
return "Local Time Zone (\(system.description))"
343+
}
344+
345+
override func copy(with zone: NSZone? = nil) -> Any {
346+
return self
347+
}
348+
}

Foundation/TimeZone.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,7 @@ public struct TimeZone : Hashable, Equatable, ReferenceConvertible {
4949
///
5050
/// The autoupdating time zone only compares equal to itself.
5151
public static var autoupdatingCurrent : TimeZone {
52-
// swift-corelibs-foundation does not yet support autoupdating, but we can return the current time zone (which will not change).
53-
return TimeZone(adoptingReference: __NSTimeZoneAutoupdating(), autoupdating: true)
52+
return NSTimeZone.local
5453
}
5554

5655
// MARK: -
@@ -118,7 +117,7 @@ public struct TimeZone : Hashable, Equatable, ReferenceConvertible {
118117
}
119118
}
120119

121-
private init(adoptingReference reference: NSTimeZone, autoupdating: Bool) {
120+
internal init(adoptingReference reference: NSTimeZone, autoupdating: Bool) {
122121
// this path is only used for types we do not need to copy (we are adopting the ref)
123122
_wrapped = reference
124123
_autoupdating = autoupdating

TestFoundation/TestTimeZone.swift

Lines changed: 65 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,33 +10,19 @@
1010
import CoreFoundation
1111

1212
class TestTimeZone: XCTestCase {
13-
14-
static var allTests: [(String, (TestTimeZone) -> () throws -> Void)] {
15-
var tests: [(String, (TestTimeZone) -> () throws -> Void)] = [
16-
("test_abbreviation", test_abbreviation),
17-
18-
// Disabled because `CFTimeZoneSetAbbreviationDictionary()` attempts
19-
// to release non-CF objects while removing values from
20-
// `__CFTimeZoneCache`
21-
// ("test_abbreviationDictionary", test_abbreviationDictionary),
22-
23-
("test_changingDefaultTimeZone", test_changingDefaultTimeZone),
24-
("test_computedPropertiesMatchMethodReturnValues", test_computedPropertiesMatchMethodReturnValues),
25-
("test_initializingTimeZoneWithOffset", test_initializingTimeZoneWithOffset),
26-
("test_initializingTimeZoneWithAbbreviation", test_initializingTimeZoneWithAbbreviation),
27-
("test_localizedName", test_localizedName),
28-
("test_customMirror", test_tz_customMirror),
29-
("test_knownTimeZones", test_knownTimeZones),
30-
("test_systemTimeZoneName", test_systemTimeZoneName),
31-
]
32-
33-
#if !os(Windows)
34-
tests.append(contentsOf: [
35-
("test_systemTimeZoneUsesSystemTime", test_systemTimeZoneUsesSystemTime),
36-
])
37-
#endif
38-
39-
return tests
13+
14+
var initialDefaultTimeZone: TimeZone?
15+
16+
override func setUp() {
17+
initialDefaultTimeZone = NSTimeZone.default
18+
super.setUp()
19+
}
20+
21+
override func tearDown() {
22+
super.tearDown()
23+
if let tz = initialDefaultTimeZone {
24+
NSTimeZone.default = tz
25+
}
4026
}
4127

4228
func test_abbreviation() {
@@ -220,4 +206,56 @@ class TestTimeZone: XCTestCase {
220206
XCTAssertEqual(CFStringGetLength(timeZoneName), TimeZone.current.identifier.count)
221207
XCTAssertEqual(CFStringGetLength(timeZoneName), createdTimeZone.identifier.count)
222208
}
209+
210+
func test_autoupdatingTimeZone() {
211+
let system = NSTimeZone.system
212+
let date = Date()
213+
214+
for zone in [NSTimeZone.local, TimeZone.autoupdatingCurrent] {
215+
XCTAssertEqual(zone.identifier, system.identifier)
216+
XCTAssertEqual(zone.secondsFromGMT(for: date), system.secondsFromGMT(for: date))
217+
XCTAssertEqual(zone.abbreviation(for: date), system.abbreviation(for: date))
218+
XCTAssertEqual(zone.isDaylightSavingTime(for: date), system.isDaylightSavingTime(for: date))
219+
XCTAssertEqual(zone.daylightSavingTimeOffset(for: date), system.daylightSavingTimeOffset(for: date))
220+
XCTAssertEqual(zone.nextDaylightSavingTimeTransition(after: date), system.nextDaylightSavingTimeTransition(after: date))
221+
222+
for style in [NSTimeZone.NameStyle.standard,
223+
NSTimeZone.NameStyle.shortStandard,
224+
NSTimeZone.NameStyle.daylightSaving,
225+
NSTimeZone.NameStyle.shortDaylightSaving,
226+
NSTimeZone.NameStyle.generic,
227+
NSTimeZone.NameStyle.shortGeneric,] {
228+
XCTAssertEqual(zone.localizedName(for: style, locale: NSLocale.system), system.localizedName(for: style, locale: NSLocale.system), "For style: \(style)")
229+
}
230+
}
231+
}
232+
233+
static var allTests: [(String, (TestTimeZone) -> () throws -> Void)] {
234+
var tests: [(String, (TestTimeZone) -> () throws -> Void)] = [
235+
("test_abbreviation", test_abbreviation),
236+
237+
// Disabled because `CFTimeZoneSetAbbreviationDictionary()` attempts
238+
// to release non-CF objects while removing values from
239+
// `__CFTimeZoneCache`
240+
// ("test_abbreviationDictionary", test_abbreviationDictionary),
241+
242+
("test_changingDefaultTimeZone", test_changingDefaultTimeZone),
243+
("test_computedPropertiesMatchMethodReturnValues", test_computedPropertiesMatchMethodReturnValues),
244+
("test_initializingTimeZoneWithOffset", test_initializingTimeZoneWithOffset),
245+
("test_initializingTimeZoneWithAbbreviation", test_initializingTimeZoneWithAbbreviation),
246+
("test_localizedName", test_localizedName),
247+
("test_customMirror", test_tz_customMirror),
248+
("test_knownTimeZones", test_knownTimeZones),
249+
("test_systemTimeZoneName", test_systemTimeZoneName),
250+
("test_autoupdatingTimeZone", test_autoupdatingTimeZone),
251+
]
252+
253+
#if !os(Windows)
254+
tests.append(contentsOf: [
255+
("test_systemTimeZoneUsesSystemTime", test_systemTimeZoneUsesSystemTime),
256+
])
257+
#endif
258+
259+
return tests
260+
}
223261
}

0 commit comments

Comments
 (0)