I am working with dates in Swift. I have to convert from String to Date but some weird stuff is happening. When I run my code on a simulator and pass my date string to formatter, it returns nil. But when I run my code on a physical device it works perfectly.
class ChatViewController: MessagesViewController {
var uid: String
var isNewConversations:Bool
private var messages = [Message]()
private var selfSender: Sender?
var senderUid: String
var conversation_Id: String?
public static let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .long
formatter.locale = .current
return formatter
}()
}
and I am using it like this :
let date = ChatViewController.dateFromatter.date(from: dateString)
My date input in string is: “08-Jan-2023 at 8:57:10 PM GMT+5”
I just debug the whole code but I am not getting what is happening. When I debug it on physical device it works perfectly but when I run it on a simulator it is not working fine, i.e the debugger shows that in 'date' variables you have got nil.
Never use dateStyle and/or timeStyle when parsing a date string. Always use dateFormat. Styles can vary based on the user's locale and other settings on their device. It can also vary based on the user's language.
Since you need to parse a fixed format date string you need to provide a specific date format. You must also use a special locale on the date formatter since your fixed format date string is always in English.
public static let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "dd-MMM-yyyy 'at' h:mm:ss a Z" // Might need O instead of Z at the end.
return formatter
}()
How about this date formatter:
let customFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "dd-MMM-yyyy' at 'h:mm:ss a ZZZZ"
return formatter
}()
Related
I receive a timestamp from a JSON request, and I want to format it to a user-friendly format. Both the input, as the desired output are of type 'String'.
The format of the input timestamp is: 2020-03-07T12:18:26.347Z
Using the following code, I try to convert it to the desired format. But it will just output the value of Date(), indicating that the output of formatter.date(from: date) is nil.
What am I missing?
func convertDate(date: String) -> String {
let formatter = DateFormatter()
formatter.dateFormat = "d-M-y, HH:mm"
let convertedDate = formatter.date(from: date) ?? Date()
return formatter.string(from: convertedDate)
}
Your dateFormat doesn't match the format of your input string. You want something like:
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
After struggling with it for hours, this answer, together with the date format information found here, I figured it out. I did previously not describe to the dateformatter how the input string would look.
func convertDate(date: String) -> String {
let dateFormatter = DateFormatter()
// This is important - we set our input date format to match our input string
// if the format doesn't match you'll get nil from your string, so be careful
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
//`date(from:)` returns an optional so make sure you unwrap when using.
let dateFromString: Date? = dateFormatter.date(from: date)
let formatter = DateFormatter()
formatter.dateFormat = "dd-MM-yyyy, HH:mm"
//Using the dateFromString variable from before.
let stringDate: String = formatter.string(from: dateFromString!)
return stringDate
}
I know these questions are asked all the time about date formatters, however the issue I have is really odd
I need to convert a simple string to date as follows
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM/dd/yyyy"
let dateOfBirthString = "10/20/2002"
let dob: Date? = dateFormatter.date(from: dateOfBirthString)
This works fine in a playground but always returns nil in the app (with those exact values (albeit properties rather than hard coded strings)
Any help would be appreciated, its driving me nuts
extension String {
func toDateTime() -> Date {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
dateFormatter.timeZone = TimeZone(identifier: "UTC")
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
guard let date = dateFormatter.date(from: self) else {
preconditionFailure("Take a look to your format")
}
return date
}
}
try this extension
let dateOfBirthString = "10/20/2002"
let dob: Date? = dateOfBirthString.toDateTime()
use this extension like this and if you get any error then feel free to comment below
I'm storing some dates in coredata in Date format. In another viewcontroller, I want to retrieve those dates and convert them to string. I tried to achieve it like so...
if let bday = result.birthday {
print(bday)
let formatter = DateFormatter()
let bDateString = formatter.string(from: bday as Date)
print(bDateString)
self.birthdate = bDateString
}
Here, printing bday gives the proper date. But printing bDateString after converting to string gives nil. What am I doing wrong...?
Please provide format of date like this :
formatter.dateFormat = "MM-dd-yyyy" //provide your date format here
The issue is you have not provided date format.
Even you can use this extension
extension Date { static func getFormattedDate(string: String) -> String{
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss +zzzz" // This formate is input formated .
let formateDate = dateFormatter.date(from:"2018-02-02 06:50:16 +0000")!
dateFormatter.dateFormat = "dd-MM-yyyy" // Output Formated
print ("Print :\(dateFormatter.string(from: formateDate))")//Print :02-02-2018
return dateFormatter.string(from: formateDate)
} }
I am getting date string from server like that "2017-08-05T00:30:00.000+02:00". Below is my code for date formatter.
let dateFormatter: DateFormatter = DateFormatter()
let serverDateString = "2017-08-05T00:30:00.000+02:00"
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZZ"
dateFormatter.locale = Foundation.Locale(identifier: "en_US_POSIX")
let currentDate: Date = dateFormatter.date(from: serverDateString)!
But it returns 2017-08-04 22:30:00 +0000. Which is wrong. Any suggestions?
In Swift 3
You can change your server time string to UTC time Date as:
let dateFormatter: DateFormatter = DateFormatter()
var serverDateString = "2017-08-05T00:30:00.000+02:00"
let index = serverDateString.index(serverDateString.startIndex, offsetBy: 19)
serverDateString = serverDateString.substring(to: index)
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
dateFormatter.timeZone = TimeZone.init(identifier: "UTC")
let currentDate: Date = dateFormatter.date(from: serverDateString)!
Your Code for parsing date is correct: 2017-08-05T00:30:00.000+02:00 and 2017-08-04 22:30:00 +0000 represent the same time, just in different time zones. Your only problem is that Date doesn't actually store the time zone
yyyy-MM-dd'T'hh:mm:ss.SSSZZZZZZ
This is correct date formate for your input string. Here is the Apple Document for more description.
Here is my code:
var strInputDateString: String = "2017-08-05T00:30:00.000+02:00"
var dateFormat = DateFormatter()
dateFormat.dateFormat = "yyyy-MM-dd'T'hh:mm:ss.SSSZZZZZZ"
//Set new dateFormate
var date1: Date? = dateFormat.date(from: strInputDateString)
dateFormat.dateFormat = "dd-MM-YYYY hh:mm:ss"
// Your Desire
var strOutputDateString: String = dateFormat.string(from: date1!)
print("\(strInputDateString)")
print("\(strOutputDateString)")
output:
Main input String:2017-08-05T00:30:00.000+02:00
Converted String: 05-08-2017 04:00:00
For now, I tried to convert your date format with my custom. It's give me the perfect output.
Actually, your code is good.
I copied your data and ran it in playground.
What kind of format you want it be?
Try this
let dateFormatter: DateFormatter = DateFormatter()
let serverDateString = "2017-08-05T00:30:00.000+02:00"
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXX"
dateFormatter.locale = Foundation.Locale(identifier: "en_US_POSIX")
let currentDate: Date = dateFormatter.date(from: serverDateString)!
Hope this helps
The step you are missing is to again use your DateFormatter to format the date into a string. When you use print on the date, it will always show GMT. For illustration purposes, I've set the TimeZone to Berlin to match the original offset of +2:00.
let dateFormatter: DateFormatter = DateFormatter()
let serverDateString = "2017-08-05T00:30:00.000+02:00"
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZZ"
// Hard set to Berlin
dateFormatter.timeZone = TimeZone(identifier: "Europe/Berlin")
let currentDate: Date = dateFormatter.date(from: serverDateString)!
// Your missing step
dateFormatter.string(from: currentDate)
Remember that DateFormatters are about:
Parsing from a String - df.date(from: String)
Formatting from a Date - df.string(from: Date)
I want this date "2016-10-18 22:06:20 +0000" to "18-10-2016", is this possible? I managed to get the date as follows:
var formatter = DateFormatter()
formatter.dateFormat = "yyy-MM-dd'HH:mm:ss.SSSZ"
let stringDate = formatter.string(from: currentDate)
The above gives me "10/18/16", but how can I get "18-10-2016"?
Solution in Swift 3
extension Foundation.Date {
func dashedStringFromDate() -> String {
let dateFormatter = DateFormatter()
let date = self
dateFormatter.dateFormat = "dd-MM-yyyy"
return dateFormatter.string(from: date)
}
}
Example
let date = Foundation.Date()
let formatedDate = date.dashedStringFromDate()
Little about what you put in your question makes a lot of sense. You don't have a date as 2016-10-18 22:06:20 +0000. The code you posted converts a current Date into a string. But you claim you want that string to be in the format 18-10-2016 but your code uses a completely different format.
Why not just do:
var formatter = DateFormatter()
formatter.dateFormat = "dd-MM-yyyy"
let stringDate = formatter.string(from: currentDate)
This will convert the currentDate to a string in the format you mention in your question.
If you really have a string in the format of 2016-10-18 22:06:20 +0000 and you want to convert it to 18-10-2016, then you want two date formatters.
The first convert that original string to a date:
let string = "2016-10-18 22:06:20 +0000"
let formatter1 = DateFormatter()
formatter1.locale = Locale(identifier: "en_US_POSIX") // if this string was from web service or a database, you should set the locale
formatter1.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
guard let date = formatter1.date(from: string) else {
fatalError("Couldn't parse original date string")
}
If you then want to build a new string in the format of 18-10-2016, then you'd use a second formatter:
let formatter2 = DateFormatter()
formatter2.dateFormat = "dd-MM-yyyy"
let result = formatter2.string(from: date)