Date formatting in Swift that supports iOS 13+ - ios

I bet this is simple. I'm trying in Xcode playgrounds to play with getting a string date
let string = "2022-11-27 00:00:00 +0000"
and converting that into a Date object that's formatted like DD-MM-YYYY
func airdateFormat(_ key: String) -> Date? {
let expectedFormat = Date().formatted(.dateTime.day().month(.wide).year())
let date = try! Date(strategy: expectedFormat)
return date
}
I also tried
func airdateFormat(_ key: String) -> Date? {
guard let dateString = self[key] as? String else { return nil }
let dateFormatted = DateFormatter.dateFormat(fromTemplate: "MM-DD-YYYY", options: Int, locale: Locale?)
return dateFormatted().date(from: dateString)
}
}
I'm parsing this Date string from json hence the guard/else statement

You need to use a format that matches your input to parse the string to a Date
If you want to use the DateFormatter
let string = "2022-11-27 12:34:56 +0000"
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
let date = formatter.date(from: string)
and for recent OS versions you use a FormatStyle
let formatStyle = Date.FormatStyle()
.year(.defaultDigits)
.month(.twoDigits)
.day(.twoDigits)
.hour()
.minute()
.second()
.timeZone()
let date = try formatStyle.parse(string)

Related

DateFormatter not working Swift with Hour and minute second

Getting nil converting date string to date
func convertDateFormater(dateStr: ""2022-10-22T22:22:16:2216Z"") -> String? {
let inputFormatter = DateFormatter()
inputFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
let strSelected = inputFormatter.date(from: dateStr)
}
convertDateFormater(dateStr: "2022-10-23T00:00:00.000Z") // Working fine
***convertDateFormater(dateStr: ""2022-10-22T22:22:16:2216Z"") // Not Working fine getting nil***
Should work convertDateFormater(dateStr: ""2022-10-22T22:22:16:2216Z"")
There are many issues in this code
"" … "" is invalid syntax.
There is no parameter type defined.
Nothing – or even the wrong type – is returned.
Z is a format specifier, it must not be wrapped in single quotes.
Apart from that look at your date string. A colon between seconds and milliseconds is very uncommon but it works with this code
func convertDateFormater(dateStr: String) -> Date? {
let inputFormatter = DateFormatter()
inputFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss:SSSZ"
return inputFormatter.date(from: dateStr)
}
convertDateFormater(dateStr: "2022-10-22T22:22:16:2216Z")
But you cannot convert both strings (colon and period separator) with the same date format.
To do so you need a second parameter
func convertDateFormater(dateStr: String, hasColonMillisecondSeparator: Bool = false) -> Date? {
let inputFormatter = DateFormatter()
inputFormatter.dateFormat = hasColonMillisecondSeparator ? "yyyy-MM-dd'T'HH:mm:ss:SSSZ" : "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
return inputFormatter.date(from: dateStr)
}
convertDateFormater(dateStr: "2022-10-23T00:00:00.000Z")
convertDateFormater(dateStr: "2022-10-22T22:22:16:2216Z", hasColonMillisecondSeparator: true)

Using DateFormatter to parse this string into a Date?

I'm hitting a webservice that is returning a string in the following format:
"yyyy-MM-dd'T'HH:mmZ"
It's very close to the standard UTC format, but just without the ss at the end. My issue is that my dateFormatter is always returning nil...and I have tried to make sure that locale and everything else is setup properly.
Here is an example of an actual string:
2019-12-26T00:00Z
Here is the code that creates the DF:
extension DateFormatter {
#objc static func defaultDateFormat(_ format: String) -> DateFormatter {
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "US")
formatter.dateFormat = format
return formatter
}
func date(from string: String?) -> Date? {
if let string = string {
return self.date(from: string)
} else {
return nil
}
}
func string(fromOptional date: Date?) -> String? {
if let date = date {
return self.string(from: date)
} else {
return nil
}
}
func string(fromOptional date: Date?, defaultStr: String) -> String {
return self.string(fromOptional: date) ?? defaultStr
}
}
let df = DateFormatter.defaultDateFormat("yyyy-MM-dd'T'HH:mmZ")
let date: Date? = df.date(from: __dateString__) // always nil
A few observations:
You want to use a locale of en_US_POSIX, an invariant locale that always works for ISO 8601 / RFC 3339 date strings. See Technical Q&A 1480.
If you want to use this formatter to convert a date back to a string like 2019-12-26T00:00Z, you will want to:
Use X (or ZZZZZ or XXXXX) in your format string, not Z (see the “zone” section in the table at Date Format Patterns and you’ll see how these various time zone patterns, e.g. Z, ZZZZZ, and X, are interpreted); and
Set the timeZone of the formatter to use Zulu/GMT/UTC.
Thus:
#objc static func defaultDateFormat(_ format: String) -> DateFormatter {
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = format
return formatter
}
And
let df = DateFormatter.defaultDateFormat("yyyy-MM-dd'T'HH:mmX")
let date = df.date(from: "2019-12-26T00:00Z")
Or
let string = df.string(from: Date())

