taler-ios

iOS apps for GNU Taler (wallet)
Log | Files | Refs | README | LICENSE

TalerDater.swift (5629B)


      1 /*
      2  * This file is part of GNU Taler, ©2022-25 Taler Systems S.A.
      3  * See LICENSE.md
      4  */
      5 /**
      6  * @author Marc Stibane
      7  */
      8 import Foundation
      9 import taler_swift
     10 
     11 public class TalerDater: DateFormatter {
     12     public static let shared = TalerDater()
     13 
     14     static func relativeDate(_ from: TimeInterval, _ minimalistic: Bool) -> String? {
     15         if from > 0 {       // transactions should always be in the past
     16             let minute = from / 60.0                // from is in seconds
     17             if minute < 1 { return minimalistic ? String(localized: "Now")
     18                                                 : String(localized: "Right now") }
     19             if minute < 2 { return minimalistic ? String(localized: "1 min ago")
     20                                                 : String(localized: "1 minute ago") }
     21             if minute < 55 { return minimalistic ? String(localized: "\(Int(minute)) min ago")
     22                                                  : String(localized: "\(Int(minute)) minutes ago") }
     23             if minute < 60 { return minimalistic ? String(localized: "~ 1 hour ago")
     24                                                  : String(localized: "About an hour ago") }
     25             if minute < 75 { return String(localized: "1 hour ago") }
     26             if minute < 105 { return minimalistic ? String(localized: "~ 1½ hours ago")
     27                                                   : String(localized: "About 1½ hours ago") }
     28             if minute < 135 { return minimalistic ? String(localized: "~ 2 hours ago")
     29                                                   : String(localized: "About 2 hours ago") }
     30             let hour = minute / 60.0
     31             let calendar = Calendar.current
     32             let now = Date.now
     33             let currHour = Double(calendar.component(.hour, from: now))
     34             let currMin = Double(calendar.component(.minute, from: now))
     35             let currTime = currHour + currMin/60
     36             if hour < currTime { return String(localized: "\(Int(hour)) hours ago") }
     37             if hour < currTime + 24 { return String(localized: "Yesterday") }
     38             let day = (hour - currTime) / 24.0
     39             if day < 7 { return String(localized: "\(Int(day+1)) days ago") }
     40             if day < 14 { return String(localized: "More than a week ago") }
     41             // will fall thru...
     42             return nil
     43         } else {            // Yikes❗️ transaction date is in the future
     44             return nil
     45         }
     46     }
     47 
     48     /// produces a random date string between `now` and m+h+d (edit values after 60x)
     49     public static func randomDateStr(_ minimalistic: Bool) -> String {
     50         let m =       60*15
     51         let h =    60*60*9
     52         let d = 24*60*60*22
     53         let t = m+h+d
     54         let randomTime = Int.random(in:1...t)
     55         if let randomDateStr = relativeDate(Double(randomTime), minimalistic) {
     56             return randomDateStr
     57         } else {    // t is too large for a relative date
     58                     // return absolute date with random locale
     59             let localeStr = (randomTime&1 == 1) ? "de_DE" : "en_US"
     60             shared.locale = NSLocale(localeIdentifier: localeStr) as Locale
     61             let randomDate = Date(timeIntervalSinceNow: Double(-t))
     62             return shared.string(from: randomDate)
     63         }
     64     }
     65 
     66 //    public static func date(from: Timestamp) -> Date {
     67 //        let milliseconds = try from.milliseconds()
     68 //        let date = Date(milliseconds: milliseconds)
     69 //        return date
     70 //    }
     71 
     72     /// converts a timestamp into a formatted date string
     73     public static func dateString(_ from: Timestamp, _ minimalistic: Bool, relative: Bool = false) -> (String, Date?) {
     74         do {
     75             let milliseconds = try from.milliseconds()
     76             let date = Date(milliseconds: milliseconds)
     77 
     78             if relative {
     79                 let now = Date.now
     80                 let timeInterval = now.timeIntervalSince(date)
     81                 if let relativeDate = relativeDate(timeInterval, minimalistic) {
     82                     return (relativeDate, date)
     83                 }
     84             }
     85             return (shared.string(from: date), date)
     86         } catch {       // Never
     87             let never = String(localized: "No date", comment: "Timestamp missing or invalid")
     88             return (never, nil)
     89         }
     90     }
     91 
     92     public static func accessibilityDate(_ date: Date?) -> String? {
     93         if let date {
     94             let formatted = date.formatted(date: .long, time: .shortened)
     95 //            print(formatted)
     96             return formatted
     97         }
     98         return nil
     99     }
    100 
    101     public static func dateString() -> String {
    102         shared.string(from: Date())
    103     }
    104 
    105     private override init() {
    106         super.init()
    107         self.setLocalizedDateFormatFromTemplate("EEEdMMM")        // abbreviated day of week
    108         self.dateStyle = .medium
    109         self.timeStyle = .short
    110 //        self.timeZone = TimeZone(abbreviation: "UTC")         // UTC prints GMT
    111 //        self.dateFormat = "z yyyy-MM-dd HH:mm"                // "GMT 2022-11-09 18:00"
    112     }
    113 
    114     required init?(coder aDecoder: NSCoder) {
    115         fatalError("init(coder:) has not been implemented")
    116     }
    117 }
    118 
    119 extension Date {
    120     static func - (lhs: Date, rhs: Date) -> TimeInterval {
    121         lhs.timeIntervalSinceReferenceDate - rhs.timeIntervalSinceReferenceDate
    122     }
    123 
    124     var iso:String {
    125         self.formatted(.iso8601
    126 //                       .day().month().year().dateSeparator(.dash)
    127                        .timeSeparator(.omitted))
    128     }
    129 }
    130 extension TimeInterval {
    131     var seconds: Int {
    132         Int(self.rounded())
    133     }
    134 
    135     var milliseconds: Int {
    136         Int(self * 1000)
    137     }
    138 }