Reputation: 166
I'am receiving following string: "2021-02-15T02:37:27.371243Z". I want to add hours by changing time zone of string to current time zone of device.
Date received from DateFormatter
with .current
timezone property from dateFormatter.date
method changes nothing.
Example:
let dateString = "2021-04-10T10:00:01.594119Z"
let dateFormatter = DateFormatter()
dateFormatter.timeZone = .current
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"
let date = dateFormatter.date(from: dateString)
let anotherDateFormatter = DateFormatter()
var calendar = Calendar.current
calendar.timeZone = .current
anotherDateFormatter.calendar = calendar
anotherDateFormatter.dateFormat = "hh:mm"
anotherDateFormatter.timeZone = .current
let string = anotherDateFormatter.string(from: date!)
print(string)
Output: 04:00. Incorrect, not my time.
I've come up with solution with calendar(current calendar has current time zone by default) by retrieving it's components:
let dateString = "2021-04-10T10:00:01.594119Z"
let dateFormatter = DateFormatter()
dateFormatter.timeZone = .current
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"
let date = dateFormatter.date(from: dateString)
print(hourWithMinutesForCurrentTimezone(date: date!))
private func hourWithMinutesForCurrentTimezone(date: Date) -> String {
let calendar = Calendar.current
let hours = String(calendar.component(.hour, from: date))
let formattedHours = hours.count == 1 ? "0\(hours)" : hours
let minutes = String(calendar.component(.minute, from: date))
let formattedMinutes = minutes.count == 1 ? "0\(minutes)" : minutes
return "\(formattedHours):\(formattedMinutes)"
}
Output: 16:00 - Yay! My time
It works and changes hour and minutes to the current timezone, but I don't find this solution elegant, anyone knows way of changing time to current timezone better?
Upvotes: 0
Views: 174
Reputation: 7591
I don't have fully understanding in dates, but there is a formatter made specifically for this type of datestring called ISO8601DateFormatter()
. It can be implemented like this.
extension String {
func toLocalDate() -> Date? {
let formatter = ISO8601DateFormatter()
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
return formatter.date(from: self)
}
}
let dateString = "2021-02-15T02:37:27.371243Z"
let date = dateString.toLocalDate() // "Feb 15, 2021 at 3:37 AM" (Sweden, GMT +2)
You can also create your own formatter: yyyy-MM-dd'T'HH:mm:ss.SSSSZZZ
yyyy: years
MM: month, numerical
dd: days
'T': String
HH: Hours in 24h format
mm: minutes
ss: seconds
SSSS: fractions of seconds (milliseconds)
ZZZ: timezone: it's enough with one Z, but I added two to clearly show the timezone is determined by the last three characters in your dateString.
extension String {
func toLocalDate() -> Date? {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSZZZ"
formatter.timeZone = TimeZone.current
return formatter.date(from: self)
}
}
let dateString = "2021-02-15T02:37:27.371243Z"
let date = dateString.toLocalDate() // "Feb 15, 2021 at 3:37 AM" (Sweden, GMT +2)
When you have a Date, then you can basically just use Calendar to pick the hours and minutes from it with Calendar.current.dateComponents([.hour, .minute], from: date)
.
Do note, toLocalDate returns nil, if the dateString
isn't formatted properly.
Upvotes: 2