Get the format of date | Swift | iOS - ios

As per the requirement, my API might return date in either "2018-01-01" or "01-01-2018" or "2018-01-01T00:00:00" format
How can I check the format of the date?
eg: my code for API response "2018-01-01" should return me "yyyy-MM-dd" etc..
I can do this by checking length of my characters and by assigning date format accordingly..but i feel this is not the right approach.

You just need to define your date formats and try each of them. One of them will succeed. Just make sure all your date strings are from the same timezone (I suppose they are all UTC) and don't forget to set the date formatter locale to "en_US_POSIX" when working with fixed format dates:
let dateStrings = ["2018-01-01", "01-01-2018", "2018-01-01T00:00:00"]
let dateFormats = ["yyyy-MM-dd'T'HH:mm:ss", "yyyy-MM-dd", "MM-dd-yyyy"]
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
var dates: [Date] = []
for dateString in dateStrings {
for dateFormat in dateFormats {
formatter.dateFormat = dateFormat
if let date = formatter.date(from: dateString) {
dates.append(date)
print("dateFormat:", dateFormat)
print("date:", date)
break
}
}
}
This will print
dateFormat: yyyy-MM-dd
date: 2018-01-01 00:00:00 +0000
dateFormat: MM-dd-yyyy
date: 2018-01-01 00:00:00 +0000
dateFormat: yyyy-MM-dd'T'HH:mm:ss
date: 2018-01-01 00:00:00 +0000

It's risky to have ambiguous date formats in an API. But if you are stuck with this you could make multiple DateFormatters and configure each for a specific format (by setting their dateFormat accordingly) and attempt to convert the string using each of these in turn. Once you have a success, you know which format you got (it's dateFormat).

Related

Swift: Date parsing on daylight saving time

I have received date-time as String from server. I am unable to parse Date if date time is exact time of daylight saving time happen. How to handle when date-time string is "2022-03-13T02:00:00.000000"
Output:
2022-03-13 05:00:00 +0000
2022-03-13 06:59:00 +0000
failed
2022-03-13 07:00:00 +0000
2022-03-13 08:00:00 +0000
Code:
extension String {
func date(using format: String) {
let df = DateFormatter()
df.dateFormat = format
df.timeZone = .current
if let date = df.date(from: self) {
print(date)
}
else {
print("failed")
}
}
}
"2022-03-13T00:00:00.000000".date(using: "yyyy-MM-dd'T'HH:mm:ss.SSSSSS")
"2022-03-13T01:59:00.000000".date(using: "yyyy-MM-dd'T'HH:mm:ss.SSSSSS")
"2022-03-13T02:00:00.000000".date(using: "yyyy-MM-dd'T'HH:mm:ss.SSSSSS")
"2022-03-13T03:00:00.000000".date(using: "yyyy-MM-dd'T'HH:mm:ss.SSSSSS")
"2022-03-13T04:00:00.000000".date(using: "yyyy-MM-dd'T'HH:mm:ss.SSSSSS")
You just need to set your date formatter's calendar property. This will also avoid using the user device's calendar which might result in parsing the wrong year. Don't forget to always set your date formatter's locale to "en_US_POSIX" when parsing a fixed date format:
extension String {
func date(using format: String) -> Date? {
let df = DateFormatter()
df.calendar = .init(identifier: .iso8601)
df.locale = .init(identifier: "en_US_POSIX")
df.timeZone = .current
df.dateFormat = format
df.date(from: self)
}
}
Note also that this approach will create a new date formatter every time you call this method. You should avoid that as well creating a static formatter. I would also make sure if the date string is using the current timezone. Usually it is UTC timezone.
Adopt the ISO8601DateFormatter To convert those strings into dates, then when you need to display them into your app use a date formatter set to the desired time zone.
In this way you won’t have any trouble with daylight savings conversions.
Of course when you need to re-encode a date into a String For transmitting it use again the ISO8601DateFormatter In order to keep the same format used for receiving them.

I can't convert iso8601 to string swift

