-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathTimeAgoInWords.swift
123 lines (113 loc) · 5.91 KB
/
TimeAgoInWords.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
//
// TimeAgoInWords.swift
// Ello
//
// Created by Ryan Boyajian on 4/2/15.
// Copyright (c) 2015 Ello. All rights reserved.
//
import Foundation
final public class TimeAgoInWords {
}
private let table = "TimeAgoInWords"
private let resourceBundle: Bundle = {
let thisBundle = Bundle(for: TimeAgoInWords.self)
let bundlePath = thisBundle.path(forResource: "TimeAgoInWords", ofType: "bundle")
let bundle = Bundle(path: bundlePath!)
return bundle!
}()
public struct TimeAgoInWordsStrings {
static var LessThan = NSLocalizedString("less-than", tableName: table, bundle: resourceBundle, comment: "Indicates a less-than number")
static var About = NSLocalizedString("approximate", tableName: table, bundle: resourceBundle, comment: "Indicates an approximate number")
static var Over = NSLocalizedString("exceeding", tableName: table, bundle: resourceBundle, comment: "Indicates an exceeding number")
static var Almost = NSLocalizedString("approaching", tableName: table, bundle: resourceBundle, comment: "Indicates an approaching number")
static var Seconds = NSLocalizedString("seconds", tableName: table, bundle: resourceBundle, comment: "More than one second in time")
static var Minute = NSLocalizedString("one-minute", tableName: table, bundle: resourceBundle, comment: "One minute in time")
static var Minutes = NSLocalizedString("minutes", tableName: table, bundle: resourceBundle, comment: "More than one minute in time")
static var Hour = NSLocalizedString("one-hour", tableName: table, bundle: resourceBundle, comment: "One hour in time")
static var Hours = NSLocalizedString("hours", tableName: table, bundle: resourceBundle, comment: "More than one hour in time")
static var Day = NSLocalizedString("one-day", tableName: table, bundle: resourceBundle, comment: "One day in time")
static var Days = NSLocalizedString("days", tableName: table, bundle: resourceBundle, comment: "More than one day in time")
static var Months = NSLocalizedString("months", tableName: table, bundle: resourceBundle, comment: "More than one month in time")
static var Years = NSLocalizedString("years", tableName: table, bundle: resourceBundle, comment: "More than one year in time")
static public func updateStrings(_ dict: [String: String]) {
for (key, value) in dict {
switch key.lowercased() {
case "lessthan": LessThan = value
case "about": About = value
case "over": Over = value
case "almost": Almost = value
case "seconds": Seconds = value
case "minute": Minute = value
case "minutes": Minutes = value
case "hour": Hour = value
case "hours": Hours = value
case "day": Day = value
case "days": Days = value
case "months": Months = value
case "years": Years = value
default: print("TimeAgoInWordsStrings.updateStrings key \(key) is not supported.")
}
}
}
}
public extension Date {
func distanceOfTimeInWords(_ toDate:Date) -> String {
let MINUTES_IN_YEAR = 525_600.0
let MINUTES_IN_QUARTER_YEAR = 131_400.0
let MINUTES_IN_THREE_QUARTERS_YEAR = 394_200.0
let distanceInSeconds = round(abs(toDate.timeIntervalSince(self)))
let distanceInMinutes = round(distanceInSeconds / 60.0)
switch distanceInMinutes {
case 0...1:
switch distanceInSeconds {
case 0...4:
return TimeAgoInWordsStrings.LessThan + "5" + TimeAgoInWordsStrings.Seconds
case 5...9:
return TimeAgoInWordsStrings.LessThan + "10" + TimeAgoInWordsStrings.Seconds
case 10...19:
return TimeAgoInWordsStrings.LessThan + "20" + TimeAgoInWordsStrings.Seconds
case 20...39:
return "30" + TimeAgoInWordsStrings.Seconds
case 40...59:
return TimeAgoInWordsStrings.LessThan + "1" + TimeAgoInWordsStrings.Minute
default:
return "1" + TimeAgoInWordsStrings.Minute
}
case 2...45:
return "\(Int(round(distanceInMinutes)))" + TimeAgoInWordsStrings.Minutes
case 45...90:
return TimeAgoInWordsStrings.About + "1" + TimeAgoInWordsStrings.Hour
// 90 mins up to 24 hours
case 90...1_440:
return TimeAgoInWordsStrings.About + "\(Int(round(distanceInMinutes / 60.0)))" + TimeAgoInWordsStrings.Hours
// 24 hours up to 42 hours
case 1_440...2_520:
return "1" + TimeAgoInWordsStrings.Day
// 42 hours up to 30 days
case 2_520...43_200:
return "\(Int(round(distanceInMinutes / 1_440.0)))" + TimeAgoInWordsStrings.Days
// 30 days up to 60 days
case 43_200...86_400:
return TimeAgoInWordsStrings.About + "\(Int(round(distanceInMinutes / 43_200.0)))" + TimeAgoInWordsStrings.Months
// 60 days up to 365 days
case 86_400...525_600:
return "\(Int(round(distanceInMinutes / 43_200.0)))" + TimeAgoInWordsStrings.Months
// TODO: handle leap year like rails does
default:
let remainder = distanceInMinutes.truncatingRemainder(dividingBy: MINUTES_IN_YEAR)
let distanceInYears = Int(floor(distanceInMinutes / MINUTES_IN_YEAR))
if remainder < MINUTES_IN_QUARTER_YEAR {
return TimeAgoInWordsStrings.About + "\(distanceInYears)" + TimeAgoInWordsStrings.Years
}
else if remainder < MINUTES_IN_THREE_QUARTERS_YEAR {
return TimeAgoInWordsStrings.Over + "\(distanceInYears)" + TimeAgoInWordsStrings.Years
}
else {
return TimeAgoInWordsStrings.Almost + "\(distanceInYears + 1)" + TimeAgoInWordsStrings.Years
}
}
}
func timeAgoInWords() -> String {
return self.distanceOfTimeInWords(Date())
}
}