简体   繁体   English

你如何创建一个 Swift Date 对象?

[英]How do you create a Swift Date object?

How do you create a date object from a date in swift xcode.如何从 swift xcode 中的日期创建日期对象。

eg in javascript you would do: var day = new Date('2014-05-20');例如,在 javascript 中你会这样做: var day = new Date('2014-05-20');

Swift has its own Date type. Swift 有自己的Date类型。 No need to use NSDate .无需使用NSDate

Creating a Date and Time in Swift在 Swift 中创建日期和时间

In Swift, dates and times are stored in a 64-bit floating point number measuring the number of seconds since the reference date of January 1, 2001 at 00:00:00 UTC .在 Swift 中,日期和时间存储在 64 位浮点数中,用于测量自 2001 年 1 月 1 日参考日期 00:00:00 UTC以来的秒数。 This is expressed in the Date structure .这在Date结构中表示。 The following would give you the current date and time:以下将为您提供当前日期和时间:

let currentDateTime = Date()

For creating other date-times, you can use one of the following methods.要创建其他日期时间,您可以使用以下方法之一。

Method 1方法一

If you know the number of seconds before or after the 2001 reference date, you can use that.如果您知道 2001 年参考日期之前或之后的秒数,则可以使用它。

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

Method 2方法二

Of course, it would be easier to use things like years, months, days and hours (rather than relative seconds) to make a Date .当然,使用诸如年、月、日和小时(而不是相对秒)之类的东西来制作Date会更容易。 For this you can use DateComponents to specify the components and then Calendar to create the date.为此,您可以使用DateComponents指定组件,然后使用Calendar创建日期。 The Calendar gives the Date context. Calendar提供Date上下文。 Otherwise, how would it know what time zone or calendar to express it in?否则,它怎么知道用哪个时区或日历来表达它?

// 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(identifier: .gregorian) // since the components above (like year 1980) are for Gregorian
let someDateTime = userCalendar.date(from: dateComponents)

Other time zone abbreviations can be found here .其他时区缩写可以在 这里找到。 If you leave that blank, then the default is to use the user's time zone.如果您将其留空,则默认使用用户的时区。

Method 3方法三

The most succinct way (but not necessarily the best) could be to use DateFormatter .最简洁的方法(但不一定是最好的)可能是使用DateFormatter

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

The Unicode technical standards show other formats that DateFormatter supports. Unicode 技术标准显示DateFormatter支持的其他格式

Notes笔记

See my full answer for how to display the date and time in a readable format.有关如何以可读格式显示日期和时间,请参阅我的完整答案 Also read these excellent articles:还可以阅读这些优秀的文章:

This is best done using an extension to the existing NSDate class.这最好使用现有NSDate类的扩展来完成。

The following extension adds a new initializer which will create a date in the current locale using the date string in the format you specified.以下扩展添加了一个新的初始化程序,它将使用您指定格式的日期字符串在当前语言环境中创建一个日期。

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)
    }
 }

Now you can create an NSDate from Swift just by doing:现在您可以通过执行以下操作从 Swift 创建一个 NSDate:

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

Please note that this implementation does not cache the NSDateFormatter, which you might want to do for performance reasons if you expect to be creating many NSDate s in this way.请注意,此实现不会缓存 NSDateFormatter,如果您希望以这种方式创建许多NSDate出于性能原因,您可能希望这样做。

Please also note that this implementation will simply crash if you try to initialize an NSDate by passing in a string that cannot be parsed correctly.另请注意,如果您尝试通过传入无法正确解析的字符串来初始化NSDate ,则此实现将简单地崩溃。 This is because of the forced unwrap of the optional value returned by dateFromString .这是因为强制解dateFromString返回的可选值。 If you wanted to return a nil on bad parses, you would ideally use a failible initializer;如果你想在错误的解析上返回一个nil ,你最好使用一个可失败的初始化器; but you cannot do that now (June 2015), because of a limitation in Swift 1.2, so then you're next best choice is to use a class factory method.但是你现在不能这样做(2015 年 6 月),因为 Swift 1.2 的限制,所以你的下一个最佳选择是使用类工厂方法。