I have a string coming from API and its format will be like this
"2021-03-01T15:00:00+07:00"
so i try to convert this string to date using this code
// string to date
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
let date = dateFormatter.date(from: isoDate)!
print("date from date Formatter = \(date)")
// convert date back to string
dateFormatter.dateFormat = "EEEE HH:mm"
let dateString = dateFormatter.string(from: date)
print("date string \(dateString)")
return dateString
The result that I expect is -> "2021-03-01 08:00:00 +0000", "Monday 15:00"
When I try this on playground the result is what I want, but when I try this on my project the result is
-> "1478-03-01 08:00:00 +0000", "Sunday 14:42"
How can I change the result to the same as i expect? Thanks
It looks like you are using a different calendar than you expect in your project (buddhist maybe?) and I guess this is because you haven't set one explicitly so it's the one set in System Preferences.
So if you for some reason do not want to use the users current calendar (and locale and time zone) you need to set those properties on your date formatter instance
//Gregorian calendar
dateFormatter.calendar = Calendar.init(identifier: .gregorian)
//UTC time zone
dateFormatter.timeZone = TimeZone(identifier: "UTC")
//English locale
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
This will give you the expected output.
Note that the playground is a bit inconsequent in what it uses and it seems to be a mix of what we have set in our System preferences and hardcoded values.

Swift date format returning wrong date

I need to convert my date to string and then string to date. date is "2020-10-17 1:22:01 PM +0000"
Here is my date to string conversion code:
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXXXX"
let string = formatter.string(from: "2020-10-17 1:22:01 PM +0000")
let createdAT = string
its returning "2020-10-17 18:51:30+05:30"
Here is my string to date conversion code:
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd' 'HH:mm:ssZ"
let date = dateFormatter.date(from:date)!
its returning "2020-10-17 1:21:30 PM +0000 - timeIntervalSinceReferenceDate : 624633690.0"
its returning the wrong date after i convert string to date. i need "2020-10-17 18:51:30+05:30" this time to be return when i convert string to date.....
The code in your question is muddled up. You try to convert a string into a string in the first example and something unspecified into a Date in the second example.
Here's how to convert a Date into a String:
import Foundation
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXXXX"
let string: String = formatter.string(from: Date())
print(string) // prints for example 2020-10-18T10:54:07+01:00
Here's how to convert a string into a date
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd' 'HH:mm:ssZ"
let date: Date = formatter.date(from: "2020-10-18 10:59:56+0100")! // In real life, handle the optional properly
print(date) // prints 2020-10-18 09:59:56 +0000
When you print a Date directly, it automatically uses UTC as the time zone. This is why it changed it in the code above.
In the examples, I explicitly specified the type of string and date to show what type they are. Type inference means you can omit these in normal code.
As a general rule when handling dates:
always use Date in your code. Date is a type that stores the number of seconds since Jan 1st 1970 UTC.
Only convert dates to strings when displaying them to the user or communicating with an external system.
When calculating periods etc, always use a Calendar to get things like date components and intervals in units other than seconds. You might think to get "the same time tomorrow" you could just add 24 * 60 * 60 to a Date but in many countries, like mine, that will work on only 363 days in the year. Calendar will correctly handle things like daylight saving and leap years.

dateFromString() returning wrong date swift 3.0

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
}

GMT date string getting converted to UTC Date

**
GET GMT DATE STRING
**
func getGMTString(dateAsDate:NSDate) -> String
{
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss zzz"//this your string date format
// dateFormatter.locale = NSLocale.currentLocale()
// dateFormatter.timeZone = NSTimeZone(name: "GMT")
let date = dateFormatter.stringFromDate(dateAsDate)
return date
}
OUTPUT
startDate---2016-06-29 00:00:00 GMT+5:30
endDate----2016-06-30 03:57:39 GMT+5:30
NOW TRYING to get GMT Date object from output string
func getGMTDate(string:String) -> NSDate {
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss zzz"//this your string date format
// dateFormatter.timeZone = NSTimeZone(abbreviation: "GMT")!
// dateFormatter.locale = NSLocale.currentLocale()
let date = dateFormatter.dateFromString(string)
return date!
}
PROBLEM: OUTPUT DATE OBJECT MESS
startDateOBJECT---2016-06-28 18:30:00 +0000 endDateOBJECT----2016-06-30 17:30:00 +0000
Unable to figure what is going wrong
I don't understand your step 3. I looks like you're using NSLog or a Swift print to display the resulting date. That is ALWAYS done in UTC.
If you want to view your date in a different format, or with your local time zone, you need a second date formatter to convert the NSDate to an output date string.
Here's the flow:
input date string -> input date formatter -> NSDate
NSDate -> output date formatter -> display date in local time zone

Resources