Skip to content

Instantly share code, notes, and snippets.

@jpavley
Created April 17, 2024 17:13
Show Gist options
  • Save jpavley/7904ad73eddf194a105497bc4d3fa752 to your computer and use it in GitHub Desktop.
Save jpavley/7904ad73eddf194a105497bc4d3fa752 to your computer and use it in GitHub Desktop.
Elapsed time since last logged date function. Returns a string representation of time elapsed since a date.
/// Returns a string representation of the time elapsed since the entry was logged.
/// It works at 4 resolutions:
/// - Full: "5yr, 6mo, 3d, 4h, 25m, 35s"
/// - Years/Months: "5yr, 6mo"
/// - Days/Hours: "3d, 4h"
/// - Minutes/Seconds: "25m, 35s"
/// - Note: Only non-zero values are rendered: "24m" instead of "24m, 0s"
/// - Parameters:
/// - loggedDate: The Date when the record was first logged
/// - full: A flag that specifies the resolution: if true full resolution, if false scoped resolution
/// - Returns: A string that represents elapsed time: "5yr, 6mo" or "5yr, 6mo, 3d, 4h, 25m, 35s"
static func elaspedTimeSince(loggedDate: Date, full: Bool = true) -> String {
enum ElapsedTimeScope {
case full, year, day, minute
}
let elapsedTime = -loggedDate.timeIntervalSinceNow
let secondsInMinute: TimeInterval = 60
let secondsInHour: TimeInterval = 3600
let secondsInDay: TimeInterval = 86400
let secondsInYear: TimeInterval = 31536000
let secondsInMonth: TimeInterval = 2592000 // Average month length in seconds (30 days)
let years = Int(elapsedTime / secondsInYear)
let months = Int((elapsedTime.truncatingRemainder(dividingBy: secondsInYear)) / secondsInMonth)
let days = Int((elapsedTime.truncatingRemainder(dividingBy: secondsInMonth)) / secondsInDay)
let hours = Int((elapsedTime.truncatingRemainder(dividingBy: secondsInDay)) / secondsInHour)
let minutes = Int((elapsedTime.truncatingRemainder(dividingBy: secondsInHour)) / secondsInMinute)
let seconds = Int(elapsedTime.truncatingRemainder(dividingBy: secondsInMinute))
var timeScope: ElapsedTimeScope = .minute // need to set a default value in case all time values are 0
if full {
timeScope = .full
} else {
if years != 0 || months != 0 {
timeScope = .year
} else {
if days != 0 || hours != 0 {
timeScope = .day
} else {
if minutes != 0 || seconds != 0 {
timeScope = .minute
}
}
}
}
var components: [String] = []
switch timeScope {
case .full:
if years > 0 {
components.append("\(years)yr")
}
if months > 0 {
components.append("\(months)mo")
}
if days > 0 {
components.append("\(days)d")
}
if hours > 0 {
components.append("\(hours)h")
}
if minutes > 0 {
components.append("\(minutes)m")
}
if seconds > 0 {
components.append("\(seconds)s")
}
case .year:
if years > 0 {
components.append("\(years)yr")
}
if months > 0 {
components.append("\(months)mo")
}
case .day:
if days > 0 {
components.append("\(days)d")
}
if hours > 0 {
components.append("\(hours)h")
}
case .minute:
if minutes > 0 {
components.append("\(minutes)m")
}
if seconds > 0 {
components.append("\(seconds)s")
}
}
return components.joined(separator: full ? "," : ", ")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment