| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See http://swift.org/LICENSE.txt for license information |
| // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| |
| |
| import CoreFoundation |
| |
| open class NSTimeZone : NSObject, NSCopying, NSSecureCoding, NSCoding { |
| typealias CFType = CFTimeZone |
| private var _base = _CFInfo(typeID: CFTimeZoneGetTypeID()) |
| private var _name: UnsafeMutableRawPointer? = nil |
| private var _data: UnsafeMutableRawPointer? = nil |
| private var _periods: UnsafeMutableRawPointer? = nil |
| private var _periodCnt = Int32(0) |
| |
| internal var _cfObject: CFType { |
| return unsafeBitCast(self, to: CFType.self) |
| } |
| |
| // Primary creation method is +timeZoneWithName:; the |
| // data-taking variants should rarely be used directly |
| public convenience init?(name tzName: String) { |
| self.init(name: tzName, data: nil) |
| } |
| |
| public init?(name tzName: String, data aData: Data?) { |
| super.init() |
| if !_CFTimeZoneInit(_cfObject, tzName._cfObject, aData?._cfObject) { |
| return nil |
| } |
| } |
| |
| public convenience required init?(coder aDecoder: NSCoder) { |
| guard aDecoder.allowsKeyedCoding else { |
| preconditionFailure("Unkeyed coding is unsupported.") |
| } |
| let name = aDecoder.decodeObject(of: NSString.self, forKey: "NS.name") |
| let data = aDecoder.decodeObject(of: NSData.self, forKey: "NS.data") |
| |
| if name == nil { |
| return nil |
| } |
| |
| self.init(name: String._unconditionallyBridgeFromObjectiveC(name), data: data?._swiftObject) |
| } |
| |
| open override var hash: Int { |
| return Int(bitPattern: CFHash(_cfObject)) |
| } |
| |
| open override func isEqual(_ object: Any?) -> Bool { |
| guard let other = object as? NSTimeZone else { return false } |
| return isEqual(to: other._swiftObject) |
| } |
| |
| open override var description: String { |
| return CFCopyDescription(_cfObject)._swiftObject |
| } |
| |
| deinit { |
| _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) { |
| 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 |
| guard let name = unsafeBitCast(CFDictionaryGetValue(CFTimeZoneCopyAbbreviationDictionary(), unsafeBitCast(abbr, to: UnsafeRawPointer.self)), to: NSString!.self) else { |
| return nil |
| } |
| self.init(name: name._swiftObject , data: nil) |
| } |
| |
| open func encode(with aCoder: NSCoder) { |
| guard aCoder.allowsKeyedCoding else { |
| preconditionFailure("Unkeyed coding is unsupported.") |
| } |
| 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 compatibility |
| aCoder.encode(self.data._bridgeToObjectiveC(), forKey:"NS.data") |
| } |
| |
| public static var supportsSecureCoding: Bool { |
| return true |
| } |
| |
| open override func copy() -> Any { |
| return copy(with: nil) |
| } |
| |
| open func copy(with zone: NSZone? = nil) -> Any { |
| return self |
| } |
| |
| open var name: String { |
| guard type(of: self) === NSTimeZone.self else { |
| NSRequiresConcreteImplementation() |
| } |
| return CFTimeZoneGetName(_cfObject)._swiftObject |
| } |
| |
| open var data: Data { |
| guard type(of: self) === NSTimeZone.self else { |
| NSRequiresConcreteImplementation() |
| } |
| return CFTimeZoneGetData(_cfObject)._swiftObject |
| } |
| |
| open func secondsFromGMT(for aDate: Date) -> Int { |
| guard type(of: self) === NSTimeZone.self else { |
| NSRequiresConcreteImplementation() |
| } |
| return Int(CFTimeZoneGetSecondsFromGMT(_cfObject, aDate.timeIntervalSinceReferenceDate)) |
| } |
| |
| open func abbreviation(for aDate: Date) -> String? { |
| guard type(of: self) === NSTimeZone.self else { |
| NSRequiresConcreteImplementation() |
| } |
| return CFTimeZoneCopyAbbreviation(_cfObject, aDate.timeIntervalSinceReferenceDate)._swiftObject |
| } |
| |
| open func isDaylightSavingTime(for aDate: Date) -> Bool { |
| guard type(of: self) === NSTimeZone.self else { |
| NSRequiresConcreteImplementation() |
| } |
| return CFTimeZoneIsDaylightSavingTime(_cfObject, aDate.timeIntervalSinceReferenceDate) |
| } |
| |
| open func daylightSavingTimeOffset(for aDate: Date) -> TimeInterval { |
| guard type(of: self) === NSTimeZone.self else { |
| NSRequiresConcreteImplementation() |
| } |
| return CFTimeZoneGetDaylightSavingTimeOffset(_cfObject, aDate.timeIntervalSinceReferenceDate) |
| } |
| |
| open func nextDaylightSavingTimeTransition(after aDate: Date) -> Date? { |
| guard type(of: self) === NSTimeZone.self else { |
| NSRequiresConcreteImplementation() |
| } |
| return Date(timeIntervalSinceReferenceDate: CFTimeZoneGetNextDaylightSavingTimeTransition(_cfObject, aDate.timeIntervalSinceReferenceDate)) |
| } |
| } |
| |
| extension NSTimeZone { |
| |
| open class var system: TimeZone { |
| return CFTimeZoneCopySystem()._swiftObject |
| } |
| |
| open class func resetSystemTimeZone() { |
| CFTimeZoneResetSystem() |
| } |
| |
| open class var `default`: TimeZone { |
| get { |
| return CFTimeZoneCopyDefault()._swiftObject |
| } |
| set { |
| CFTimeZoneSetDefault(newValue._cfObject) |
| } |
| } |
| |
| open class var local: TimeZone { NSUnimplemented() } |
| |
| open class var knownTimeZoneNames: [String] { |
| guard let knownNames = CFTimeZoneCopyKnownNames() else { return [] } |
| return knownNames._nsObject._bridgeToSwift() as! [String] |
| } |
| |
| open class var abbreviationDictionary: [String : String] { |
| get { |
| 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 { |
| let currentDate = Date() |
| return secondsFromGMT(for: currentDate) |
| } |
| |
| /// The abbreviation for the receiver, such as "EDT" (Eastern Daylight Time). (read-only) |
| /// |
| /// This invokes `abbreviationForDate:` with the current date as the argument. |
| open var abbreviation: String? { |
| let currentDate = Date() |
| return abbreviation(for: currentDate) |
| } |
| |
| 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? { |
| #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: _SwiftBridgeable, _CFBridgeable { |
| typealias SwiftType = TimeZone |
| var _swiftObject: TimeZone { return TimeZone(reference: self) } |
| } |
| |
| extension CFTimeZone : _SwiftBridgeable, _NSBridgeable { |
| typealias NSType = NSTimeZone |
| var _nsObject : NSTimeZone { return unsafeBitCast(self, to: NSTimeZone.self) } |
| var _swiftObject: TimeZone { return _nsObject._swiftObject } |
| } |
| |
| extension TimeZone : _NSBridgeable, _CFBridgeable { |
| typealias NSType = NSTimeZone |
| typealias CFType = CFTimeZone |
| var _nsObject : NSTimeZone { return _bridgeToObjectiveC() } |
| var _cfObject : CFTimeZone { return _nsObject._cfObject } |
| } |
| |
| extension NSTimeZone { |
| |
| public enum NameStyle : Int { |
| case standard // Central Standard Time |
| case shortStandard // CST |
| case daylightSaving // Central Daylight Time |
| case shortDaylightSaving // CDT |
| case generic // Central Time |
| case shortGeneric // CT |
| } |
| |
| } |
| |
| extension NSNotification.Name { |
| public static let NSSystemTimeZoneDidChange = NSNotification.Name(rawValue: kCFTimeZoneSystemTimeZoneDidChangeNotification._swiftObject) |
| } |