iOS DateComponentsFormatter - 获取使用的单位
iOS DateComponentsFormatter - get used units
我想将时间从秒转换为位置格式,例如 2:05 min 或 1:23 h 或 19秒。我在检索本地化时间缩写单位时遇到问题。这是我的代码。
let secs: Double = 3801
let stopWatchFormatter = DateComponentsFormatter()
stopWatchFormatter.unitsStyle = .positional
stopWatchFormatter.maximumUnitCount = 2
stopWatchFormatter.allowedUnits = [.hour, .minute, .second]
print(stopWatchFormatter.string(from: secs)) // 1:03
stopWatchFormatter.unitsStyle = .short
print(stopWatchFormatter.string(from: secs)) // 1 hr, 3 min
如您所见,3801 秒被格式化为 1:03,这很好,但我不知道 DateComponentsFormatter
是否使用小时或分钟等。
我可能会使用简单的 MOD 逻辑来检查它,但接下来是本地化的困难部分。另请注意,如果我将 collapsesLargestUnit
设置为 false
,MOD 解决方案将毫无价值。
据我所知,您不需要字符串,但需要 DateComponent:
let dateA = Date(timeIntervalSince1970: 0)
let dateB = Date(timeIntervalSince1970: timeInterval)
let components = Calendar.current.dateComponents([.hour, .minute, .second], from: dateA, to: dateB)
DateComponentsFormatter
不直接支持您想要的格式,本质上是位置格式,但短格式的第一个单元显示在末尾。
以下辅助函数将这两个单独的结果组合成您想要的结果。这应该适用于任何语言环境,但需要进行彻底的测试以确认这一点。
func formatStopWatchTime(seconds: Double) -> String {
let stopWatchFormatter = DateComponentsFormatter()
stopWatchFormatter.unitsStyle = .positional
stopWatchFormatter.maximumUnitCount = 2
stopWatchFormatter.allowedUnits = [.hour, .minute, .second]
var pos = stopWatchFormatter.string(from: seconds)!
// Work around a bug where some values return 3 units despite only requesting 2 units
let parts = pos.components(separatedBy: CharacterSet.decimalDigits.inverted)
if parts.count > 2 {
let seps = pos.components(separatedBy: .decimalDigits).filter { ![=10=].isEmpty }
pos = parts[0..<2].joined(separator: seps[0])
}
stopWatchFormatter.maximumUnitCount = 1
stopWatchFormatter.unitsStyle = .short
let unit = stopWatchFormatter.string(from: seconds)!
// Replace the digits in the unit result with the pos result
let res = unit.replacingOccurrences(of: "[\d]+", with: pos, options: [.regularExpression])
return res
}
print(formatStopWatchTime(seconds: 3801))
输出:
1:03 hr
我想将时间从秒转换为位置格式,例如 2:05 min 或 1:23 h 或 19秒。我在检索本地化时间缩写单位时遇到问题。这是我的代码。
let secs: Double = 3801
let stopWatchFormatter = DateComponentsFormatter()
stopWatchFormatter.unitsStyle = .positional
stopWatchFormatter.maximumUnitCount = 2
stopWatchFormatter.allowedUnits = [.hour, .minute, .second]
print(stopWatchFormatter.string(from: secs)) // 1:03
stopWatchFormatter.unitsStyle = .short
print(stopWatchFormatter.string(from: secs)) // 1 hr, 3 min
如您所见,3801 秒被格式化为 1:03,这很好,但我不知道 DateComponentsFormatter
是否使用小时或分钟等。
我可能会使用简单的 MOD 逻辑来检查它,但接下来是本地化的困难部分。另请注意,如果我将 collapsesLargestUnit
设置为 false
,MOD 解决方案将毫无价值。
据我所知,您不需要字符串,但需要 DateComponent:
let dateA = Date(timeIntervalSince1970: 0)
let dateB = Date(timeIntervalSince1970: timeInterval)
let components = Calendar.current.dateComponents([.hour, .minute, .second], from: dateA, to: dateB)
DateComponentsFormatter
不直接支持您想要的格式,本质上是位置格式,但短格式的第一个单元显示在末尾。
以下辅助函数将这两个单独的结果组合成您想要的结果。这应该适用于任何语言环境,但需要进行彻底的测试以确认这一点。
func formatStopWatchTime(seconds: Double) -> String {
let stopWatchFormatter = DateComponentsFormatter()
stopWatchFormatter.unitsStyle = .positional
stopWatchFormatter.maximumUnitCount = 2
stopWatchFormatter.allowedUnits = [.hour, .minute, .second]
var pos = stopWatchFormatter.string(from: seconds)!
// Work around a bug where some values return 3 units despite only requesting 2 units
let parts = pos.components(separatedBy: CharacterSet.decimalDigits.inverted)
if parts.count > 2 {
let seps = pos.components(separatedBy: .decimalDigits).filter { ![=10=].isEmpty }
pos = parts[0..<2].joined(separator: seps[0])
}
stopWatchFormatter.maximumUnitCount = 1
stopWatchFormatter.unitsStyle = .short
let unit = stopWatchFormatter.string(from: seconds)!
// Replace the digits in the unit result with the pos result
let res = unit.replacingOccurrences(of: "[\d]+", with: pos, options: [.regularExpression])
return res
}
print(formatStopWatchTime(seconds: 3801))
输出:
1:03 hr