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
相关产品推荐
相关产品推荐