How to format date in Swift that similarly matches Json?

I am having trouble generating Date objects that match the json output. In http://chartapi.finance.yahoo.com/instrument/1.0/aapl/chartdata;type=quote;range=1y/json - the dates are in the following format "Date": 20151013. In order to get 2015-10-13, first I use Alamofire & SwiftJSON in my API call and JSON parsing. Here are some relevant lines from my code:
let dateInteger = subJson["Date"].int
if dateInteger != nil {
let editedDateInt = dateInteger!
let dateString = NSMutableString(string: "\(editedDateInt)")
dateString.insert("-", at: 4)
dateString.insert("-", at: 7)
chartpoint.date = Formatters.sharedInstance.dateFromString(key: dateString as String) }
// date extension
public class Formatters {
public static let sharedInstance = Formatters()
private let dateKeyFormatter = DateFormatter()
init() { dateKeyFormatter.dateFormat = "yyyy-MM-dd" }
public func dateFromString(key: String?) -> Date? {
guard let key = key else { return nil }
return dateKeyFormatter.date(from: key) }
Problem is the output came up Optional(2015-10-12 16:00:00 +0000). Not quite 2015-10-13 that I was expecting. How do I fix this? Is this related to user's Locale or TimeZone?
Check this out
Swift 3.0
let dateFromServer = "20151013"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyyMMdd"
dateFormatter.timeZone = TimeZone(abbreviation: "GMT")
let date = dateFormatter.date(from: dateFromServer)
dateFormatter.dateFormat = "yyyy-MM-dd"
let finalDate = dateFormatter.string(from: date!)
print(finalDate)
Output:
2015-10-13
As suggested by #rmaddy changed the format style form YYYY to yyyy.

Swift full date with milliseconds

Is any way to print full date with milliseconds?
For example, I'm doing this:
print("\(NSDate())")
But I'm just get this:
2016-05-09 22:07:19 +0000
How can I get the milliseconds too in the full date?
Updated for Swift 3
let d = Date()
let df = DateFormatter()
df.dateFormat = "y-MM-dd H:mm:ss.SSSS"
df.string(from: d) // -> "2016-11-17 17:51:15.1720"
When you have a Date d, you can get the formatted string using a NSDateFormatter. You can also use a formatter to turn a string date based on your format into a Date
See this chart for more on what dateFormat can do http://waracle.net/iphone-nsdateformatter-date-formatting-table/
Swift 5 to/from Timestamp String Extension
extension String {
static func timestamp() -> String {
let dateFMT = DateFormatter()
dateFMT.locale = Locale(identifier: "en_US_POSIX")
dateFMT.dateFormat = "yyyyMMdd'T'HHmmss.SSSS"
let now = Date()
return String(format: "%#", dateFMT.string(from: now))
}
func tad2Date() -> Date? {
let dateFMT = DateFormatter()
dateFMT.locale = Locale(identifier: "en_US_POSIX")
dateFMT.dateFormat = "yyyyMMdd'T'HHmmss.SSSS"
return dateFMT.date(from: self)
}
}

How to convert a date string from Rails into Swift

Please bear with me as I'm new to Swift: I'm writing a little app that calls an API (Rails) which return some data. The problem I'm having is that the date provided by the API comes like this: yyyy-MM-dd'T'HH:mm:sssZ my function expects yyyy-MM-dd'T'HH:mm:ssZ Please note the extra second
Here's my function:
public func dateFromString(date: String, format: String) -> NSDate {
if dateFormatter == nil {
dateFormatter = NSDateFormatter()
}
dateFormatter!.dateFormat = format
return dateFormatter!.dateFromString(date)!
}
On the console, when I try to run the app I get this:
date String "2015-04-13T12:48:23.310Z"
format String "yyyy-MM-dd'T'HH:mm:ssZ"
Any ideas on how I should resolve this?
You can do if you use the SSS as format string, like below.
"yyyy-MM-dd'T'HH:mm:ss.SSSZ"
See also: Date Format Patterns
You can use the following function:
func dateFromate(_ stringTime:String) -> String{
//"2015-04-13T12:48:23.310Z"
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
guard let date2 = formatter.date(from: stringTime) else{
return stringTime
}
let date1 = Date()
return date1.offset(from: date2)
}

Resources