Created
April 17, 2024 17:13
-
-
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.
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
/// 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