Swift 正确计算时间占天的比例

Swift Correct calculation of time as a proportion of day

我正在尝试计算特定时间占一天的比例。例如,06:00是0.25,18:00是0.75等等

我正在评估在 timeZone = "GMT" 中创建的一系列 Date 类型的日期。下面的例程工作正常。但是,当我在 23:00 之后计算 DST 日期的时间时,计算出错,因为时间被计算为第二天(例如 23:08 被计算为 00:08)

有什么方法可以让我识别从格林威治标准时间到夏令时的转变将日期带入了第二天?然后我可以相应地调整计算。

我判断输入时间所占比例的函数是:

func getTimeAsProportionOfDay(time: Date) -> Double {
    //calculates the amount of day, between 0 and 1 given the input date

    let calendar =  Calendar.current
    let hours = calendar.component(.hour, from: time)
    let minutes = calendar.component(.minute, from: time)
    let seconds = calendar.component(.second, from: time)
    let totalSeconds = Double(hours * 60 * 60 + minutes * 60 + seconds)

    return Double(totalSeconds) / Double(secondsInDay)
}

此外,我知道我的 secondsInDay (= 24*60*60) 常量在技术上可能不正确,但我不确定用什么系统常量替换它。

谢谢。

一般来说,我会这样做:

let date = Date()

var dayStart = Date()
var dayDuration: TimeInterval = 0

Calendar.current.dateInterval(of: .day, start: &dayStart, interval: &dayDuration, for: date)

let timeInterval = date.timeIntervalSince(dayStart)
let percentage = timeInterval / dayDuration

print(percentage)

你只需要在原始日期之后减去一秒。然后使用日历方法计算该日期的秒数

func ordinality(of smaller: Calendar.Component, in larger: Calendar.Component, for date: Date) -> Int?

一些帮手可以让你的生活更轻松

extension Date {
    var dayAfter: Date { Calendar.current.date(byAdding: .day, value: 1, to: noon)!}
    var noon: Date { Calendar.current.date(bySettingHour: 12, minute: 0, second: 0, of: self)! }
    var startOfDay: Date { Calendar.current.startOfDay(for: self) }
    var endOfDay: Date { Calendar.current.date(byAdding: .init(second: -1), to: dayAfter.startOfDay)! }
}

测试 endOfDay

Date().endOfDay  // "Feb 7, 2020 at 11:59 PM"

你的方法:

func getTimeAsProportionOfDay(time: Date) -> Double {
    // discarding the fractional seconds
    let time = Calendar.current.date(bySetting: .nanosecond, value: 0, of: time)!
    return Double(Calendar.current.ordinality(of: .second, in: .day, for: time)!-1) /
        Double(Calendar.current.ordinality(of: .second, in: .day, for: time.endOfDay)!-1)
}

游乐场测试:

let date = DateComponents(calendar: .current, year: 2020, month: 2, day: 7, hour: 23, minute: 08).date!
date.endOfDay
let result = getTimeAsProportionOfDay(time: date)  // 0.9639000451394113

所有,感谢您的帮助。我想我已经通过使用固定的一天开始时间进行比较找到了解决方案。

func getTimeAsProportionOfDay(time: Date) -> Double {
    //calculates the amount of day, between 0 and 1 given the input date


    if Int(time.timeIntervalSince(tides.tideDate)) > secondsInDay { //time has been moved to next day by BST change) so return 1 for gradient
        return 1.0
    } else {/// this was my original code
        let calendar =  Calendar.current
        let hours = calendar.component(.hour, from: time)
        let minutes = calendar.component(.minute, from: time)
        let seconds = calendar.component(.second, from: time)
        let totalSeconds = Double(hours * 60 * 60 + minutes * 60 + seconds)

        return Double(totalSeconds) / Double(secondsInDay)
    }
}