deskside / emodiary

0 stars 0 forks source link

How to format the Date? #8

Closed deskside closed 1 year ago

deskside commented 1 year ago

Method 1: Apple's code

Apple uses built-in DateFormatter.

private let itemFormatter: DateFormatter = {
    let formatter = DateFormatter()
    formatter.dateStyle = .short
    formatter.timeStyle = .medium
    return formatter
}()

Then use as follows:

Text(Date(), formatter: itemFormatter)
deskside commented 1 year ago

Method 2: My code

I use functions to turn date into specific format. It's more intuitive but also more complex.


struct DateAndString{

    // MARK: String and Date
    static func dateToString(date:Date, dateFormat:String = Constants.timeFormatWithDateHourMinute) -> String{
        let formatter = DateFormatter()
        formatter.locale = Locale.init(identifier: Constants.defaultTimeIdentifier)
        formatter.dateFormat = dateFormat
        let date = formatter.string(from: date)
        return date
    }
    static func stringToDate(string:String, dateFormat:String = Constants.timeFormatWithDateHourMinute) -> Date{
        let formatter = DateFormatter()
        formatter.locale = Locale.init(identifier: Constants.defaultTimeIdentifier)
        formatter.dateFormat = dateFormat

        let date = formatter.date(from: string)
        return date ?? Date()
    }

    // MARK: Specific date
    static func yesterDay(today:Date = Date()) -> Date {
        var dayComponent = DateComponents()
        dayComponent.day = -1
        let calendar = Calendar.current
        let nextDay =  calendar.date(byAdding: dayComponent, to: today)!
        let formatter = DateFormatter()
        formatter.locale = .current
        formatter.dateFormat = Constants.timeFormatWithDateHourMinute
        return stringToDate(string: formatter.string(from: nextDay)) 
    }

    static func theDayBeforeYesterDay(date:Date = Date()) -> Date {
        var dayComponent = DateComponents()
        dayComponent.day = -2
        let calendar = Calendar.current
        let nextDay =  calendar.date(byAdding: dayComponent, to: Date())!
        let formatter = DateFormatter()
        formatter.locale = .current
        formatter.dateFormat = Constants.timeFormatWithDateHourMinute
        return stringToDate(string: formatter.string(from: nextDay))
    }

    static func tomorrow(today:Date = Date()) -> Date {
        var dayComponent = DateComponents()
        dayComponent.day = +1
        let calendar = Calendar.current
        let nextDay =  calendar.date(byAdding: dayComponent, to: today)!
        let formatter = DateFormatter()
        formatter.locale = .current
        formatter.dateFormat = Constants.timeFormatWithDateHourMinute
        return stringToDate(string: formatter.string(from: nextDay))
    }
    static func specificDateFromGivenDate(today:Date = Date(), difference:Int) -> Date {
        var dayComponent = DateComponents()
        dayComponent.day = difference
        let calendar = Calendar.current
        let nextDay =  calendar.date(byAdding: dayComponent, to: today)!
        let formatter = DateFormatter()
        formatter.locale = .current
        formatter.dateFormat = Constants.timeFormatWithDateHourMinute
        return stringToDate(string: formatter.string(from: nextDay))
    }

    // MARK: Start point and end point
    static func todayStartPoint(date:Date = Date()) -> Date {
        let calendar = Calendar.current
        let startDate = calendar.startOfDay(for: date)
        return startDate
    }
    static func todayEndPoint() -> Date {
        let today = Date()
        let calendar = Calendar.current
        let startDate = calendar.startOfDay(for: today)
        let endDate = calendar.date(byAdding: .day, value: 1, to: startDate)!
        return endDate
    }
    static func tomorrowStartPoint(date:Date) -> Date {
        let tomorrow = self.tomorrow(today: date)
        let calendar = Calendar.current
        let startDate = calendar.startOfDay(for: tomorrow)
        return startDate
    }
    static func weekStartPoint(date:Date = Date()) -> Date {
        let aWeekAgo = self.specificDateFromGivenDate(difference: -6)
        let calendar = Calendar.current
        let startDate = calendar.startOfDay(for: aWeekAgo)
        return startDate
    }
    static func monthStartPoint(date:Date = Date()) -> Date {
        let aMonthAgo = self.specificDateFromGivenDate(difference: -30)
        let calendar = Calendar.current
        let startDate = calendar.startOfDay(for: aMonthAgo)
        return startDate
    }
    static func specificStartPoint(date:Date = Date(), difference:Int) -> Date {
        let ago = self.specificDateFromGivenDate(difference: difference)
        let calendar = Calendar.current
        let startDate = calendar.startOfDay(for: ago)
        return startDate
    }
    static func specificEndPoint(date:Date = Date(), difference:Int) -> Date {
        let ago = self.specificDateFromGivenDate(difference: difference)
        let calendar = Calendar.current
        let startDate = calendar.startOfDay(for: ago)
        let endDate = calendar.date(byAdding: .day, value: 1, to: startDate)!
        return endDate
    }

    // MARK: Time calculation
    static func timeIntervalBetweenMidnight(date:Date) -> Double{
        // This func will return seconds of the timedifference.
        var isAfterMidnight:Bool {
            if Int(self.dateToString(date: date, dateFormat:Constants.timeFormatWithHour)) ?? 0 >= 18{
                return false
            }else if Int(self.dateToString(date: date, dateFormat: Constants.timeFormatWithHour)) ?? 0 >= 0 && Int(self.dateToString(date: date, dateFormat: Constants.timeFormatWithHour)) ?? 0 < 18{
                return true
            }else{
                return false
            }
        }

        if isAfterMidnight {
            let difference = date.timeIntervalSince(todayStartPoint(date: date))
            return Double(difference)
        }else{
            let difference = date.timeIntervalSince(tomorrowStartPoint(date: date))
            return Double(difference)
        }

    }

    static func secondToHours(seconds:Int) -> String{
        return String(format: "%.1f", round(Double(seconds) / 3600.0))
    }

    static func averageTime(seconds:Int) -> String{
        if seconds > 0{
            let startPoint = todayStartPoint()
            let addDate = startPoint.addingTimeInterval(TimeInterval(seconds))
            let targetDateInString = self.dateToString(date: addDate, dateFormat: Constants.timeFormatWithHourMinute)
            return targetDateInString
        }else if seconds < 0{
            let subtraction = 86400 + seconds
            let startPoint = todayStartPoint()
            let addDate = startPoint.addingTimeInterval(TimeInterval(subtraction))
            let targetDateInString = self.dateToString(date: addDate, dateFormat: Constants.timeFormatWithHourMinute)
            return targetDateInString
        }else{
            return "00:00"
        }
    }

}

Then use as follows:

Text(DateAndString.secondToHours(3600))