I have a date string coming from back-end as "2022-08-16T13:44:11.8743234". Date formatting and conversion is the oldest skill in the book but I cannot figure out why I'm unable to convert that string to a Date object in Swift iOS. I just get nil with any source format I specify.
private func StringToDate(dateString: String) -> Date?
{
let formatter = DateFormatter()
formatter.dateFormat = "YYYY-MM-DDTHH:mm:ss.[nnnnnnn]"
let date = formatter.date(from: dateString)
return date //this is nil every time
}
DateTime2 is a more precise SQL Server extension of the normal C# DateTime, hence why the date string has 7 decimal places afters the seconds.
What am I doing wrong?
In your code the way you are handling the millisecond part is wrong. We use usually .SSS for milliseconds. Take a look at here it shows all the symbols related to date format.
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"
let date = dateFormatter.date(from: "2022-08-16T13:44:11.8743234")
print(date)
In addition to that you are using DD for day. DD means the day of the year(numeric). So it should be dd. Same case is applied for the year as well.
I'm trying to format this date: 2018-01-10T11:57:21.153 to Swift Date object like this:
let dateSentString = jsonDict["date"] as! String
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
let date = dateFormatter.date(from: dateSentString)!
For some reason, the app crashes on the last line.
What am I doing wrong? Thanks!
change the milli seconds format use 'SSS' specifier (with number of S's equal to number of digits of milliseconds ). for more information you get here
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"
from
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
Full code
let dateSentString = "2018-01-10T11:57:21.153"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"
let date = dateFormatter.date(from: dateSentString)!
print(date)
You have to first set formatter for date you are getting from JSON and then another formatter for the date you want.
First convert string fro JSON to a date variable by setting same format coming in JSON object .
Then you have to re-format that date variable into format you want.
I can write code if you want but it is better to try yourself.
Happy Coding
i am passing "01/12/2017" in the fromDate.text(textfield), but receiving unexpected output.
let formatter = DateFormatter.init()
formatter.dateFormat = "dd/mm/yyyy"
startDate = formatter.date(from: fromDate.text!)
print("startDate = \(startDate)")
output is : 31/12/2016
The format of date should be dd/MM/yyyy not dd/mm/yyyy. The mm indicates the minutes and MM indicates the month.
And also add the below line in your code
formatter.timeZone = TimeZone(abbreviation: "GMT+0:00")
This line of code set time zone. If you not, then you get 30/11/2017 in output.
The reason behind this is when string date not contain time then formatter assume that it is midnight and you also not given the timezone so it will take current timezone.
It has to be dd/MM/yyyy dateformat. MM in capital.
func convertToString(of dateTo: Date) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd/MM/yyyy" //Your New Date format as per requirement change it own
let newDate: String = dateFormatter.string(from: dateTo) //pass Date here
print(newDate) //New formatted Date string
return newDate
}
I've watching trough stack overflow to find the answer and I can't find it I want to cast this string value "1900-01-01T00:00:00" to Date format, I was trying with some formats like those:
"yyyy-MM-dd HH:mm:ss"
"EEE, dd MMM yyyy hh:mm:ss +zzzz"
"YYYY-MM-dd HH:mm:ss.A"
"yyyy-MM-dd HH:mm:ss.S"
but anyone of those its working.
and I want the date format like this
"dd-mm-yyyy"
Hope you can help me!
Thanks.
It is a two step process, first converting 1900-01-01T00:00:00 (known as a RFC 3999 or ISO 8601 date, referred to the specifications that define this format) into a Date object, and then converting that Date object back to a string in the form of 01-01-1900:
To convert your string in the form of 1900-01-01T00:00:00 into a Date object, you can use ISO8601DateFormatter:
let formatter = ISO8601DateFormatter()
formatter.formatOptions.remove(.withTimeZone)
let date = formatter.date(from: string)!
That is equivalent to the following DateFormat, in which one has to manually set the locale to en_US_POSIX (because RFC 3999/ISO 8601 dates use a Gregorian calendar, regardless of what the device's default calendar type) and sets the timeZone to GMT/Zulu, because usually RFC 3999/ISO 8601 dates are representing GMT unless specified otherwise:
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
let date = formatter.date(from: string)!
For more information about the importance of timezones and locales in parsing RFC 3999 and ISO 8601 dates, see Apple's Technical Q&A 1480.
Then, to convert that Date object to a string into 01-01-1900 (day, month, and year), you'd use a format string of dd-MM-yyyy (note the uppercase MM for "month", to distinguish it from mm for "minute"):
let formatter2 = DateFormatter()
formatter2.dateFormat = "dd-MM-yyyy"
let string = formatter2.string(from: date)
Two observations regarding the dateFormat string:
If this string is for displaying to the user, you might use use dateStyle rather than dateFormat, e.g.:
formatter2.dateStyle = .short
While this will generate a slightly different format, e.g. dd/MM/yy, the virtue of this approach is that the string will be localized (e.g. UK users will see MM/dd/yyyy, their preferred way of seeing short dates).
It just depends upon the purpose of your dd-MM-yyyy format. If it's for internal purposes, go ahead and use dateFormat. But if it's for showing dates in your UI, use dateStyle instead, and enjoy the localization that DateFormatter does automatically for you. For more information, see "Working With User-Visible Representations of Dates and Times" section of the DateFormatter reference.
Note that in the absence of a timeZone specified for this second formatter, it assumes that while the ISO 8601 date was in GMT, that you want to see the date in your local timezone. For example, (1900-01-01T00:00:00 GMT was Dec 31, 1899 at 4pm in California). If you want to see the date string of the original ISO 8601 object, not corrected for timezones, you'd just set the timeZone of this second formatter to be GMT as well, e.g.
formatter2.timeZone = TimeZone(secondsFromGMT: 0)
As others have pointed out, you want to avoid unnecessarily re-instantiating DateFormatter objects. So you might put these formatters in properties that are instantiated only once, or use an extension:
extension DateFormatter {
static let customInputFormatter: ISO8601DateFormatter = {
let formatter = ISO8601DateFormatter()
formatter.formatOptions.remove(.withTimeZone)
return formatter
}()
static let customOutputFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "dd-MM-yyyy"
formatter.timeZone = TimeZone(secondsFromGMT: 0) // if you want date in your local timezone, remove this line
return formatter
}()
}
And then:
let input = "1900-01-01T00:00:00"
let date = DateFormatter.customInputFormatter.date(from: input)!
let output = DateFormatter.customOutputFormatter.string(from: date)
print(output)
This is how I do custom date formatters:
extension DateFormatter {
static let inDateFormatter: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
return dateFormatter
}()
static let outDateFormatter: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd-mm-yyyy"
return dateFormatter
}()
}
And then use it like:
if let date = DateFormatter.inDateFormatter.date(from: "1900-01-01T00:00:00") {
let newDateString = DateFormatter.outDateFormatter.string(from: date);
print(newDateString) //prints 01-00-1900
}
This avoids any potential performance issues and is clear at the point of use, while still being concise.
Use this extension I created, where you can pass the format as a parameter.
extension String
{
func toDate( dateFormat format : String) -> Date
{
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = format
if let date = dateFormatter.date(from: self)
{
return date
}
print("Invalid arguments ! Returning Current Date . ")
return Date()
}
}
"1900-01-01T00:00:00".toDate(dateFormat: "yyyy-MM-dd'T'HH:mm:ss") //Plyground call test
I have a json that contains date field:
"created_at":"2016-03-06T16:39:29.786Z"
in my app I'm doing like this:
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-ddThh:mm:ss.SSSZ"
let created_at = json["created_at"].string
let crd = dateFormatter.dateFromString(created_at!)
print(crd) //prints nil
Why am I getting nil there?
You need to quote literal text and you are using the wrong format specifier for the hour.
The T must be quoted.
hh is for 12-hour format but you have 24-hour format which is HH.
So you want:
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"