Convert string containing date to Date - ios

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)

Related

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.

DateFormater error only when running on iOS 13

I have a function to convert string to date format. This function works as expected on iOS 12 but on iOS 13. I get this error:
"Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value"
Here is my code:
func ConvertDateAndTimeFormat2() {
let timeDate = "2019-09-24 15:00:00 +0000"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss +zzzz"
dateFormatter.timeZone = TimeZone(abbreviation: "GMT+3:00")
var dateObj:Date!
dateObj = dateFormatter.date(from: timeDate)
dateFormatter.dateFormat = "EEEE, MMM d, yyyy"
dateFormatter.timeZone = TimeZone(abbreviation: "GMT+3:00")
let timeFormatter = DateFormatter()
timeFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss +zzzz"
timeFormatter.timeZone = TimeZone(abbreviation: "GMT+3:00")
var timeObj:Date!
timeObj = timeFormatter.date(from: timeDate)
timeFormatter.dateFormat = "HH:mm"
timeFormatter.timeZone = TimeZone(abbreviation: "GMT+3:00")
let timef = "\(timeFormatter.string(from: timeObj!))"
let Date = "\(dateFormatter.string(from: dateObj!))"
}
Please change your dateformat and use "yyyy-MM-dd HH:mm:ss Z" and try.
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
For more details please visit https://nsdateformatter.com/
If you are trying to convert string time which in 24 hours format (Ex 15:25:00 / HH:mm:ss) then enable your device 24-Hour Time option. It might solve the issue in IOS 13.3
You may find the option here
Settings -> General -> Date & Time
There are many issues with your code. There is no reason to create two Date objects from one string. Just parse the original string once. Then you can create your date string and time string with the desired formats from that one date.
You should also use the special locale of en_US_POSIX when parsing fixed format date strings. There is also no need to set a timezone when parsing the original date string. The string provides its own timezone. The +0000 means it is UTC time.
You may not want to provide a timezone when converting the date to your final strings either. Most likely you want strings in the user's locale timezone, not some hardcoded timezone.
Here's your code cleaned up a lot:
func convertDateAndTimeFormat2() {
let timeDate = "2019-09-24 15:00:00 +0000"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
if let dateObj = dateFormatter.date(from: timeDate) {
dateFormatter.dateFormat = "EEEE, MMM d, yyyy"
dateFormatter.timeZone = TimeZone(abbreviation: "GMT+3:00") // Probably not needed
let timeFormatter = DateFormatter()
timeFormatter.dateFormat = "HH:mm"
timeFormatter.timeZone = TimeZone(abbreviation: "GMT+3:00") // Probably not needed
let timef = timeFormatter.string(from: dateObj)
let datef = dateFormatter.string(from: dateObj)
print("Date: \(datef), time: \(timef)")
}
}
convertDateAndTimeFormat2()
Output:
Date: Tuesday, Sep 24, 2019, time: 18:00

Swift date from string always returns nil

I have a date that is a string that looks like this:
Apr 25 2018 12:00AM
What I am trying to do is convert this date format to yyyy-MM-dd and then convert it back to a string, I have a tried the following:
let formatter = DateFormatter()
formatter.dateFormat = "M dd yyyy h:mm A"
let SLAIssuedFinalGradingDate = formatter.date(from: tableDic["SLAIssuedFinalGradingDate"] as! String)
formatter.dateFormat = "yyyy-MM-dd"
let SLAIssuedFinalGradingDateString = formatter.string(from: SLAIssuedFinalGradingDate!)
But SLAIssuedFinalGradingDate always returns nil, what am I doing wrong?
Your dateFormat for Apr 25 2018 12:00AM is not right. You are using M dd yyyy h:mm A, but format would be MMM dd yyyy hh:mma.
Use this link to check date format.
Code Should be:
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "MMM dd yyyy hh:mma"
let SLAIssuedFinalGradingDate = formatter.date(from: tableDic["SLAIssuedFinalGradingDate"] as! String)
formatter.dateFormat = "yyyy-MM-dd"
let SLAIssuedFinalGradingDateString = formatter.string(from: SLAIssuedFinalGradingDate!)
Your dateFormat string is incorrect. A DateFormatter will always return nil if the dateFormat string does not match the supplied string.
"MMM dd yyyy hh:mma"
This is what you're after. I suggest you review a DateFormatter cheat sheet and familiarise yourself with the symbols.

