Why my date parser doesn't work in Swift? - ios

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"

Related

Formatting JSON date to Swift date doesn't work

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

Dateformat of 2017-12-16T07:28:59.629Z

What date format I need to process this string? 2017-12-16T07:28:59.629Z
Tried yyyy-MM-dd'T'HH:mm:ssZZZZZ and Tried yyyy-MM-dd'T'HH:mm:sssZZZZZ
Anyway how many s and Z needs end of the format?
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:sssZZZZZ"
date = dateFormatter.date(from: value as! String)
use the dateformat as
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
as the Date Format Patterns suggests that "S" is the format specifier for fractions of seconds.

cast "1900-01-01T00:00:00" string value to date

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

What should be the format of a string to convert into NSDate?

I'm getting following two types of strings from server:
2016-07-28T12:25:31.922247
2016-07-28T13:39:13
I want to convert them into NSDate. I'm using following snippet to convert but it's failing:
let dateFormatter = NSDateFormatter()
dateFormatter.timeZone = NSTimeZone(name: "UTC")
dateFormatter.dateFormat = "yyyy-MM-ddTHH:mm:ss"
I'm not getting the desired output.
If you doesn't care the fraction of second then you can remove it like this.
var strDate = "2016-07-28T12:25:31.922247"
if strDate.rangeOfString(".") != nil{
let arr = strDate.characters.split{$0 == " "}.map(String.init)
strDate = arr[0]
}
//Now you can convert this string to date using same date format
let formatter= NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
let date = formatter.dateFromString(strDate)
You can get the exact format from this Link
For the second string use this
yyyy-MM-dd'T'HH:mm:ss
You need to quote the "T" (or any alpha characters that should be present in literal form), try:
let dateFormatter = NSDateFormatter()
dateFormatter.timeZone = NSTimeZone(name: "UTC")
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
Note that this will only parse your second string. To parse your first string you'll need to use:
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.S"
if you care about the fractional seconds. Since NSDateFormatter is a literal parser it doesn't allow you to easily parse either format, if you have to parse both you'll just need to pass it to one, if that fails pass to the other.
Your date format works in 2016-07-28T13:39:13 but add 'T'
Example: yyyy-MM-dd'T'HH:mm:ss.
But for the 2016-07-28T12:25:31.922247 you need clarifies that this means 922247
the truth had never seen anything like it, but I would try with yyyy-MM-ddTHH:mm:ssZ

How to convert String to NSDate?

I have string that I received whenever there is new remote notifications.I'm using parse for my Backend. And String that I retrieved come from "createdAt" column.
I've tried below code:
var ca = "2015-07-03T03:16:17.220Z"
var dateFormater : NSDateFormatter = NSDateFormatter()
dateFormater.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"
let date = dateFormater.dateFromString(ca)
println(date)
But the println is giving me nil, I think there is something wrong with my date format. How can I fix this?
You are missing the milliseconds. Thus:
dateFormater.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
Note, when converting from the date string to a NSDate, you shouldn't quote the Z. If you quote the Z, it will match the literal Z character, but won't correctly reflect that this date string is actually Zulu/GMT/UTC.
If you want to create formatter that also goes the other way, converting NSDate objects to strings, in that case you should quote the Z, but in that case you must remember to explicitly set the timezone:
dateFormater.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
dateFormater.timeZone = NSTimeZone(forSecondsFromGMT: 0)
By the way, don't forget to set the locale as per Apple Technical Q&A 1480.
dateFormater.locale = NSLocale(localeIdentifier: "en_US_POSIX")

Resources