如何为Swift Duration创建仅显示秒数的自定义TimeFormatStyle
自定义Swift Duration的TimeFormatStyle处理秒级时长
Swift的Duration提供的.hourMinute、.hourMinuteSecond等预定义格式,没法覆盖仅含秒数或超过一天的时长场景。要实现自定义格式,将不足一分钟的时长(如9秒541毫秒)格式化为9.54(或补零的09.54),且支持毫秒四舍五入,可按以下方式实现:
实现自定义FormatStyle
通过自定义结构体遵循FormatStyle协议,控制时长的格式化逻辑:
struct SecondsDecimalFormatStyle: FormatStyle { typealias FormatInput = Duration typealias FormatOutput = String // 控制秒数整数部分的最小位数,设为2时会补零(如09.54) var minimumIntegerDigits: Int = 1 func format(_ value: Duration) -> String { // 将Duration转换为总秒数(保留小数精度) let totalNanoseconds = value.components.nanoseconds let totalSeconds = Double(totalNanoseconds) / 1_000_000_000 // 四舍五入到两位小数,避免截断毫秒 let roundedSeconds = (totalSeconds * 100).rounded() / 100 // 拆分整数和小数部分,格式化输出 let integerPart = Int(roundedSeconds) let fractionalPart = Int((roundedSeconds.truncatingRemainder(dividingBy: 1)) * 100) let formatPattern = "%0\(minimumIntegerDigits)d.%02d" return String(format: formatPattern, integerPart, fractionalPart) } } // 给Duration扩展便捷调用方法 extension Duration { func formatted(with style: SecondsDecimalFormatStyle) -> String { style.format(self) } }
使用示例
// 9秒541毫秒 → 四舍五入为9.54 let shortDuration1 = Duration.seconds(9) + Duration.milliseconds(541) print(shortDuration1.formatted(with: SecondsDecimalFormatStyle())) // 输出: 9.54 print(shortDuration1.formatted(with: SecondsDecimalFormatStyle(minimumIntegerDigits: 2))) // 输出: 09.54 // 9秒547毫秒 → 四舍五入为9.55 let shortDuration2 = Duration.seconds(9) + Duration.milliseconds(547) print(shortDuration2.formatted(with: SecondsDecimalFormatStyle())) // 输出: 9.55 // 超过一分钟的时长也能处理:2分30秒547毫秒 → 150.55 let longDuration = Duration.minutes(2) + Duration.seconds(30.547) print(longDuration.formatted(with: SecondsDecimalFormatStyle())) // 输出: 150.55
关键逻辑说明
- 精度处理:通过纳秒数转换为秒的Double值,保证计算精度,避免整数除法丢失小数部分。
- 四舍五入:通过
(totalSeconds * 100).rounded() / 100实现两位小数的四舍五入,替代默认的截断行为。 - 补零控制:通过
minimumIntegerDigits参数灵活控制秒数整数部分的显示位数,满足不同场景的格式需求。
内容的提问来源于stack exchange,提问作者Brian
相关产品推荐
相关产品推荐

