Parse ISO8601 in swift - ios

I am parsing 2020-06-09T18:11:26.904Z and it returns this 09 Jun, 11:11 pm it should be 06:11 pm
I have tried this solution Parsing a ISO8601 String to Date in Swift but it also works like the same.
Here's my code.
let df = DateFormatter()
df.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
guard let date = df.date(from: dateTime) else {
return nil
}
df.dateFormat = "dd MMM, hh:mm a"
df.amSymbol = "am"
df.pmSymbol = "pm"
let stringFromDate = df.string(from: date)
return stringFromDate
I know I could ask it on the mentioned link but due to the new user I couldn't add comment on that.

You didn't set the timezone of the output date, so it's defaulting to your systems' timezone rather than UTC (which is what you were expecting).

Related

Convert string containing date to Date

I'm having issues converting a string to date on swift, maybe it is something obvious but I don't get it.
I'm trying to convert "Jan 18, 2022 04:39PM GMT" this string into a Date. My code looks like this:
let str = "Jan 18, 2022 04:39PM GMT"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM d, YYYY hh:mma z"
let date = dateFormatter.date(from: str)
print(date)
And console shows: Optional(2021-12-19 16:39:00 +0000)
Any idea what's wrong in this formatter?
In addition to the Date being shown as an Optional, your format string appears to be wrong. "YYYY" should be "yyyy", so the whole line that assigns the formatter should be:
dateFormatter.dateFormat = "MMM d, yyyy hh:mma z"
That change yields the output
"Optional(2022-01-18 16:39:00 +0000)"
In addition, you should really force the calendar to Gregorian or iso8601, and set its locale to "en_US_POSIX:
An improved version of the date formatter could would look like this:
(from Leo's edit.)
let str = "Jan 18, 2022 04:39PM GMT"
let dateFormatter = DateFormatter()
dateFormatter.calendar = .init(identifier: .iso8601)
dateFormatter.locale = .init(identifier: "en_US_POSIX")
dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
dateFormatter.dateFormat = "MMM d, yyyy hh:mma z"
if let date = dateFormatter.date(from: str) {
let dateString = dateFormatter.string(from: date)
print(dateString == str) // true
}
The code written for converting date is correct, also converted date is correct. But final result is optional so you are getting date like Optional(2021-12-19 16:39:00 +0000).
Also the date formatter is wrong.
So please unwrap the date to get actual date without optional.
dateFormatter.dateFormat = "MMM d, yyyy hh:mma z"
guard let convertedDate = date else {
return
}
print(convertedDate)

String to date conversion sometimes returns nil with DateFormatter

I just read over this post which details that you need to set a locale before the format before attempting to convert a given string back to a date.
I have the below code that follows that format but the conversion from string to date still seems to return nil though in the playground it seems to work fine.
// originalDate style is the .full style, "Friday, December 10, 2021 at 4:17:04 PM Pacific Standard Time"
let df: DateFormatter = DateFormatter()
df.locale = Locale(identifier: "en_US_POSIX")
df.dateFormat = "MMM d, yyyy" // Sep 12, 2018 format'
let newDate = df.date(from: originalDate)
let newStringDate = df.string(from: newDate!) // throws found nil when unwrapping
What could be causing this?
Edit 1: I'm pulling a string type out of a sqlite db using SQLite.swift
Answer for your question (string to date is nil): While converting from string to date, you have to use the same format as String. I assume the originalDate from your comments. You have to change your code like this
let originalDate = "Friday, December 10, 2021 at 4:17:04 PM"
let df: DateFormatter = DateFormatter()
df.locale = Locale(identifier: "en_US_POSIX")
df.dateFormat = "EEEE, MMMM d, yyyy 'at' h:mm:ss a"
let newDate = df.date(from: originalDate)
print(newDate)
If you again want string from date then you can again specify which format you want.
df.dateFormat = "MMM d, yyyy" // Sep 12, 2018 format'
let newStringDate = df.string(from: newDate!)
print(newStringDate)
Note: If you try to log the newDate value in the console using print, sometimes it shows nil. In that case, you can try 'po newDate' in the console.

Convert date string to date object

Actual string - January 31, 2020 at 11:59:59 p.m. (ET).
format - "MMMM d, yyyy 'at' hh:mm:ss aa"
Not able to convert this string to Date object. Tried various date format and but unable to change string to Date object.
Please help
You could delete the non-standard character . between p and m and escape the parentheses around the time zone
let dateString = "January 31, 2020 at 11:59:59 p.m. (ET)"
let trimmedDateString = dateString.replacingOccurrences(of: ".m.", with: "m")
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "MMMM d, yyyy 'at' hh:mm:ss a (v)"
let date = formatter.date(from: trimmedDateString)
let raw = "January 31, 2020 at 11:59:59 p.m. (ET)"
func getDateFrom(_ raw: String) -> Date? {
if let i = (raw.range(of: "(")?.lowerBound) { // get index of open parenthesis
var zone: TimeZone?
let dateString = String(raw.prefix(upTo: i)) // January 31, 2020 at 11:59:59 p.m.
let zoneString = String(raw.suffix(from: i)) // (ET)
switch zoneString { // determine time zone
case "(ET)", "(EST)", "(EDT)": // study your data source and learn how they may express time zones
zone = TimeZone(abbreviation: "EDT")
default:
return nil // failure
}
let formatter = DateFormatter()
formatter.dateFormat = "MMMM d, yyyy 'at' hh:mm:ss a"
formatter.timeZone = zone
formatter.amSymbol = "a.m."
formatter.pmSymbol = "p.m."
if let date = formatter.date(from: dateString) {
return date
} else {
return nil
}
} else {
return nil
}
}
if let date = getDateFrom(raw) {
print(date) // 2020-02-01 04:59:59 +0000
}
This should be a good starting point. There are a number of ways to do this, such as whether you want it to fail if a time zone can't be determined, how to extract the time zone (using abbreviations, identifiers, seconds from GMT), etc. I like vadian's answer if I was completely comfortable with the time zone. But time zones are so inconsistent and surprisingly non-standardized when expressed as strings, that I'd rather dedicate a mechanism to getting it and making sure it's valid.
That said, this is a relatively crude example of where I'd begin—a finished version would be more nuanced. In this example, if the time zone fails, the function fails.

iOS Swift: how to convert specific date string format to Date object, when string contains time zone abbreviation?

I am getting a date string from server in the format of "March 08, 2018 16:00:00 PST" where there is a lot of whitespace between Month & Date.
My intention is to basically remove those extra whitespaces. My idea is that- I will convert the string into Date object, and then convert back to string.
How can I convert this into Date object using Date Formatter, taking timezone into consideration.
I am concerned about the "PST" here. While converting the Date to String, I will need in the format - "March 08, 2018 16:00:00 PST" i.e. PST (or whatever time zone comes in) should stay intact in the final string.
extension String {
func getDate(fromFormat format: String = "MMMM dd, yyyy HH:mm:ss zzz") -> Date? {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = format
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
return dateFormatter.date(from: self)
}
}
let myDateString = "March 08, 2018 16:00:00 PST"
myDateString.getDate()
You can call with other time formats too.
Try this
let isoDate = "March 08, 2018 16:00:00 PST"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMMM dd, yyyy HH:mm:ss z"
let date = dateFormatter.date(from: isoDate)!
Try this
class func stringToDate (dateString:String, dateFormat:String) -> Date? {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = dateFormat
let dateFromString = dateFormatter.date(from: dateString)
return dateFromString
}

Swift: DateFormatter not able to parse date

I've a specific time format which I want to use to generate a Date object.
This is the format:
Fri, 17 Mar 2017 08:42:00 +0100
Here is my Swift code that should create the data object:
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "EEE, dd MMM yyyy HH:mm:ss xx"
let d = dateFormatter.date(from: value)
The generation of the Date object with dateFormatter.date does always return nil. But I cant see what's wrong in my formatting string.
Can anyone see my error?
I have test it and works perfectly.
Could you test this code line to identify you Locale configuration?
print(Locale.current.identifier)
I only made a little change related to the Optional result that DateFormatter method returns
import Foundation
let the_date: String = "Fri, 17 Mar 2017 08:42:00 +0100"
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale.current
dateFormatter.dateFormat = "EEE, dd MMM yyyy HH:mm:ss xx"
if let d = dateFormatter.date(from: the_date)
{
print(d)
}

Resources