how to convert a String to a Date without changing the Format - swift

I'm using Xcode 11.4.1
In my Project I got a String with some data which I need to split up and save the Information in some variables.
now I face a problem if I try this
let dateString = "12-04-2020"
let dateFormatIn = DateFormatter()
dateFormatIn.dateFormat = "dd-MM-yyyy"
let saveDate: Date = dateFormatIn.date(from: dateString)!
print("The date is: \(saveDate)")
the result which I expected is "The date is: 12-04-2019" but what I got is "The date is: 2020-04-11 15:00:00 +0000"
what do I miss, what is this printed Date? it's not the current date ans also not the String!
I need the Date in the same format as I got it in the String.

A Date is a point in time, it doesn't have a format nor a time zone.
print shows the description – a string representation – of the date in the UTC time zone.
Your time zone is obviously UTC +0900, 2020-04-12 00:00:00 +0900 and 2020-04-11 15:00:00 +0000 is the same point in time.
If you want to create the date string independent of the time zone add the line
dateFormatIn.timeZone = TimeZone(secondsFromGMT: 0)

let saveDate: Date = dateFormatIn.date(from: dateString)!
The ": Date" looks like a data type declaration. You're saying, "create a variable called saveDate of type Date, and initialize it from the output of dateFormatIn.date(from: dateString)".
So you're not printing the formatted output. You're converting the formatted output to a new Date object, and then printing that.
Try:
let saveDate = dateFormatIn.date(from: dateString)!
This should save whatever dateFormatIn.date(from: dateString) returns in saveDate.

Related

How to convert a date to a specific timezone when user is in a different timezone?

I have a problem in handling dates in Swift in different timezones. I'm getting an Italian date from my server and I'm trying to convert it into a Date through the following function:
func stringToDateTime(dateString: String) -> Date? {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
formatter.locale = Locale(identifier: "it_IT")
formatter.timeZone = TimeZone(identifier: "Europe/Rome")
return formatter.date(from: dateString)
}
However if the date is "2022-11-22 10:00:00", for example, and I'm in London or New York the function returns:
▿ 2022-11-22 09:00:00 +0000
- timeIntervalSinceReferenceDate : 690800400.0
Why is that so? I specified the timezone in the formatter so it should return me 10 o'clock. What am I doing wrong?
The date and time seems correct to me.
The date and time which was passed "2022-11-22 10:00:00" is in Italian time, which is GMT+1, or with other words, 1 hour ahead of UTC.
The date and time which was printed to the console is in UTC, or GMT+0, and is indicated by '+0000'.
2022-11-22 09:00:00 +0000
If we were to put this date into a converter for UTC to Italian time, we would get the initial value - "2022-11-22 10:00:00".
When you print a Date in the console directly, it automatically uses UTC as the time zone. If you'd like to print a string representation of your Date object to the console in your locale, use this method:
Generates a locale-aware string representation of a date using the default date format style.
func formatted() -> String
from Apple documentation: https://developer.apple.com/documentation/swift/sequence/formatted(_:)

How to parse date in "2022-03-04T10:30:00-08:00" format correctly in swift?

