Adeline
Adeline

Reputation: 475

Swift Date literal / Date initialisation from string

I need to initialize a date to a known, fixed, point in time. Swift lacking date literals, I tried :

extension DateFormatter
{
    convenience init(_ format: String)
    {
        self.init()
        self.dateFormat = format
    }
}

extension Date
{
    init?(_ yyyyMMdd: String)
    {
        let formatter = DateFormatter("yyyyMMdd")
        self = formatter.date(from: yyyyMMdd)
    }
}

Unfortunately, I can't write self = ... or return formatter.date... as part of the initializer.

However, I would very much like to write :

let date = Date("20120721")

How can I achieve this ?

Upvotes: 0

Views: 1482

Answers (1)

Martin R
Martin R

Reputation: 539795

You can initialize a struct by assigning a value to self. The problem in your case is that formatter.date(from:) returns an optional, so you have to unwrap that first:

extension Date {
    init?(yyMMdd: String) {
        let formatter = DateFormatter("yyyyMMdd")
        guard let date = formatter.date(from: yyMMdd) else {
            return nil
        }
        self = date
    }
}

You can even initialize a date from a string literal by adopting the ExpressibleByStringLiteral protocol:

extension Date: ExpressibleByStringLiteral {
    public init(stringLiteral value: String) {
        let formatter = DateFormatter("yyyyMMdd")
        self = formatter.date(from: value)!
    }
    public init(extendedGraphemeClusterLiteral value: String) {
        self.init(stringLiteral: value)
    }
    public init(unicodeScalarLiteral value: String) {
        self.init(stringLiteral: value)
    }

}

let date: Date = "20120721"

Note however that this would crash at runtime for invalid dates.

Two more remarks:

  • You should set the formatters locale to Locale(identifier: "en_US_POSIX") to allow parsing the date string independent of the user's locale settings.
  • The result depends on the current time zone, unless you also set the formatters time zone to a fixed value (such as TimeZone(secondsFromGMT: 0).

Upvotes: 6

Related Questions