You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI时间计算异常及时长向上取整至15分钟的实现需求

解决SwiftUI中工作时长计算与向上取整问题

一、修复时间间隔计算不准确的问题

原代码中DatePicker选择时分时,底层Date对象仍保留当前的秒数,导致计算出的时间差包含秒数偏差,比如你遇到的3分钟差值却算出158秒的情况。解决方法是先将开始/结束时间的秒数清零,只保留小时和分钟部分:

1. 添加时间格式化工具方法

在ContentView外扩展Date,添加清除秒数的方法:

extension Date {
    func roundedToMinute() -> Date {
        let calendar = Calendar.current
        let components = calendar.dateComponents([.year, .month, .day, .hour, .minute], from: self)
        return calendar.date(from: components)!
    }
}

2. 使用处理后的时间计算差值

在计算时长时,先对startTime和endTime调用roundedToMinute(),确保秒数为0:

let cleanedStartTime = startTime.roundedToMinute()
let cleanedEndTime = endTime.roundedToMinute()
let diffSeconds = cleanedEndTime.timeIntervalSince(cleanedStartTime)
let caseHours = Int(diffSeconds) / 3600
let caseMinutes = (Int(diffSeconds) % 3600) / 60
Text("\(Int(diffSeconds)) 秒 = \(caseHours) 小时:\(caseMinutes) 分钟")

这样就能得到精确的时分差值,不会出现秒数偏差导致的错误。

二、实现时长向上取整至最近15分钟

通过数学运算即可实现向上取整:将总分钟数除以15,向上取整后再乘以15。

计算并取整时长

基于上述的diffSeconds,先转换为总分钟数,再进行取整:

let totalMinutes = diffSeconds / 60
// 向上取整到最近的15分钟
let roundedUpMinutes = ceil(totalMinutes / 15) * 15
let roundedHours = Int(roundedUpMinutes) / 60
let roundedRemainingMinutes = Int(roundedUpMinutes) % 60
Text("向上取整后时长:\(roundedHours) 小时:\(roundedRemainingMinutes) 分钟")

完整整合后的代码

将上述修改整合到原代码中,同时添加24小时制强制设置:

import SwiftUI

extension Date {
    func roundedToMinute() -> Date {
        let calendar = Calendar.current
        let components = calendar.dateComponents([.year, .month, .day, .hour, .minute], from: self)
        return calendar.date(from: components)!
    }
}

struct ContentView: View {
    
    @State private var startTime = Date()
    @State private var endTime = Date()
    
    var body: some View {
        NavigationView {
            Form {
                Section(header: Text("输入工作时间:")) {
                    DatePicker("开始时间", selection: $startTime, displayedComponents: .hourAndMinute)
                        .environment(\.locale, Locale(identifier: "zh_CN")) // 强制24小时制显示
                    DatePicker("结束时间", selection: $endTime, in: startTime..., displayedComponents: .hourAndMinute)
                        .environment(\.locale, Locale(identifier: "zh_CN"))
                }
                Section(header: Text("已选时间:")) {
                    Text("开始时间 = \(startTime.formatted(date: .omitted, time: .shortened))")
                    Text("结束时间 = \(endTime.formatted(date: .omitted, time: .shortened))")
                }
                Section(header: Text("工作时长:")) {
                    let cleanedStartTime = startTime.roundedToMinute()
                    let cleanedEndTime = endTime.roundedToMinute()
                    let diffSeconds = cleanedEndTime.timeIntervalSince(cleanedStartTime)
                    
                    let caseHours = Int(diffSeconds) / 3600
                    let caseMinutes = (Int(diffSeconds) % 3600) / 60
                    Text("\(Int(diffSeconds)) 秒 = \(caseHours) 小时:\(caseMinutes) 分钟")
                    
                    // 向上取整到15分钟
                    let totalMinutes = diffSeconds / 60
                    let roundedUpMinutes = ceil(totalMinutes / 15) * 15
                    let roundedHours = Int(roundedUpMinutes) / 60
                    let roundedRemainingMinutes = Int(roundedUpMinutes) % 60
                    Text("向上取整后时长:\(roundedHours) 小时:\(roundedRemainingMinutes) 分钟")
                }
            }
            .navigationTitle("服务费用计算器")
        }
    }
}

内容的提问来源于stack exchange,提问作者mgianzero

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 22:45:27