How to convert date/time from GMT to local timezone - swift

I'm getting a date time string from a JSON response that looks like this:
2019-07-18 13:39:05
This time is GMT. How can I convert this to locale time zone, in my case Eastern with day light savings.
func convertDateFormat(date:String) -> String {
let dateFormatterGet = DateFormatter()
dateFormatterGet.dateFormat = "yyyy-MM-dd HH:mm:ss"
let dateFormatterPrint = DateFormatter()
dateFormatterPrint.dateStyle = .long
dateFormatterPrint.timeStyle = .short
let date = dateFormatterGet.date(from: date)
return dateFormatterPrint.string(from: date!)
}
In the code above the result should be July 18, 2019 at 9:39 AM
Thanks

The input is a fixed-format date string in GMT, therefore dateFormatterGet must have
the locale set to "en_US_POSIX" (otherwise it can default to the user's locale settings, compare What is the best way to deal with the NSDateFormatter locale "feechur"?), and
the time zone set to GMT (otherwise it defaults to the user's time zone):
Example:
let dateFormatterGet = DateFormatter()
dateFormatterGet.locale = Locale(identifier: "en_US_POSIX")
dateFormatterGet.timeZone = TimeZone(secondsFromGMT: 0)
dateFormatterGet.dateFormat = "yyyy-MM-dd HH:mm:ss"
Everything else should be OK: you don't set a time zone for dateFormatterPrint so that the user's time zone is used.

Related

Swift Convert UTC string to UTC Interval

I am getting UTC date in string format from server which is "Sep 8 2022 10:14AM"
Now I want to convert it into same time interval like this 1662632040.
Below Is my code I am not getting why I am getting different time interval
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM dd yyyy HH:mma"
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
let dt = dateFormatter.date(from: "Sep 8 2022 10:14AM")!
let interval = dt.timeIntervalSince1970
interval is giving result 1662596040 but correct one is 1662632040.
I am not getting what is missing

How can i Convert (2020-02-21 06:07:21 +0000) to "21 Feb 2021 12:00 AM"?

I am using device time to get date components. this works fine for 12 hours formate but if user changes device time to 24 hours it shows wrong calculations. used the following method to convert but it always return nil.
let dateAsString = "\(Date())"
let df = DateFormatter()
df.dateFormat = "yyyy-mm-dd HH:mm:ss zzz"
let date = df.date(from: dateAsString)
df.dateFormat = "d MMM yyyy h:mm a"
let time12 = df.string(from: date!)
print(time12)
So, the core problem you're having is the fact that yyyy-mm-dd is using mm which is minutes and not using MM which is months.
So, if instead, you tried something like...
let dateAsString = "\(Date())"
let df = DateFormatter()
df.dateFormat = "yyyy-MM-dd HH:mm:ss zzz"
let date = df.date(from: dateAsString)
df.dateFormat = "d MMM yyyy h:mm a"
let time12 = df.string(from: date!)
it would result in
21 Feb 2020 6:00 PM
Now, the problem is, you could simply do
let df = DateFormatter()
df.dateFormat = "d MMM yyyy h:mm a"
df.string(from: Date())
and get the same result.
Remember, Date does not, in of itself, have a concept of "format", beyond what its "debug" output provides, so you can't change a Date's format, instead, you use a formatter to "represent" the value of the Date in some human readable form.
I have just tried below it works fine on both cases. with AM or PM or 24Format and if you remove a in formatter.dateFormat = "dd MMM yyyy HH:mm a" gives you 24 Format. Even I am using this in my code.
let someDate = Date()
let formatter = DateFormatter()
formatter.dateFormat = "dd MMM yyyy HH:mm a"
let someDateTime = formatter.string(from: someDate)
print(someDateTime)
Print:
21 Feb 2020 09:35 AM
Try this:
let date : "2021-01-20T21:40:59.416Z"
func setDate(date: String) -> String {
var interval: Double = 0
let convertedDate = date.components(separatedBy: ":")
for (index, part) in convertedDate.reversed().enumerated() {
interval += (Double(part) ?? 0) * pow(Double(60), Double(index))
}
let date = Date(timeIntervalSinceNow: interval)
let formatter = Foundation.DateFormatter()
formatter.dateFormat = "LLLL dd, HH:mm at"
return formatter.string(from: date)}
This will return a date in this format
--> "January 21, 05:30 am"
Try,
let str = "2020-02-21 06:07:21 +0000"
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-mm-dd hh:mm:ss zzz"
if let date = formatter.date(from: str) {
formatter.dateFormat = "dd MMM yyyy hh:mm a"
let formattedDate = formatter.string(from: date)
print(formattedDate)
}
Swift-this answer helped me
swift - how to convert date from am/pm to 24 hour format
// posting my work here aswell.
i had device formate in 24H.
i needed in 12H.
so i just converted date object to required formate with this code snippet.
let df = DateFormatter()
df.dateFormat = "d MMM yyyy h:mm a"
let time12 = df.string(from: Date())
print(time12)

How do you display date in this format? "Jul 18, 2018 at 10:02 AM"

let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "UTC")
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
let date = dateFormatter.date(from: "2018-07-18T17:02:02.614Z")
date description prints: 2015-06-18 17:02:02 +0000
Playground seems to naturally outputs this on the right side: "Jun 18, 2015 at 10:02 AM"
How do I format it to display this? "Jul 18, 2018 at 10:02 AM"
Thanks!
You need to format date (which is now a Date instance) using another DateFormatter. And you should use date and time styles, not a fixed format for this.
And "UTC" is not a locale, it's a timezone. But you don't need that. But you should use the special locale of en_US_POSIX when parsing a fixed format date string.
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
let date = dateFormatter.date(from: "2018-07-18T17:02:02.614Z")
if let date = date {
let outputFormatter = DateFormatter()
outputFormatter.dateStyle = .medium
outputFormatter.timeStyle = .short
let output = outputFormatter.string(from: date)
print(output)
}
Output:
Jul 18, 2018 at 11:02 AM
Note that the time will depend on your local timezone. By default the output will be in local time so don't expect the output to be 17:02 since that is the time in the UTC timezone.

Swift: get the offset value from a date object

as simple as it sounds, but it is hard to find my exact question in google.
I'm trying to ignore the UTC printed out value. I receive multiple dates, this one here is just an example: (it could be +0900, -0200, etc...)
"2017-05-01T12:30:00-0700"
once I apply it to a value using these lines:
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssxxxxx"
if let result = formatter.date(from: time) {print result}
the value of the dateTimeResult prints:
2017-05-01 19:30:00 UTC
Using swift date objects, how do I slice out the part "-0700", multiply the -7 or +7 (this example is negative) by minutes by seconds. I'll save that total as int in DB (I need it for categorizing the different timezones later). Then applying that total to the incoming date input using this line:
let output = Calendar.current.date(byAdding: .second, value: totalSecs, to: result)
The goal is to end up with this date:
"2017-05-01 12:30:00"
I already have a solution using string manipulation, but I don't think that is the ideal solution. If it must be done by string, how do you do it?
If I understand you correctly you want only the date and time portion ignoring always the time zone information.
In this case strip the time zone from the date string with regular expression
let dateString = "2017-05-01T12:30:00-0700"
let dateStringIgnoringTimeZone = dateString.replacingOccurrences(of: "[+-]\\d{4}", with: "", options: .regularExpression)
print(dateStringIgnoringTimeZone) // "2017-05-01T12:30:00"
let dateFormatter = DateFormatter()
dateFormatter.calendar = Calendar(identifier: .iso8601)
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
let date = dateFormatter.date(from: dateStringIgnoringTimeZone)!
I think you should keep the date as it is and then just use DateFormatter to display the time at that timezone
let time = "2017-05-01T12:30:00-0700"
let dateFormatter = DateFormatter()
dateFormatter.calendar = Calendar(identifier: .iso8601)
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssxxxxx"
if let result = dateFormatter.date(from: time) {
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
print(dateFormatter.string(from: result)) // "2017-05-01 16:30:00 (corresponding time at my location GMT-3)
// to display it at -0700 just set the formatter timaZone
dateFormatter.timeZone = TimeZone(secondsFromGMT: -3600 * 7)
print(dateFormatter.string(from: result)) // "2017-05-01 12:30:00\n"
}
To get the timezone offset from the string:
let hours = Int(time.suffix(5).prefix(3)) ?? 0
let minutes = Int(time.suffix(2)) ?? 0
let offset = hours * 3600 + minutes * 60
print(offset) // -25200

Extracting the offset value from a ISO-8601 string in Swift

With NSDateFormatter, if I pass in an ISO-8601 date+time value with an offset, it will read the offset and adjust the output to a UTC value, like so:
// Setup
let formatter = NSDateFormatter()
formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
// Test
let input = "2016-04-16 04:12:00-0800"
let output = formatter.dateFromString( input )
let outputStr = formatter.stringFromDate( output )
print( outputStr ) // "2016-04-15 08:12:00-0000"
So far, so good.
But I want to get at that offset value myself. My application is a client for a webservice which preserves date-time offset information, so I must do the same (as if I blindly return outputStr to the webservice, it will have lost the offset information so the database won't know what the offset was when the datetime was collected.
NSDateFormatter only seems to accept timezone information for outputting dates, there's no way for me to get the numeric offset out of an input string.
'self explanatory' example
import Foundation
let formatter = NSDateFormatter()
formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd HH:mm:ssZ"
// Test
let input = "2016-04-16 04:12:00-0800"
let output = formatter.dateFromString( input )
// with curent time zone (system default
let outputStrL = formatter.stringFromDate( output! )
// with time zone Z+0000
formatter.timeZone = NSTimeZone(forSecondsFromGMT: 0)
let outputStr = formatter.stringFromDate( output! )
// with time zone Z-0800
formatter.timeZone = NSTimeZone(forSecondsFromGMT: -8 * 3600)
let outputStr1 = formatter.stringFromDate( output! )
print("My local time:", outputStrL)
print("GMT+0000 time:", outputStr)
print("GMT-0800 tume:", outputStr1)
/*
My local time: 2016-04-16 14:12:00+0200
GMT+0000 time: 2016-04-16 12:12:00+0000
GMT-0800 tume: 2016-04-16 04:12:00-0800
*/
if you replace the input string with any of output strings (outputStr, outputStrL, outputStr1), NSDate created from it represents the same value (time)