A more elaborate example, which addresses both issues, is here: https://gist.github.com/algal/09b08515460b7bd229fa .一个解决这两个问题的更详细的例子在这里: https : //gist.github.com/algal/09b08515460b7bd229fa


Update for Swift 5 Swift 5 更新

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

Swift doesn't have its own Date type, but you to use the existing Cocoa NSDate type, eg: Swift 没有自己的 Date 类型,但您可以使用现有的 Cocoa 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
    }
}

Which you can use like:您可以像这样使用:

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

Here's how I did it in Swift 4.2:这是我在 Swift 4.2 中的做法:

extension Date {

    /// Create a date from specified parameters
    ///
    /// - Parameters:
    ///   - year: The desired year
    ///   - month: The desired month
    ///   - day: The desired day
    /// - Returns: A `Date` object
    static func from(year: Int, month: Int, day: Int) -> Date? {
        let calendar = Calendar(identifier: .gregorian)
        var dateComponents = DateComponents()
        dateComponents.year = year
        dateComponents.month = month
        dateComponents.day = day
        return calendar.date(from: dateComponents) ?? nil
    }
}

Usage:用法:

let marsOpportunityLaunchDate = Date.from(year: 2003, month: 07, day: 07)

According to Apple documentation根据苹果文档

Example :例子 :

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

In, Swift 3.0 you have set date object for this way.在 Swift 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)
    }
}

Personally I think it should be a failable initialiser:我个人认为它应该是一个可失败的初始化程序:

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
        }
    }
}

Otherwise a string with an invalid format will raise an exception.否则,格式无效的字符串将引发异常。

According to @mythz answer, I decide to post updated version of his extension using swift3 syntax.根据@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)
    }
}

I don't use parse method, but if someone needs, I will update this post.我不使用parse方法,但如果有人需要,我会更新这篇文章。

I often have a need to combine date values from one place with time values for another.我经常需要将一个地方的日期值与另一个地方的时间值结合起来。 I wrote a helper function to accomplish this.我写了一个辅助函数来完成这个。

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)!

According to Apple's Data Formatting Guide根据 Apple 的数据格式指南

Creating a date formatter is not a cheap operation.创建日期格式化程序并不是一项廉价的操作。 If you are likely to use a formatter frequently, it is typically more efficient to cache a single instance than to create and dispose of multiple instances.如果您可能经常使用格式化程序,则缓存单个实例通常比创建和处置多个实例更有效。 One approach is to use a static variable一种方法是使用静态变量

And while I agree with @Leon that this should preferably be a failable initializer, it doesn't always have to be (just like there is UIImage(imageLiteralResourceName:) that will crash if the resource doesn't exist).虽然我同意 @Leon 这应该最好是一个可失败的初始化程序,但它并不总是必须是(就像UIImage(imageLiteralResourceName:)如果资源不存在就会崩溃一样)。

So here's my approach:所以这是我的方法:

extension DateFormatter {
  static let yyyyMMdd: DateFormatter = {
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd"
    formatter.calendar = Calendar(identifier: .iso8601)
    formatter.timeZone = TimeZone(secondsFromGMT: 0)
    formatter.locale = Locale(identifier: "en_US_POSIX")
    return formatter
  }()
}

extension Date {
    init?(yyyyMMdd: String) {
        guard let date = DateFormatter.yyyyMMdd.date(from: yyyyMMdd) else { return nil }
        self.init(timeInterval: 0, since: date)
    }

    init(dateLiteralString yyyyMMdd: String) {
        let date = DateFormatter.yyyyMMdd.date(from: yyyyMMdd)!
        self.init(timeInterval: 0, since: date)
    }
}

And now enjoy simply calling:现在享受简单的调用:

// For cases where the date exists for sure (eg. seed data)
Date(dateLiteralString: "2020-03-30")

// The rest of the time (eg. parsing unknown data)
guard let date = Date(yyyyMMdd: "2020-03-30") else { return nil }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM