2014-06-06 33 views

回答

103

斯威夫特有它自己的Date類型。無需使用NSDate

創建

在斯威夫特,日期和時間都存儲在一個64位浮點數字測量,因爲在00:00 2001年1月1日的基準日期的秒數斯威夫特一個日期和時間:00 UTC。這表示在Date structure。以下將給出當前日期和時間:

let currentDateTime = Date() 

要創建其他日期時間,可以使用下列方法之一。

方法1

如果你知道秒之前或2001年的基準日期後的數字,你可以使用。

let someDateTime = Date(timeIntervalSinceReferenceDate: -123456789.0) // Feb 2, 1997, 10:26 AM 

方法2

當然,這將是更容易使用的東西像年,月,日,小時(而不是相對秒),以使Date。爲此,您可以使用DateComponents指定組件,然後使用Calendar創建日期。 Calendar給出Date上下文。否則,它如何知道要在哪個時區或日曆中表示?

// Specify date components 
var dateComponents = DateComponents() 
dateComponents.year = 1980 
dateComponents.month = 7 
dateComponents.day = 11 
dateComponents.timeZone = TimeZone(abbreviation: "JST") // Japan Standard Time 
dateComponents.hour = 8 
dateComponents.minute = 34 

// Create date from components 
let userCalendar = Calendar.current // user calendar 
let someDateTime = userCalendar.date(from: dateComponents) 

其他時區的縮寫,可以發現here。如果您留下空白,則默認使用用戶的時區。

方法3

最簡潔的方式(但不一定是最好的)可能是使用DateFormatter

let formatter = DateFormatter() 
formatter.dateFormat = "yyyy/MM/dd HH:mm" 
let someDateTime = formatter.date(from: "2016/10/08 22:31") 

Unicode technical standards show other formatsDateFormatter支持。

註釋

參見my full answer對於如何以可讀格式顯示日期和時間。還可以閱讀這些優秀的文章:

4

根據Apple documentation

例子:

var myObject = NSDate() 
let futureDate = myObject.dateByAddingTimeInterval(10) 
let timeSinceNow = myObject.timeIntervalSinceNow 
+3

不錯,但不回答問題,問題不在於時間間隔。 – zaph

43

斯威夫特沒有自己的日期類型,但你使用現有的可可NSDate類型,例如:

class Date { 

    class func from(year: Int, month: Int, day: Int) -> Date { 
     let gregorianCalendar = NSCalendar(calendarIdentifier: .gregorian)! 

     var dateComponents = DateComponents() 
     dateComponents.year = year 
     dateComponents.month = month 
     dateComponents.day = day 

     let date = gregorianCalendar.date(from: dateComponents)! 
     return date 
    } 

    class func parse(_ string: String, format: String = "yyyy-MM-dd") -> Date { 
     let dateFormatter = DateFormatter() 
     dateFormatter.timeZone = NSTimeZone.default 
     dateFormatter.dateFormat = format 

     let date = dateFormatter.date(from: string)! 
     return date 
    } 
} 

您可以使用這樣的:

var date = Date.parse("2014-05-20") 
var date = Date.from(year: 2014, month: 05, day: 20) 
+0

我不得不改變這一行:var date = gregorian?.dateFromComponents(c)但我不明白爲什麼,並且解析返回的dateFmt.dateFromString也在抱怨。任何線索?啊,我已經將函數的返回類型從NSDate更改爲NSDate?讓它編譯。但我不確定爲什麼它需要是可空的。 –

+0

@TheSenator NSCalendar init返回一個可選的(?),所以gregorian是一個可選的(?)。訪問一個可選的需要可選的鏈接來訪問它,所以gregorian?.dateFromCoomponents是可選的鏈接,用於解包來自gregorian(NSCalendar)選項的值。更多可選鏈接[這裏](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/OptionalChaining.html) –

+0

NSGregorianCalendar從iOS 8開始已棄用,因此請使用NSCalendarIdentifierGregorian代替 – Knightsy

107

這是最好的使用擴展到現有NSDate類完成。

以下擴展添加了一個新的初始化程序,它將使用您指定格式的日期字符串在當前語言環境中創建一個日期。

extension NSDate 
{ 
    convenience 
     init(dateString:String) { 
     let dateStringFormatter = NSDateFormatter() 
     dateStringFormatter.dateFormat = "yyyy-MM-dd" 
     dateStringFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX") 
     let d = dateStringFormatter.dateFromString(dateString)! 
     self.init(timeInterval:0, sinceDate:d) 
    } 
} 

現在,你可以通過做創建斯威夫特一個NSDate:

NSDate(dateString:"2014-06-06") 

請注意,此實現不緩存NSDateFormatter,你可能希望出於性能的考慮,如果你希望做以這種方式創建許多NSDate

另請注意,如果您嘗試通過傳入無法正確解析的字符串來初始化NSDate,則此實現將僅會崩潰。這是因爲強制打開dateFromString返回的可選值。如果你想在錯誤的分析中返回一個nil,你最好使用一個可靠的初始化程序;但你現在不能這樣做(2015年6月),因爲Swift1.2的限制,所以下一個最好的選擇是使用類工廠方法。

解決這兩個問題的更詳細的示例如下:https://gist.github.com/algal/09b08515460b7bd229fa

+8

那麼這裏有什麼「便利」這個詞呢? –

+15

它表明擴展提供了一個初始化程序,實際上它將初始化委託給已經存在的指定初始化程序,在本例中爲NSDate.init(timeInterval:,sinceDate :)初始化程序。這在Swift編程語言手冊的第275頁中有描述。 – algal

+1

我在上面的代碼中看到的一個缺陷是每次訪問函數時重新創建'NSDateFormatter'。作爲[日期格式指南](https://developer.apple.com/library/ios/documentation/cocoa/Conceptual/DataFormatting/Articles/dfDateFormatting10_4.html#//apple_ref/doc/uid/TP40002369-SW10)states _Creating a日期格式化程序不是一個便宜的操作_。此外,該類自iOS7開始就是線程安全的,因此可以安全地將其用於所有'NSDate'擴展。 –

1

我經常需要將一個地方的日期值與另一個地方的時間值結合起來。我寫了一個輔助函數來完成這個任務。

let startDateTimeComponents = NSDateComponents() 
startDateTimeComponents.year = NSCalendar.currentCalendar().components(NSCalendarUnit.Year, fromDate: date).year 
startDateTimeComponents.month = NSCalendar.currentCalendar().components(NSCalendarUnit.Month, fromDate: date).month 
startDateTimeComponents.day = NSCalendar.currentCalendar().components(NSCalendarUnit.Day, fromDate: date).day 
startDateTimeComponents.hour = NSCalendar.currentCalendar().components(NSCalendarUnit.Hour, fromDate: time).hour 
startDateTimeComponents.minute = NSCalendar.currentCalendar().components(NSCalendarUnit.Minute, fromDate: time).minute 
let startDateCalendar = NSCalendar(identifier: NSCalendarIdentifierGregorian) 
combinedDateTime = startDateCalendar!.dateFromComponents(startDateTimeComponents)! 
3

這種方式,雨燕3.0已經設置日期對象。

extension Date 
{ 
    init(dateString:String) { 
     let dateStringFormatter = DateFormatter() 
     dateStringFormatter.dateFormat = "yyyy-MM-dd" 
     dateStringFormatter.locale = Locale(identifier: "en_US_POSIX") 
     let d = dateStringFormatter.date(from: dateString)! 
     self(timeInterval:0, since:d) 
    } 
} 
+0

我會在哪裏放這個代碼? –

+0

@ Zonker.in.Geneva無處不在你想要的。創建單獨的文件,稱之爲「Extension」,idk。 – Aleksandr

1

我個人認爲這應該是一個failable初始化器:

extension Date { 

    init?(dateString: String) { 
     let dateStringFormatter = DateFormatter() 
     dateStringFormatter.dateFormat = "yyyy-MM-dd" 
     if let d = dateStringFormatter.date(from: dateString) { 
      self.init(timeInterval: 0, since: d) 
     } else { 
      return nil 
     } 
    } 
} 

否則具有無效格式的字符串將引發異常。

1

根據@mythz的回答,我決定使用swift3語法發佈其擴展的更新版本。

extension Date { 
    static func from(_ year: Int, _ month: Int, _ day: Int) -> Date? 
    { 
     let gregorianCalendar = Calendar(identifier: .gregorian) 
     let dateComponents = DateComponents(calendar: gregorianCalendar, year: year, month: month, day: day) 
     return gregorianCalendar.date(from: dateComponents) 
    } 
} 

我不使用parse方法,但是,如果有人需要,我會更新這個帖子。