Skip to content

Commit

Permalink
Merge pull request swiftlang#602 from xwu/time-zone
Browse files Browse the repository at this point in the history
Swift 3 API parity and new implementations for NSTimeZone
  • Loading branch information
itaiferber authored Aug 29, 2016
2 parents 6d6057a + 98cf808 commit ab63b51
Show file tree
Hide file tree
Showing 4 changed files with 233 additions and 62 deletions.
2 changes: 1 addition & 1 deletion Foundation/NSDateFormatter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ open class DateFormatter : Formatter {

open var generatesCalendarDates = false { willSet { _reset() } }

/*@NSCopying*/ open var timeZone: TimeZone! = NSTimeZone.systemTimeZone() { willSet { _reset() } }
/*@NSCopying*/ open var timeZone: TimeZone! = NSTimeZone.system { willSet { _reset() } }

/*@NSCopying*/ internal var _calendar: Calendar! { willSet { _reset() } }
open var calendar: Calendar! {
Expand Down
129 changes: 88 additions & 41 deletions Foundation/NSTimeZone.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,27 @@ open class NSTimeZone : NSObject, NSCopying, NSSecureCoding, NSCoding {
_CFDeinit(self)
}

// `init(forSecondsFromGMT:)` is not a failable initializer, so we need a designated initializer that isn't failable.
internal init(_name tzName: String) {
super.init()
_CFTimeZoneInit(_cfObject, tzName._cfObject, nil)
}

// Time zones created with this never have daylight savings and the
// offset is constant no matter the date; the name and abbreviation
// do NOT follow the POSIX convention (of minutes-west).
public convenience init(forSecondsFromGMT seconds: Int) { NSUnimplemented() }
public convenience init(forSecondsFromGMT seconds: Int) {
let sign = seconds < 0 ? "-" : "+"
let absoluteValue = abs(seconds)
var minutes = absoluteValue / 60
if (absoluteValue % 60) >= 30 { minutes += 1 }
var hours = minutes / 60
minutes %= 60
hours = min(hours, 99) // Two digits only; leave CF to enforce actual max offset.
let mm = minutes < 10 ? "0\(minutes)" : "\(minutes)"
let hh = hours < 10 ? "0\(hours)" : "\(hours)"
self.init(_name: "GMT" + sign + hh + mm)
}

public convenience init?(abbreviation: String) {
let abbr = abbreviation._cfObject
Expand All @@ -95,7 +112,7 @@ open class NSTimeZone : NSObject, NSCopying, NSSecureCoding, NSCoding {
open func encode(with aCoder: NSCoder) {
if aCoder.allowsKeyedCoding {
aCoder.encode(self.name._bridgeToObjectiveC(), forKey:"NS.name")
// darwin versions of this method can and will encode mutable data, however it is not required for compatability
// Darwin versions of this method can and will encode mutable data, however it is not required for compatibility
aCoder.encode(self.data._bridgeToObjectiveC(), forKey:"NS.data")
} else {
}
Expand Down Expand Up @@ -165,58 +182,47 @@ open class NSTimeZone : NSObject, NSCopying, NSSecureCoding, NSCoding {

extension NSTimeZone {

open class func systemTimeZone() -> TimeZone {
open class var system: TimeZone {
return CFTimeZoneCopySystem()._swiftObject
}

open class func resetSystemTimeZone() {
CFTimeZoneResetSystem()
}

open class func defaultTimeZone() -> TimeZone {
return CFTimeZoneCopyDefault()._swiftObject
}

open class func setDefaultTimeZone(_ aTimeZone: TimeZone) {
CFTimeZoneSetDefault(aTimeZone._cfObject)
open class var `default`: TimeZone {
get {
return CFTimeZoneCopyDefault()._swiftObject
}
set {
CFTimeZoneSetDefault(newValue._cfObject)
}
}
}

extension NSTimeZone: _SwiftBridgable, _CFBridgable {
typealias SwiftType = TimeZone
var _swiftObject: TimeZone { return TimeZone(reference: self) }
}

extension CFTimeZone : _SwiftBridgable, _NSBridgable {
typealias NSType = NSTimeZone
var _nsObject : NSTimeZone { return unsafeBitCast(self, to: NSTimeZone.self) }
var _swiftObject: TimeZone { return _nsObject._swiftObject }
}
open class var local: TimeZone { NSUnimplemented() }

extension TimeZone : _NSBridgable, _CFBridgable {
typealias NSType = NSTimeZone
typealias CFType = CFTimeZone
var _nsObject : NSTimeZone { return _bridgeToObjectiveC() }
var _cfObject : CFTimeZone { return _nsObject._cfObject }
}
open class var knownTimeZoneNames: [String] {
guard let knownNames = CFTimeZoneCopyKnownNames() else { return [] }
return knownNames._nsObject._bridgeToSwift() as! [String]
}

extension NSTimeZone {
open class func localTimeZone() -> TimeZone { NSUnimplemented() }

open class var knownTimeZoneNames: [String] { NSUnimplemented() }

open class var abbreviationDictionary: [String : String] {
get {
NSUnimplemented()
guard let dictionary = CFTimeZoneCopyAbbreviationDictionary() else { return [:] }
return dictionary._nsObject._bridgeToSwift() as! [String : String]
}
set {
// CFTimeZoneSetAbbreviationDictionary(newValue._cfObject)
NSUnimplemented()
}
}

open class var timeZoneDataVersion: String { NSUnimplemented() }

open var secondsFromGMT: Int { NSUnimplemented() }

open var secondsFromGMT: Int {
let currentDate = Date()
return secondsFromGMT(for: currentDate)
}

/// The abbreviation for the receiver, such as "EDT" (Eastern Daylight Time). (read-only)
///
Expand All @@ -226,15 +232,52 @@ extension NSTimeZone {
return abbreviation(for: currentDate)
}

open var daylightSavingTime: Bool { NSUnimplemented() }
open var daylightSavingTimeOffset: TimeInterval { NSUnimplemented() }
/*@NSCopying*/ open var nextDaylightSavingTimeTransition: Date? { NSUnimplemented() }

open var isDaylightSavingTime: Bool {
let currentDate = Date()
return isDaylightSavingTime(for: currentDate)
}

open var daylightSavingTimeOffset: TimeInterval {
let currentDate = Date()
return daylightSavingTimeOffset(for: currentDate)
}

/*@NSCopying*/ open var nextDaylightSavingTimeTransition: Date? {
let currentDate = Date()
return nextDaylightSavingTimeTransition(after: currentDate)
}

open func isEqual(to aTimeZone: TimeZone) -> Bool {
return CFEqual(self._cfObject, aTimeZone._cfObject)
}

open func localizedName(_ style: NameStyle, locale: Locale?) -> String? { NSUnimplemented() }

open func localizedName(_ style: NameStyle, locale: Locale?) -> String? {
#if os(OSX) || os(iOS)
let cfStyle = CFTimeZoneNameStyle(rawValue: style.rawValue)!
#else
let cfStyle = CFTimeZoneNameStyle(style.rawValue)
#endif
return CFTimeZoneCopyLocalizedName(self._cfObject, cfStyle, locale?._cfObject ?? CFLocaleCopyCurrent())._swiftObject
}

}

extension NSTimeZone: _SwiftBridgable, _CFBridgable {
typealias SwiftType = TimeZone
var _swiftObject: TimeZone { return TimeZone(reference: self) }
}

extension CFTimeZone : _SwiftBridgable, _NSBridgable {
typealias NSType = NSTimeZone
var _nsObject : NSTimeZone { return unsafeBitCast(self, to: NSTimeZone.self) }
var _swiftObject: TimeZone { return _nsObject._swiftObject }
}

extension TimeZone : _NSBridgable, _CFBridgable {
typealias NSType = NSTimeZone
typealias CFType = CFTimeZone
var _nsObject : NSTimeZone { return _bridgeToObjectiveC() }
var _cfObject : CFTimeZone { return _nsObject._cfObject }
}

extension NSTimeZone {
Expand All @@ -249,3 +292,7 @@ extension NSTimeZone {
}

}

extension NSNotification.Name {
public static let NSSystemTimeZoneDidChange = NSNotification.Name(rawValue: "NSSystemTimeZoneDidChangeNotification") // NSUnimplemented
}
65 changes: 48 additions & 17 deletions Foundation/TimeZone.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@
//===----------------------------------------------------------------------===//



internal func __NSTimeZoneIsAutoupdating(_ timezone: NSTimeZone) -> Bool {
return false
}

internal func __NSTimeZoneAutoupdating() -> NSTimeZone {
return NSTimeZone.local._nsObject
}

internal func __NSTimeZoneCurrent() -> NSTimeZone {
fatalError()
return NSTimeZone.system._nsObject
}

/**
Expand All @@ -29,7 +32,7 @@ internal func __NSTimeZoneCurrent() -> NSTimeZone {

Cocoa does not provide any API to change the time zone of the computer, or of other applications.
*/
public struct TimeZone : CustomStringConvertible, CustomDebugStringConvertible, Hashable, Equatable, ReferenceConvertible {
public struct TimeZone : Hashable, Equatable, ReferenceConvertible {
public typealias ReferenceType = NSTimeZone

internal var _wrapped : NSTimeZone
Expand All @@ -39,6 +42,15 @@ public struct TimeZone : CustomStringConvertible, CustomDebugStringConvertible,
public static var current : TimeZone {
return TimeZone(adoptingReference: __NSTimeZoneCurrent(), autoupdating: false)
}

/// The time zone currently used by the system, automatically updating to the user's current preference.
///
/// If this time zone is mutated, then it no longer tracks the application time zone.
///
/// The autoupdating time zone only compares equal to itself.
public static var autoupdatingCurrent : TimeZone {
return TimeZone(adoptingReference: __NSTimeZoneAutoupdating(), autoupdating: true)
}

// MARK: -
//
Expand Down Expand Up @@ -194,28 +206,48 @@ public struct TimeZone : CustomStringConvertible, CustomDebugStringConvertible,

// MARK: -

public var description: String {
return _wrapped.description
}

public var debugDescription : String {
return _wrapped.debugDescription
}

public var hashValue : Int {
if _autoupdating {
return 1
} else {
return _wrapped.hash
}
}

public static func ==(lhs: TimeZone, rhs: TimeZone) -> Bool {
if lhs._autoupdating || rhs._autoupdating {
return lhs._autoupdating == rhs._autoupdating
} else {
return lhs._wrapped.isEqual(rhs._wrapped)
}
}
}

public func ==(_ lhs: TimeZone, _ rhs: TimeZone) -> Bool {
if lhs._autoupdating || rhs._autoupdating {
return lhs._autoupdating == rhs._autoupdating
} else {
return lhs._wrapped.isEqual(rhs._wrapped)
extension TimeZone : CustomStringConvertible, CustomDebugStringConvertible, CustomReflectable {
private var _kindDescription : String {
if (self == TimeZone.current) {
return "current"
} else {
return "fixed"
}
}

public var customMirror : Mirror {
var c: [(label: String?, value: Any)] = []
c.append((label: "identifier", value: identifier))
c.append((label: "kind", value: _kindDescription))
c.append((label: "abbreviation", value: abbreviation()))
c.append((label: "secondsFromGMT", value: secondsFromGMT()))
c.append((label: "isDaylightSavingTime", value: isDaylightSavingTime()))
return Mirror(self, children: c, displayStyle: Mirror.DisplayStyle.struct)
}

public var description: String {
return "\(identifier) (\(_kindDescription))"
}

public var debugDescription : String {
return "\(identifier) (\(_kindDescription))"
}
}

Expand Down Expand Up @@ -247,4 +279,3 @@ extension TimeZone {
return result!
}
}

Loading

0 comments on commit ab63b51

Please sign in to comment.