blob: fe8d6da43044811a66c156831ba08fa179f37b45 [file] [log] [blame]
// 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 DateFormatter : Formatter {
typealias CFType = CFDateFormatter
private var __cfObject: CFType?
private var _cfObject: CFType {
guard let obj = __cfObject else {
#if os(macOS) || os(iOS)
let dateStyle = CFDateFormatterStyle(rawValue: CFIndex(self.dateStyle.rawValue))!
let timeStyle = CFDateFormatterStyle(rawValue: CFIndex(self.timeStyle.rawValue))!
#else
let dateStyle = CFDateFormatterStyle(self.dateStyle.rawValue)
let timeStyle = CFDateFormatterStyle(self.timeStyle.rawValue)
#endif
let obj = CFDateFormatterCreate(kCFAllocatorSystemDefault, locale._cfObject, dateStyle, timeStyle)!
_setFormatterAttributes(obj)
if let dateFormat = _dateFormat {
CFDateFormatterSetFormat(obj, dateFormat._cfObject)
}
__cfObject = obj
return obj
}
return obj
}
public override init() {
super.init()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
}
open var formattingContext: Context = .unknown // default is NSFormattingContextUnknown
@available(*, unavailable, renamed: "date(from:)")
func getObjectValue(_ obj: UnsafeMutablePointer<AnyObject?>?,
for string: String,
range rangep: UnsafeMutablePointer<NSRange>?) throws {
NSUnsupported()
}
open override func string(for obj: Any) -> String? {
guard let date = obj as? Date else { return nil }
return string(from: date)
}
open func string(from date: Date) -> String {
return CFDateFormatterCreateStringWithDate(kCFAllocatorSystemDefault, _cfObject, date._cfObject)._swiftObject
}
open func date(from string: String) -> Date? {
var range = CFRange(location: 0, length: string.length)
let date = withUnsafeMutablePointer(to: &range) { (rangep: UnsafeMutablePointer<CFRange>) -> Date? in
guard let res = CFDateFormatterCreateDateFromString(kCFAllocatorSystemDefault, _cfObject, string._cfObject, rangep) else {
return nil
}
return res._swiftObject
}
// range.length is updated with the last position of the input string that was parsed
guard range.length == string.length else {
// The whole string was not parsed
return nil
}
return date
}
open class func localizedString(from date: Date, dateStyle dstyle: Style, timeStyle tstyle: Style) -> String {
let df = DateFormatter()
df.dateStyle = dstyle
df.timeStyle = tstyle
return df.string(for: date._nsObject)!
}
open class func dateFormat(fromTemplate tmplate: String, options opts: Int, locale: Locale?) -> String? {
guard let res = CFDateFormatterCreateDateFormatFromTemplate(kCFAllocatorSystemDefault, tmplate._cfObject, CFOptionFlags(opts), locale?._cfObject) else {
return nil
}
return res._swiftObject
}
open func setLocalizedDateFormatFromTemplate(_ dateFormatTemplate: String) {
if let format = DateFormatter.dateFormat(fromTemplate: dateFormatTemplate, options: 0, locale: locale) {
dateFormat = format
}
}
private func _reset() {
__cfObject = nil
}
internal func _setFormatterAttributes(_ formatter: CFDateFormatter) {
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterIsLenient, value: isLenient._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterTimeZone, value: _timeZone?._cfObject)
if let ident = _calendar?.identifier {
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterCalendarName, value: Calendar._toNSCalendarIdentifier(ident).rawValue._cfObject)
} else {
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterCalendarName, value: nil)
}
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterTwoDigitStartDate, value: _twoDigitStartDate?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterDefaultDate, value: defaultDate?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterCalendar, value: _calendar?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterEraSymbols, value: _eraSymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterMonthSymbols, value: _monthSymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterShortMonthSymbols, value: _shortMonthSymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterWeekdaySymbols, value: _weekdaySymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterShortWeekdaySymbols, value: _shortWeekdaySymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterAMSymbol, value: _amSymbol?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterPMSymbol, value: _pmSymbol?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterLongEraSymbols, value: _longEraSymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterVeryShortMonthSymbols, value: _veryShortMonthSymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterStandaloneMonthSymbols, value: _standaloneMonthSymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterShortStandaloneMonthSymbols, value: _shortStandaloneMonthSymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterVeryShortStandaloneMonthSymbols, value: _veryShortStandaloneMonthSymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterVeryShortWeekdaySymbols, value: _veryShortWeekdaySymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterStandaloneWeekdaySymbols, value: _standaloneWeekdaySymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterShortStandaloneWeekdaySymbols, value: _shortStandaloneWeekdaySymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterVeryShortStandaloneWeekdaySymbols, value: _veryShortStandaloneWeekdaySymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterQuarterSymbols, value: _quarterSymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterShortQuarterSymbols, value: _shortQuarterSymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterStandaloneQuarterSymbols, value: _standaloneQuarterSymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterShortStandaloneQuarterSymbols, value: _shortStandaloneQuarterSymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterGregorianStartDate, value: _gregorianStartDate?._cfObject)
}
internal func _setFormatterAttribute(_ formatter: CFDateFormatter, attributeName: CFString, value: AnyObject?) {
if let value = value {
CFDateFormatterSetProperty(formatter, attributeName, value)
}
}
private var _dateFormat: String? { willSet { _reset() } }
open var dateFormat: String! {
get {
guard let format = _dateFormat else {
return CFDateFormatterGetFormat(_cfObject)._swiftObject
}
return format
}
set {
_dateFormat = newValue
}
}
open var dateStyle: Style = .none {
willSet {
_dateFormat = nil
}
}
open var timeStyle: Style = .none {
willSet {
_dateFormat = nil
}
}
/*@NSCopying*/ internal var _locale: Locale? { willSet { _reset() } }
open var locale: Locale! {
get {
guard let locale = _locale else { return .current }
return locale
}
set {
_locale = newValue
}
}
open var generatesCalendarDates = false { willSet { _reset() } }
/*@NSCopying*/ internal var _timeZone: TimeZone? { willSet { _reset() } }
open var timeZone: TimeZone! {
get {
guard let tz = _timeZone else {
return (CFDateFormatterCopyProperty(_cfObject, kCFDateFormatterTimeZone) as! NSTimeZone)._swiftObject
}
return tz
}
set {
_timeZone = newValue
}
}
/*@NSCopying*/ internal var _calendar: Calendar! { willSet { _reset() } }
open var calendar: Calendar! {
get {
guard let calendar = _calendar else {
return (CFDateFormatterCopyProperty(_cfObject, kCFDateFormatterCalendar) as! NSCalendar)._swiftObject
}
return calendar
}
set {
_calendar = newValue
}
}
open var isLenient = false { willSet { _reset() } }
/*@NSCopying*/ internal var _twoDigitStartDate: Date? { willSet { _reset() } }
open var twoDigitStartDate: Date? {
get {
guard let startDate = _twoDigitStartDate else {
return (CFDateFormatterCopyProperty(_cfObject, kCFDateFormatterTwoDigitStartDate) as? NSDate)?._swiftObject
}
return startDate
}
set {
_twoDigitStartDate = newValue
}
}
/*@NSCopying*/ open var defaultDate: Date? { willSet { _reset() } }
internal var _eraSymbols: [String]? { willSet { _reset() } }
open var eraSymbols: [String] {
get {
guard let symbols = _eraSymbols else {
let cfSymbols = CFDateFormatterCopyProperty(_cfObject, kCFDateFormatterEraSymbols) as! NSArray
return cfSymbols.allObjects as! [String]
}
return symbols
}
set {
_eraSymbols = newValue
}
}
internal var _monthSymbols: [String]? { willSet { _reset() } }
open var monthSymbols: [String] {
get {
guard let symbols = _monthSymbols else {
let cfSymbols = CFDateFormatterCopyProperty(_cfObject, kCFDateFormatterMonthSymbols) as! NSArray
return cfSymbols.allObjects as! [String]
}
return symbols
}
set {
_monthSymbols = newValue
}
}
internal var _shortMonthSymbols: [String]? { willSet { _reset() } }
open var shortMonthSymbols: [String] {
get {
guard let symbols = _shortMonthSymbols else {
let cfSymbols = CFDateFormatterCopyProperty(_cfObject, kCFDateFormatterShortMonthSymbols) as! NSArray
return cfSymbols.allObjects as! [String]
}
return symbols
}
set {
_shortMonthSymbols = newValue
}
}
internal var _weekdaySymbols: [String]? { willSet { _reset() } }
open var weekdaySymbols: [String] {
get {
guard let symbols = _weekdaySymbols else {
let cfSymbols = CFDateFormatterCopyProperty(_cfObject, kCFDateFormatterWeekdaySymbols) as! NSArray
return cfSymbols.allObjects as! [String]
}
return symbols
}
set {
_weekdaySymbols = newValue
}
}
internal var _shortWeekdaySymbols: [String]? { willSet { _reset() } }
open var shortWeekdaySymbols: [String] {
get {
guard let symbols = _shortWeekdaySymbols else {
let cfSymbols = CFDateFormatterCopyProperty(_cfObject, kCFDateFormatterShortWeekdaySymbols) as! NSArray
return cfSymbols.allObjects as! [String]
}
return symbols
}
set {
_shortWeekdaySymbols = newValue
}
}
internal var _amSymbol: String? { willSet { _reset() } }
open var amSymbol: String {
get {
guard let symbol = _amSymbol else {
return (CFDateFormatterCopyProperty(_cfObject, kCFDateFormatterAMSymbol) as! NSString)._swiftObject
}
return symbol
}
set {
_amSymbol = newValue
}
}
internal var _pmSymbol: String? { willSet { _reset() } }
open var pmSymbol: String {
get {
guard let symbol = _pmSymbol else {
return (CFDateFormatterCopyProperty(_cfObject, kCFDateFormatterPMSymbol) as! NSString)._swiftObject
}
return symbol
}
set {
_pmSymbol = newValue
}
}
internal var _longEraSymbols: [String]? { willSet { _reset() } }
open var longEraSymbols: [String] {
get {
guard let symbols = _longEraSymbols else {
let cfSymbols = CFDateFormatterCopyProperty(_cfObject, kCFDateFormatterLongEraSymbols) as! NSArray
return cfSymbols.allObjects as! [String]
}
return symbols
}
set {
_longEraSymbols = newValue
}
}
internal var _veryShortMonthSymbols: [String]? { willSet { _reset() } }
open var veryShortMonthSymbols: [String] {
get {
guard let symbols = _veryShortMonthSymbols else {
let cfSymbols = CFDateFormatterCopyProperty(_cfObject, kCFDateFormatterVeryShortMonthSymbols) as! NSArray
return cfSymbols.allObjects as! [String]
}
return symbols
}
set {
_veryShortMonthSymbols = newValue
}
}
internal var _standaloneMonthSymbols: [String]? { willSet { _reset() } }
open var standaloneMonthSymbols: [String] {
get {
guard let symbols = _standaloneMonthSymbols else {
let cfSymbols = CFDateFormatterCopyProperty(_cfObject, kCFDateFormatterStandaloneMonthSymbols) as! NSArray
return cfSymbols.allObjects as! [String]
}
return symbols
}
set {
_standaloneMonthSymbols = newValue
}
}
internal var _shortStandaloneMonthSymbols: [String]? { willSet { _reset() } }
open var shortStandaloneMonthSymbols: [String] {
get {
guard let symbols = _shortStandaloneMonthSymbols else {
let cfSymbols = CFDateFormatterCopyProperty(_cfObject, kCFDateFormatterShortStandaloneMonthSymbols) as! NSArray
return cfSymbols.allObjects as! [String]
}
return symbols
}
set {
_shortStandaloneMonthSymbols = newValue
}
}
internal var _veryShortStandaloneMonthSymbols: [String]? { willSet { _reset() } }
open var veryShortStandaloneMonthSymbols: [String] {
get {
guard let symbols = _veryShortStandaloneMonthSymbols else {
let cfSymbols = CFDateFormatterCopyProperty(_cfObject, kCFDateFormatterVeryShortStandaloneMonthSymbols) as! NSArray
return cfSymbols.allObjects as! [String]
}
return symbols
}
set {
_veryShortStandaloneMonthSymbols = newValue
}
}
internal var _veryShortWeekdaySymbols: [String]? { willSet { _reset() } }
open var veryShortWeekdaySymbols: [String] {
get {
guard let symbols = _veryShortWeekdaySymbols else {
let cfSymbols = CFDateFormatterCopyProperty(_cfObject, kCFDateFormatterVeryShortWeekdaySymbols) as! NSArray
return cfSymbols.allObjects as! [String]
}
return symbols
}
set {
_veryShortWeekdaySymbols = newValue
}
}
internal var _standaloneWeekdaySymbols: [String]? { willSet { _reset() } }
open var standaloneWeekdaySymbols: [String] {
get {
guard let symbols = _standaloneWeekdaySymbols else {
let cfSymbols = CFDateFormatterCopyProperty(_cfObject, kCFDateFormatterStandaloneWeekdaySymbols) as! NSArray
return cfSymbols.allObjects as! [String]
}
return symbols
}
set {
_standaloneWeekdaySymbols = newValue
}
}
internal var _shortStandaloneWeekdaySymbols: [String]? { willSet { _reset() } }
open var shortStandaloneWeekdaySymbols: [String] {
get {
guard let symbols = _shortStandaloneWeekdaySymbols else {
let cfSymbols = CFDateFormatterCopyProperty(_cfObject, kCFDateFormatterShortStandaloneWeekdaySymbols) as! NSArray
return cfSymbols.allObjects as! [String]
}
return symbols
}
set {
_shortStandaloneWeekdaySymbols = newValue
}
}
internal var _veryShortStandaloneWeekdaySymbols: [String]? { willSet { _reset() } }
open var veryShortStandaloneWeekdaySymbols: [String] {
get {
guard let symbols = _veryShortStandaloneWeekdaySymbols else {
let cfSymbols = CFDateFormatterCopyProperty(_cfObject, kCFDateFormatterVeryShortStandaloneWeekdaySymbols) as! NSArray
return cfSymbols.allObjects as! [String]
}
return symbols
}
set {
_veryShortStandaloneWeekdaySymbols = newValue
}
}
internal var _quarterSymbols: [String]? { willSet { _reset() } }
open var quarterSymbols: [String] {
get {
guard let symbols = _quarterSymbols else {
let cfSymbols = CFDateFormatterCopyProperty(_cfObject, kCFDateFormatterQuarterSymbols) as! NSArray
return cfSymbols.allObjects as! [String]
}
return symbols
}
set {
_quarterSymbols = newValue
}
}
internal var _shortQuarterSymbols: [String]? { willSet { _reset() } }
open var shortQuarterSymbols: [String] {
get {
guard let symbols = _shortQuarterSymbols else {
let cfSymbols = CFDateFormatterCopyProperty(_cfObject, kCFDateFormatterShortQuarterSymbols) as! NSArray
return cfSymbols.allObjects as! [String]
}
return symbols
}
set {
_shortQuarterSymbols = newValue
}
}
internal var _standaloneQuarterSymbols: [String]? { willSet { _reset() } }
open var standaloneQuarterSymbols: [String] {
get {
guard let symbols = _standaloneQuarterSymbols else {
let cfSymbols = CFDateFormatterCopyProperty(_cfObject, kCFDateFormatterStandaloneQuarterSymbols) as! NSArray
return cfSymbols.allObjects as! [String]
}
return symbols
}
set {
_standaloneQuarterSymbols = newValue
}
}
internal var _shortStandaloneQuarterSymbols: [String]? { willSet { _reset() } }
open var shortStandaloneQuarterSymbols: [String] {
get {
guard let symbols = _shortStandaloneQuarterSymbols else {
let cfSymbols = CFDateFormatterCopyProperty(_cfObject, kCFDateFormatterShortStandaloneQuarterSymbols) as! NSArray
return cfSymbols.allObjects as! [String]
}
return symbols
}
set {
_shortStandaloneQuarterSymbols = newValue
}
}
internal var _gregorianStartDate: Date? { willSet { _reset() } }
open var gregorianStartDate: Date? {
get {
guard let startDate = _gregorianStartDate else {
return (CFDateFormatterCopyProperty(_cfObject, kCFDateFormatterGregorianStartDate) as? NSDate)?._swiftObject
}
return startDate
}
set {
_gregorianStartDate = newValue
}
}
open var doesRelativeDateFormatting = false { willSet { _reset() } }
}
extension DateFormatter {
public enum Style : UInt {
case none
case short
case medium
case long
case full
}
}