Created
February 26, 2017 10:26
-
-
Save jinthagerman/009c85b7bbd0a40dcbba747e89a501bf to your computer and use it in GitHub Desktop.
Time ago/ahead in Swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
struct DateComponentUnitFormatter { | |
private struct DateComponentUnitFormat { | |
let unit: Calendar.Component | |
let singularUnit: String | |
let pluralUnit: String | |
let futureSingular: String | |
let pastSingular: String | |
} | |
private let formats: [DateComponentUnitFormat] = [ | |
DateComponentUnitFormat(unit: .year, | |
singularUnit: "year", | |
pluralUnit: "years", | |
futureSingular: "Next year", | |
pastSingular: "Last year"), | |
DateComponentUnitFormat(unit: .month, | |
singularUnit: "month", | |
pluralUnit: "months", | |
futureSingular: "Next month", | |
pastSingular: "Last month"), | |
DateComponentUnitFormat(unit: .weekOfYear, | |
singularUnit: "week", | |
pluralUnit: "weeks", | |
futureSingular: "Next week", | |
pastSingular: "Last week"), | |
DateComponentUnitFormat(unit: .day, | |
singularUnit: "day", | |
pluralUnit: "days", | |
futureSingular: "Tomorrow", | |
pastSingular: "Yesterday"), | |
DateComponentUnitFormat(unit: .hour, | |
singularUnit: "hour", | |
pluralUnit: "hours", | |
futureSingular: "In an hour", | |
pastSingular: "An hour ago"), | |
DateComponentUnitFormat(unit: .minute, | |
singularUnit: "minute", | |
pluralUnit: "minutes", | |
futureSingular: "In a minute", | |
pastSingular: "A minute ago"), | |
DateComponentUnitFormat(unit: .second, | |
singularUnit: "second", | |
pluralUnit: "seconds", | |
futureSingular: "Just now", | |
pastSingular: "Just now"), | |
] | |
func string(forDateComponents dateComponents: DateComponents, useNumericDates: Bool) -> String { | |
for format in self.formats { | |
let unitValue: Int | |
switch format.unit { | |
case .year: | |
unitValue = dateComponents.year ?? 0 | |
case .month: | |
unitValue = dateComponents.month ?? 0 | |
case .weekOfYear: | |
unitValue = dateComponents.weekOfYear ?? 0 | |
case .day: | |
unitValue = dateComponents.day ?? 0 | |
case .hour: | |
unitValue = dateComponents.hour ?? 0 | |
case .minute: | |
unitValue = dateComponents.minute ?? 0 | |
case .second: | |
unitValue = dateComponents.second ?? 0 | |
default: | |
assertionFailure("Date does not have requried components") | |
return "" | |
} | |
switch unitValue { | |
case 2 ..< Int.max: | |
return "\(unitValue) \(format.pluralUnit) ago" | |
case 1: | |
return useNumericDates ? "\(unitValue) \(format.singularUnit) ago" : format.pastSingular | |
case -1: | |
return useNumericDates ? "In \(-unitValue) \(format.singularUnit)" : format.futureSingular | |
case Int.min ..< -1: | |
return "In \(-unitValue) \(format.pluralUnit)" | |
default: | |
break | |
} | |
} | |
return "Just now" | |
} | |
} | |
extension Date { | |
func timeAgoSinceNow(useNumericDates: Bool = false) -> String { | |
let calendar = Calendar.current | |
let unitFlags: Set<Calendar.Component> = [.minute, .hour, .day, .weekOfYear, .month, .year, .second] | |
let now = Date() | |
let components = calendar.dateComponents(unitFlags, from: self, to: now) | |
let formatter = DateComponentUnitFormatter() | |
return formatter.string(forDateComponents: components, useNumericDates: useNumericDates) | |
} | |
} |
Sounds like your date might be deserializing incorrectly? If you convert it to a string using
DateFormatter
, is it in the correct time zone?
No, my serailizing is fine. But the relative time that is being returned is according to UTC which is not my timezone
That doesn't make sense. There's no presumption of time zone in this code and Date
is time zone independent ("A specific point in time, independent of any calendar or time zone." - Apple Docs).
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Sounds like your date might be deserializing incorrectly? If you convert it to a string using
DateFormatter
, is it in the correct time zone?