Swift unable to parse string date to Date object - swift

I have the following date format:
2016-08-26T05:16:50.200Z
And I am trying to parse similar date formatted strings into Date objects in Swift 3.0.
Here is my effort:
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-mm-dd EEEEE HH:mm:ss Z"
formatter.locale = Locale(identifier: "us")
var date = formatter.date(from: date_str)!
Where date_str is of the format mentioned above.
Unfortunately, swift don't recognize the format and returns nil.
Note: I don't want to change the string to match the formatter, but to adapt the formatter to the format of the string. String is of external source so I don't have the ability to change the string's format, but to stick with it and create a formatter that will recognize the string's date pattern.
Any ideas on where my format is wrong?

You are making mistake here, Here T is not for Week detail, The T is just a marker for where the time part begins.
A single point in time can be represented by concatenating a complete date expression, the letter T as a delimiter, and a valid time expression. For example "2016-10-05T14:30".
So now just change your dateFomat to yyyy-MM-dd'T'HH:mm:ss.SSSZ and you will get correct date you want.
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
formatter.locale = Locale(identifier: "us")
var date = formatter.date(from: date_str)!
print(date)
Output:

Related

How to convert "Hours:Minutes:Seconds AM/PM"(UTC timezone) to the user's time zone in the format of "Hours:Minutes AM/PM" in Swift?

The input string will always be in the Hours:Minutes:Seconds AM/PM format, and it will always be in the UTC Timezone (The string represents the sunrise time where the user is, but only in UTC). A few examples are:
10:3:30 AM,
2:40:01 PM,
12:0:04 AM
I want to convert the time to the user's timezone and then get rid of the seconds component, so that it is just "Hours:Minutes AM/PM"
So far, I think I can use
var localTimeZoneAbbreviation: String { return TimeZone.current.abbreviation() ?? "" }
to get the user's current timezone, but I still don't know how to convert the string to that timezone. Any suggestions?
Use DateFormatter. One instance to convert from your UTC time to a Date and another to convert from that Date to a localized String.
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX") // set locale before format; good to use this locale for fixed date formats
formatter.dateFormat = "h:m:ss a"
formatter.timeZone = TimeZone(abbreviation: "UTC")
let date = formatter.date(from: "10:3:30 AM")! // whichever input string you have
let localFormatter = DateFormatter() // time zone and locale default to system's
localFormatter.dateFormat = "hh:mm a" // if you don't want a zero padding single digits then use "h:m a"
let string = localFormatter.string(from: date)
Note the day/month/year will implicitly default to the default for the system, (I'm seeing January 1 2000) but you can presumably ignore that.

DateFormatter giving me incorrect result while I am converting String into Date in UK region and Timezone is Muscat

I want "yyyy-MM-dd HH:mm:ss", with time in 24 hour format, but as i m having 12 hrs date format setting in my phone and Timezone is set to the Muscat ,the date which I am getting is always 12 hrs format, while i m checking with UK region. I am able to change Date() into string in 24 hrs format but while I am changing 24 hrs string into 24 hrs Date , It always give me 12 hrs Date format
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
let dateToString = dateFormatter.string(from: Date()) //2020-04-06 15:47:16
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
let dateFromString = dateFormatter.date(from: dateToString)
print(dateFromString) // 2020-04-06 1:47:25 pm +0000
A Date object just represents a point in time. The “should I show it in 12 hour clock or 24 hour clock” is not something that Date objects know about. This is a feature of strings generated by (or consumed by) a DateFormatter.
So, a few thoughts:
A date formatter’s dateFormat (and its locale) dictates what a string will look like when you call string(from:). (It will also dictate how to interpret a string and create a Date object when you call date(from:), but that’s not relevant here.)
So, if you’re looking for a string representation of a date using a 24 hour clock, look at the string generated by the date formatter’s string(from:) method. This is the dateToString string in your example.
But, if you subsequently generate a Date object from the formatter’s date(from:) method, that resulting Date will not capture whether to use 12 vs 24 hour clock. If you print this Date object, it won’t reflect your 12/24 hour clock preference.
Bottom line, only concern yourself with am/pm vs 24-hour clock when looking at String objects generated by (or passed to) the DateFormatter. Don’t worry about the format of the output when you print a Date object, as that’s for debugging purposes only and won’t capture this am/pm vs 24-hour clock dimension.
You said:
Final statement is giving me “2020-04-09 4:23:27 am +0000” format.
If you’re seeing the +0000, that suggests that you are printing the Date object, itself. The dateFormat and locale of a DateFormatter only controls the format of the string generated by string(from:) (and how strings are parsed).
So, print the string generated by DateFormatter, not Date objects. The print of a Date object will always be in this predefined format. Within the app, if you need the output in a given format, use the String generated by DateFormatter, not Date objects.
Consider a more obvious example of the issue where the DateFormatter is used to create a string in a very different format:
let now = Date()
print(now) // 2020-04-07 11:54:58 +0000
let formatter = DateFormatter()
formatter.dateStyle = .long
formatter.timeStyle = .long
let string = formatter.string(from: Date())
print(string) // April 7, 2020 at 4:54:58 AM PDT
if let date = formatter.date(from: string) {
print(date) // 2020-04-07 11:54:58 +0000
}
So, even though that formatter successfully converted a Date to a String, and back, that final print statement uses the same fixed format that the first print statement did, because I’m just printing a Date object. I’m not concerned that the that last print statement didn’t honor the configuration of my DateFormatter. I wouldn’t expect it to. When I print a Date, it’s always in that fixed, predefined format. I only worry about the format of the strings generated by the DateFormatter (the second print statement).
As an aside, there are secondary questions about your "yyyy-MM-dd HH:mm:ss" format. What timezone does this represent? Your local timezone? Your server’s timezone? GMT/UTC/Zulu? We often use ISO8601/RFC3339 date strings (like 2020-04-07T11:54:58Z) to remove this ambiguity. You should get your arms around your original question first, but when you have that behind you, you’ll want to take a hard look at why you’re storing it in this format, and how you want to deal with timezones correctly. But first things first.

How to add characters into dateFormatter

I followed this answer, but it doesn't work for me.
I want to format my time as:
"2017-09-11T11:45:00-04:00"
I'm doing:
let xFormatter = DateFormatter()
xFormatter.dateFormat = "yyyy-MM-ddTHH:mm:ss-04:00"
print(xFormatter.string(from: date))
I need a T between the date and time. however if I add that, my format turns into something like:
2017-09-11
(The -4:00 at the end is a timeoffset which I hardcode...)
Add single quotes
xFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss-04:00"
From the documentation:
... This includes the need to enclose ASCII letters in single quotes if they are intended to represent literal text.
Source: Unicode.org: Date Format Patterns
Edit:
Be aware that the time zone is just an amendment to the string, it's not considered by the date formatter.
To consider the time zone you have to set the timeZone of the formatter
xFormatter.timeZone = TimeZone(secondsFromGMT: -14400)
In iOS 10.0+ and macOS 10.12+ there is a more convenient way to create an ISO8601 string
let isoFormatter = ISO8601DateFormatter()
isoFormatter.timeZone = TimeZone(secondsFromGMT: -14400)
isoFormatter.formatOptions = .withInternetDateTime
print(isoFormatter.string(from: Date()))

How do I make more than one date format in a single view in Swift?

I am trying to save data to a database and am using a date that shows seconds as the key but I want to show a smaller date in the value that is going to be displayed. The problem is to use the date formatter you need to set it like this and I cant figure out how to set another one without overwriting the current format.
DateFormatter.dateFormat = "MM-dd-yy hh:mm:ss a"
This is how to have multiple DateFormatter in a single View.
Formatter1
let formatter = DateFormatter()
formatter.dateFormat = "QQQQ\ryyyy" //Shows Financial Quarter for Date
let formattedDate = formatter.string(from: date)
Formatter2
let formatter1 = DateFormatter()
formatter1.dateFormat = "EEEE, MMM d, yyyy" //Wednesday, Mar 29, 2017
let formattedDate1 = formatter1.string(from: date)
Refer to this site to know more about DateFormatter. Hope this helps. Happy Coding !

NSDate set timezone in swift

how can i return a NSDate in a predefined time zone from a string
let responseString = "2015-8-17 GMT+05:30"
var dFormatter = NSDateFormatter()
dFormatter.dateFormat = "yyyy-M-dd ZZZZ"
var serverTime = dFormatter.dateFromString(responseString)
println("NSDate : \(serverTime!)")
the above code returns the time as
2015-08-16 18:30:00 +0000
The date format has to be assigned to the dateFormat property of the date formatter instead.
let date = NSDate.date()
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let str = dateFormatter.stringFromDate(date)
println(str)
This prints the date using the default time zone on the device. Only if you want the output according to a different time zone then you would add for example
Swift 3.*
dateFormatter.timeZone = NSTimeZone(name: "UTC")
Swift 4.*
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
also refer link http://www.brianjcoleman.com/tutorial-nsdate-in-swift/
how can i return a NSDate in a predefined time zone?
You can't.
An instance of NSDate does not carry any information about timezone or calendar. It just simply identifies one point in universal time.
You can interpret this NSDate object in whatever calendar you want. Swift's string interpolation (the last line of your example code) uses an NSDateFormatter that uses UTC (that's the "+0000" in the output).
If you want the NSDate's value as a string in the current user's calendar you have to explicitly set up a date formatter for that.
Swift 4.0
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
If you always have the same time zone for the input string, you can create two date formatters to output the local time zone (or a specified one):
let timeFormatterGet = DateFormatter()
timeFormatterGet.dateFormat = "h:mm a"
timeFormatterGet.timeZone = TimeZone(abbreviation: "PST")
let timeFormatterPrint = DateFormatter()
timeFormatterPrint.dateFormat = "h:mm a"
// timeFormatterPrint.timeZone = TimeZone(abbreviation: "EST") // if you want to specify timezone for output, otherwise leave this line blank and it will default to devices timezone
if let date = timeFormatterGet.date(from: "3:30 PM") {
print(timeFormatterPrint.string(from: date)). // "6:30 PM" if device in EST
} else {
print("There was an error decoding the string")
}
The number 1 means 1 regardless of language. Yet in English it's spelled as one, in Spanish it's una, in Arabic it wahid, etc.
Similarly 123982373 seconds pass 1970 is going to reflect differently in different timezones or calendar formats, but's all still 123982373 seconds passed 1970
The difference between 3 seconds and 7 seconds is 4 seconds. That doesn't require a calendar. Neither you need a calendar/timezone to know the difference in time between these two Epoch times 1585420200 and 1584729000
Dates are just a timeInterval from January 1, 1970 (midnight UTC/GMT). Dates also happen to have a string representation.
Repeating Nikolia's answer, Swift's default string interpolation (2015-08-16 18:30:00 +0000) uses a DateFormatter that uses UTC (that's the "+0000" in the output).
Calendars with the use of timezones give us a contextual representation that is just easier to understand than trying to calculate the difference between two gigantic numbers.
Meaning a single date (think of a single timeInterval since 1970) will have a different string interpretations per calendar. On top of that a calendar will itself vary based on time zones
I highly recommend that you go and play around with this Epoch converter site and see how selecting a different timezone will cause the string representations for the same moment/date/timeInterval to change
I also recommend to see this answer. Mainly this part:
Timezone is just an amendment to the timestamp string, it's not considered by the date formatter.
To consider the time zone you have to set the timeZone of the formatter
dateFormatter.timeZone = TimeZone(secondsFromGMT: -14400)