Last active
June 28, 2017 23:49
-
-
Save ckalbas/eccdc7db6893001d0811dea7823549a2 to your computer and use it in GitHub Desktop.
"Time ago" em 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
/// Based on https://gist.github.com/jinthagerman/009c85b7bbd0a40dcbba747e89a501bf | |
import UIKit | |
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: .day, | |
singularUnit: "dia", | |
pluralUnit: "dias", | |
futureSingular: "amanhã", | |
pastSingular: "ontem"), | |
DateComponentUnitFormat(unit: .hour, | |
singularUnit: "hora", | |
pluralUnit: "horas", | |
futureSingular: "em 1 hora", | |
pastSingular: "há 1 hora"), | |
DateComponentUnitFormat(unit: .minute, | |
singularUnit: "minuto", | |
pluralUnit: "minutos", | |
futureSingular: "em 1 minuto", | |
pastSingular: "há 1 minuto"), | |
] | |
func string(_ date: Date, forDateComponents dateComponents: DateComponents, useNumericDates: Bool) -> String { | |
for format in self.formats { | |
let unitValue: Int | |
// MARK: - Get difference, in case. | |
switch format.unit { | |
case .day: | |
unitValue = dateComponents.day ?? 0 | |
case .hour: | |
unitValue = dateComponents.hour ?? 0 | |
case .minute: | |
unitValue = dateComponents.minute ?? 0 | |
default: | |
assertionFailure("Date does not have requried components") | |
return "" | |
} | |
// MARK: - 1 day difference handling | |
// Set formatter | |
let formatter = DateFormatter() | |
// Portuguese-BR | |
formatter.locale = Locale(identifier: "pt_BR") | |
let absoluteUnitValue = abs(unitValue) | |
// Checks if is 1 day difference | |
let todayDay = Calendar.current.component(.day, from: Date()) | |
let dateDay = Calendar.current.component(.day, from: date) | |
if abs(todayDay - dateDay) == 1 { | |
let day = todayDay > dateDay ? "ontem" : "amanhã" | |
formatter.dateFormat = "'\(day) às' HH:mm" | |
return formatter.string(from: date) | |
} | |
// MARK: - Handle date difference | |
switch (format.unit, absoluteUnitValue){ | |
case (_, 0): | |
break | |
// Over 7 days | |
case (.day, 7...Int.max): | |
// Same year? | |
let todayYear = Calendar.current.component(.year, from: Date()) | |
let dateYear = Calendar.current.component(.year, from: date) | |
if todayYear != dateYear{ | |
// Different years, change date to "EEEEEE, dd/MM/yy". | |
formatter.dateFormat = "EEEEEE, dd/MM/yy" | |
}else { | |
// Same year, more detail on date difference | |
formatter.dateFormat = "dd 'de' MMMM 'às' HH:mm" | |
} | |
return formatter.string(from: date) | |
// 1 to 7 days | |
case (.day, 1..<7): | |
formatter.dateFormat = "EEEE, 'às' HH:mm" | |
return formatter.string(from: date) | |
case (.hour, 0...Int.max), (.minute, 5...Int.max): | |
// Same day | |
let prefix = unitValue > 0 ? "há" : "em" | |
return "\(prefix) \(absoluteUnitValue) \(absoluteUnitValue == 1 ? format.singularUnit : format.pluralUnit)" | |
default: | |
break | |
} | |
} | |
// Under 5 minutes. | |
return "agora" | |
} | |
} | |
extension Date { | |
func timeAgoSinceNow(useNumericDates: Bool = false) -> String { | |
let calendar = Calendar.current | |
let unitFlags: Set<Calendar.Component> = [.minute, .hour, .day] | |
let now = Date() | |
let components = calendar.dateComponents(unitFlags, from: self, to: now) | |
let formatter = DateComponentUnitFormatter() | |
return formatter.string(self, forDateComponents: components, useNumericDates: useNumericDates) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment