Files
ccn/Services/Website/Sources/Library/Internal/Extensions/Date+Stamps.swift
T

97 lines
2.9 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Foundation
extension Date {
// MARK: Methods
/// How long until the date, in a few words: `47 h left`, `2 days left`, `under an hour left`.
/// - Parameter now: the moment counted from.
func countdown(
from now: Date
) -> String {
let hours = Int(timeIntervalSince(now) / 3_600)
switch hours {
case ..<1: return "under an hour left"
case ..<48: return "\(hours) h left"
default: return "\(hours / 24) days left"
}
}
/// The days an event runs over, e.g. `Sat 26 – Sun 27 Sep`.
static func span(
from start: Date,
to end: Date
) -> String {
let first = start.formatted(style.weekday(.abbreviated).day())
let last = end.formatted(style.weekday(.abbreviated).day().month(.abbreviated))
return calendar.isDate(start, inSameDayAs: end) ? last : "\(first) – \(last)"
}
/// Whether the date falls within the week from the given moment: an event "this weekend".
func isWithinAWeek(
of now: Date
) -> Bool {
(0..<7 * 86_400).contains(timeIntervalSince(now)) || Self.calendar.isDate(self, inSameDayAs: now)
}
/// The date as a day on a record, e.g. `20 Sep`.
var dayStamp: String {
formatted(Self.style.day().month(.abbreviated))
}
/// The date as a stamp on a record: `today, 09:14`, `yesterday, 21:38`, `20 Sep, 14:05`, or with the year once it differs.
///
/// Read on Amsterdam's clock: the marketplace is NL-first.
/// - Parameter now: the moment "today" is judged from.
func stamp(
relativeTo now: Date
) -> String {
let time = formatted(Self.style.hour(.twoDigits(amPM: .omitted)).minute(.twoDigits))
if Self.calendar.isDate(self, inSameDayAs: now) {
return "today, \(time)"
}
if
let yesterday = Self.calendar.date(byAdding: .day, value: -1, to: now),
Self.calendar.isDate(self, inSameDayAs: yesterday)
{
return "yesterday, \(time)"
}
let isSameYear = Self.calendar.isDate(self, equalTo: now, toGranularity: .year)
let day = formatted(isSameYear ? Self.style.day().month(.abbreviated) : Self.style.day().month(.abbreviated).year())
return "\(day), \(time)"
}
}
// MARK: - Helpers
private extension Date {
// MARK: Constants
/// The calendar days are told apart by, on Amsterdam's clock.
static let calendar: Calendar = {
var calendar = Calendar(identifier: .gregorian)
calendar.timeZone = timeZone
return calendar
}()
/// The base format style: British English, on Amsterdam's clock.
static let style = Date.FormatStyle(
locale: .init(identifier: "en_GB"),
calendar: calendar,
timeZone: timeZone
)
static let timeZone = TimeZone(identifier: "Europe/Amsterdam") ?? .gmt
}