How to get the day of the week from a date in Swift

I can print the date in this format: Mon, Mar 19, 2018, but I am not sure how to get the Day of the week in this format.
Please help
let dateFormatter = DateFormatter()
// uncomment to enforce the US locale
// dateFormatter.locale = Locale(identifier: "en-US")
dateFormatter.setLocalizedDateFormatFromTemplate("EEE MMM d yyyy")
print(dateFormatter.string(from: Date())) // "Tue, Mar 20, 2018" for en-US locale
Note that I am using a template to provide the exact format, therefore the format will be properly localized in every language.
To get the day for a particular date:
let customDateFormatter = DateFormatter()
print(customDateFormatter.weekdaySymbols[Calendar.current.component(.weekday, from: Date())])
// "Wednesday"
source
Rather than needing to spell out a date format. I would simplify it further to:
dateFormatter.dateStyle = .full
Or if you just want the day:
dateFormatter.dateFormat = "EEEE"
With swift 4
func timeStamp()->String {
let dateFormater = DateFormatter()
dateFormater.locale = Locale(identifier: "en-US")
dateFormater.setLocalizedDateFormatFromTemplate("EEE MMM d yyyy")
return dateFormatter.string(from: Date())
}
Use it.
let getTimeStamp = timeStamp()
print(getTimeStamp)
dateFormatter.dateFormat = "EEE, MMM dd, yyyy"
For dat of week in alphabets, you use EEEE or EEE similar to MMM & yyyy for month year.
The best way to change your date is follow this method.
func ChangeDateFormat(date:String,FromFormat: String, ToFormat: String) -> String {
let dateFormatter1 = DateFormatter()
dateFormatter1.dateFormat = FromFormat
let myDate = dateFormatter1.date(from: date)
dateFormatter1.dateFormat = ToFormat
if(myDate != nil){
let Date = dateFormatter1.string(from: myDate!)
return Date
}
else{
return ""
}
}
and then you can use this method like
String(ChangeDateFormat(date: StartDate, FromFormat: "yyyy-MM-dd hh:mm:ss a", ToFormat: "MMM d, yyyy"))
You can pass your date format in which format do you want in your case it should be
String(ChangeDateFormat(date: StartDate, FromFormat: "Pass your date format", ToFormat: "EEE MMM d, yyyy"))

Date Formatter in swift

i want to get this type of formate -> April 20, 2018 at 9:02:00 PM UTC+5:30
for firestore timestamp. i already try this code but do not get proper formate as above.
let date = Date()
let formatter = DateFormatter()
formatter.dateFormat = "MMMM d yyyy hh:mm:ss a Z"
formatter.timeZone = NSTimeZone(name: "IST") as TimeZone?
let result = formatter.string(from: date)
print(result)
already use this formatter formatter.dateFormat = "MMMM d yyyy'T'hh:mm:ss a Z"
Thanks
You can use like this:
let date = Date()
let formatter = DateFormatter()
formatter.dateFormat = "MMMM dd, yyyy 'at' hh:mm:ss a 'UTC'Z" //If you dont want static "UTC" you can go for ZZZZ instead of 'UTC'Z.
formatter.timeZone = TimeZone(abbreviation: "IST")
let result1 = formatter.string(from: date)
print(result1)
Note: If you do not want the UTC to be static in the string, you can also use the format "MMMM dd, yyyy 'at' hh:mm:ss a ZZZZ"
Thank you Larme For the format improvement
Output:
do like
let formatter = DateFormatter()
//If you want it in your specific format you can simply add 'UTC'
formatter.dateFormat = "MMMM dd, yyyy 'at' hh:mm:ss a 'UTC'Z"
formatter.timeZone = NSTimeZone(name: "IST") as TimeZone?
let result = formatter.string(from: Date())
print(result)
Note: if you want to set the currentTimezone for your string then use the format "MMMM dd, yyyy 'at' hh:mm:ss a ZZZZ"
you get the output as
Try this if you don't want leading zero in hour, when hour has single digit. Also you don't need to typecast NSTimeZone into TimeZone. You can directly use TimeZone.
let date = Date()
let formatter = DateFormatter()
formatter.dateFormat = "MMMM dd, yyyy 'at' h:mm:ss a 'UTC'Z"
formatter.timeZone = TimeZone(abbreviation: "IST")
let result = formatter.string(from: date)
print(result)
April 23, 2018 at 3:09:01 PM UTC+0530

Resources