I have date coming from API shown below. These dates are for different countries.
dateTime = "2022-03-04T14:30:00-08:00"
I need to convert this use it both as Date and as String. But I do not know if date and time I am converting are correct. I am using following code:
To Convert String from API to Date:
extension String {
var CommonDateFormat: Date? {
get {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
return dateFormatter.date(from: self)
}
}
}
To Convert Date to String:
extension Date {
func getDateAccoringTo(format: DateFormat ) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = format.rawValue
dateFormatter.timeZone = .current
dateFormatter.timeZone = TimeZone.init(identifier: "UTC")
return dateFormatter.string(from: self)
}
}
enum DateFormat: String {
case ddmmyyyy = "dd/MM/yyyy"
case mmddyyyy = "MM/dd/yyyy"
case mmmd_yyyy = "MMM d, yyyy"
case llll_yyyy = "LLLL ,yyyy"
case TIME = "HH:mm:ss"
case day = "dd"
}
When I try to get day from date it always gives next day date. For example if date = "2022-03-04T14:30:00-08:00" then if I try to get day using code below
date?.getDateAccoringTo(format: .day)
This returns 5 not 4
date?.getDateAccoringTo(format: .TIME)
This returns time 00:00:00
Am I missing something important which is leading to these values?
Also, if I am missing something in my question kindly let me know so that I can improve it.
The given string
let dateTime = "2022-03-04T14:30:00-08:00"`
is a standard ISO8601 formatted date string. It can be converted to Date with
let formatter = ISO8601DateFormatter()
let date = formatter.date(from: dateTime)!
At this specific point in time it is
14:30 on Friday, March 4 in Denver, CO, USA
22:30 on Friday, March 4 in London, UK
06:30 on Saturday, March 5 in Tokyo, Japan
Now let's see how Xcode displays dates.
print displays Date instances always in UTC indicated by +0000 which is the London time zone unless you print(date.description(with: .current), this displays the date in the local time zone.
In a Xcode Playground the result area displays Date instances in the local time zone except in print lines.
Last point to consider is that DateFormatter converts Date to String in the local time zone if no time zone is specified.
Keeping this behavior in mind you get the next day if you convert the date to string with DateFormatter but without specifying the time zone and your local time zone is greater than or equal to +01:30.
And you get the time 00:00 if you convert the date to string with DateFormatter but without specifying the time zone and your local time zone is exactly +01:30 which is a pretty unusual time zone by the way.

Converting string to date with a different timezone gives the wrong date

So, this:
import Foundation
let df = DateFormatter()
df.dateFormat = "yyyy-MM-dd"
df.timeZone = TimeZone(identifier: "Australia/Currie")!
let todayString = (df.string(from: Date()))
print(todayString)
let today = df.date(from: todayString)!
print(today)
Prints:
2021-02-19
2021-02-18 13:00:00 +0000
For reference, today’s date based on my current timezone is the 18th. So it correctly prints the 19th when using an Australian timezone that moves the time ahead.
What I don't understand is why today is a day behind todayString, since it's constructed from the same DateFormatter. Ideally, they should both print the 19th, right?
Basically, what I'm trying to do is have both a date (from a different timezone) and its string representation.
As mentioned in the comments print displays Date instances always in UTC(+0000). For example check
let date = Date()
print(date)
To print the date in your current locale (and time zone) write
print(today.description(with: .current))

Comparing dates in Swift ignoring current timezone

In Swift I can find the difference between two dates using Calendar.current.dateComponents
The problem is that this gives the difference relative to my current time zone.
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm XXX"
let from = zoneFormatter.date(from: "2018-03-25 00:00 +00:00")!
let to = zoneFormatter.date(from: "2018-03-26 00:00 +00:00")!
let components = Calendar.current.dateComponents([.month, .day, .hour, .minute], from: from, to: to)
// components is 1 day, 1 hour, because I am in UK and Daylight Savings started on 25 March.
How can I retrieve the absolute difference between the two instants specified in the same format which dateComponents returns?
Incorrect Date Format String
Looks like your using the incorrect format for your dates. The date format for the specified date of "2018-03-25 00:00 +00:00" is actually "yyyy-MM-dd HH:mm ZZZZZ". Give that format a try and it should fix the problem.
Why does the incorrect format not work for comparison between time zones?
This is because it was the timeZone component of your format string that is incorrect. This means the timeZone will not be accounted for in the comparison.
The timezone of Calendar.current can be changed by setting the system default timezone as follows:
NSTimeZone.default = NSTimeZone(abbreviation: "UTC")! as TimeZone

Swift: Get correct time zone from Date Picker?

I am trying to get the correct time zone from the date picker in swift using time formatter, it's not working. I'm getting UTC, not EST.
1) If I print dateFormatter.stringFromDate(datePicker) I get EST, but
2) I don't need a string, I need an NSDate in EST so
3) I can use it to get the timeIntervalSinceDate(NSDate) in EST.
My trick of trying to take it from string back to NSDate as seen below didn't work. It's still in UTC and the time interval since date is not right.
dateFormatter.locale = NSLocale.currentLocale()
dateFormatter.timeZone = NSTimeZone.localTimeZone()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let date: NSDate = dateFormatter.dateFromString(dateFormatter.stringFromDate(datePicker))!
print(date)
print(date.timeIntervalSinceDate(datePicker))
The above answer is totally wrong. Date picker report the date in system locale anytime, so, if the datePicker shows an 08:00 Time and you are GMT+2, the property date of the picker will be 06:00.
So for have the absolute value of the datePicker you have to pass to him the UTC time zone in view did load with:
datePicker.timeZone = TimeZone.init(identifier: "UTC")
Now, the date property of the picker will be the expected and choosen one.
You cannot "get a time zone" from a date picker. You can just get a date. The date will be independent on the current time zone of the device.
Perhaps you think you have a different date, but actually, there is no such thing as a "UTC date" or "EST date". Instead, there is only one date, and you use date formatters to display them for various time zones.
Note that there is quite a bit of redundancy in your code. The default locale and time zone of a date formatter are already the same values that you set. Also, when you have a method that returns a NSDate you do not have annotate the constant with : NSDate, making your code more verbose and cluttered.
Note that if you print a date the console will always show UTC. e.g.
let date = NSDate() // Nov 10, 9:44 PM
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "YYYY-MM-dd hh:mm a"
let dateString = dateFormatter.stringFromDate(date) // "2015-11-10 09:44 PM"
print(date) // "2015-11-10 20:44:54 +0000\n"
To set the TimeZone of a DatePicker to UTC use:
datePicker.timeZone = TimeZone.init(identifier: "UTC")
Notice the camelcase notation of "timeZone".
Unfortunately I don't have enough credit to comment on the last post, which has it almost right, so I had to create a new answer.
A little trivia: TimeZone has been around since iOS 2.0 as is stated here:
https://developer.apple.com/documentation/uikit/uidatepicker/1615976-timezone
Those who are trying to find a solution and are not able to wrap their head around the exact issue. Here is what something I tried:
Use time.addTimeInterval(-14400) function, where -14400 is the 4 hours difference. So if you want UTC to EST do this.
Something like this:-
var time = Date() // assuming you have this in UTC
time.addTimeInterval(-14400)
You can also use addingTimeInterval function which returns you the new date.
I know this is a little wonky cause we're manually doing this, but hope it helps someone.