Skip to content

Instantly share code, notes, and snippets.

@ckalbas
Last active June 28, 2017 23:49
Show Gist options
  • Save ckalbas/eccdc7db6893001d0811dea7823549a2 to your computer and use it in GitHub Desktop.
Save ckalbas/eccdc7db6893001d0811dea7823549a2 to your computer and use it in GitHub Desktop.
"Time ago" em Swift
/// 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