我在Swift中使用以下DateComponentsFormatter:
function filter_bins(source_group, f) {
return {
all:function () {
return source_group.all().filter(function(d) {
return f(d.value);
});
}
};
}
var filtered_years_group = filter_bins(FTEMonthGroup, function(d) {
return !yearsHiddenArray.includes(d.Year);
}
heatMap.group(filtered_years_group);
这将产生类似于2:41(2分钟41秒)和08(8秒)的结果。但是,我想在Minutes位置至少保留一位数字,返回0:08而不是08。DateComponentsFormatter是否可能?我希望有一个返回本地化结果的解决方案。
答案 0 :(得分:1)
是的。在设置日期组件格式化程序允许的单位时,可以很容易地完成基于时间间隔的三元条件添加操作:
extension Formatter {
static let positional: DateComponentsFormatter = {
let positional = DateComponentsFormatter()
positional.unitsStyle = .positional
positional.zeroFormattingBehavior = .pad
return positional
}()
}
extension TimeInterval {
var positionalTime: String {
Formatter.positional.allowedUnits = self >= 3600 ?
[.hour, .minute, .second] :
[.minute, .second]
return Formatter.positional.string(from: self)!
}
}
用法
8.0.positionalTime // "0:08"
161.0.positionalTime // "2:41"
3600.0.positionalTime // "1:00:00"
答案 1 :(得分:0)
签出一个不同的zeroFormattingBehavior属性值。我用它来获得我认为您正在寻找的结果,但是可以根据需要进行实验...
formatter.zeroFormattingBehavior = [.pad]
答案 2 :(得分:0)
可以根据持续时间修改allowedUnits
和zeroFormattingBehavior
来创建合适的位置时间字符串。请注意,如果希望只有一个,那么它将在几分钟内填充两个前导零,以便事后以安全的方式进行处理。
let formatter = DateComponentsFormatter()
if duration < 60 {
formatter.allowedUnits = [.minute, .second]
formatter.zeroFormattingBehavior = .pad //pad seconds and minutes ie 00:05
} else if duration >= 60*60 {
formatter.allowedUnits = [.hour, .minute, .second]
}
var formattedDuration = formatter.string(from: duration) ?? "0"
if formattedDuration.hasPrefix("00") {
formattedDuration = String(formattedDuration.dropFirst()) //remove leading 0 ie 0:05
}
以下是duration
和formattedDuration
的列表:
0 ▶️ 0:00
5 ▶️ 0:05
30 ▶️ 0:30
60 ▶️ 1:00
65 ▶️ 1:05
3600 ▶️ 1:00:00
3665 ▶️ 1:00:05
3660 ▶️ 1:01:00
替代解决方案
您可以通过使用.dropTrailing
zeroFormattingBehavior
获得相同的结果,而无需检查两个前导零,这很有趣。我会警告,我不完全了解为什么会这样做,也不知道它可能会对本地化产生什么影响。请注意,如果duration为0
,则结果为"0"
,因此在这种情况下,我们可以使用.pad
来获得"00:00"
的结果。这样一来,您最终会遇到上述相同的情况,但也许您会觉得这是一个不需要处理的极端情况。
let formatter = DateComponentsFormatter()
if duration >= 60 {
formatter.allowedUnits = [.hour, .minute, .second]
formatter.zeroFormattingBehavior = .default
} else if duration == 0 {
formatter.allowedUnits = [.minute, .second]
formatter.zeroFormattingBehavior = .pad
//is 00:00 but should be 0:00
} else {
formatter.allowedUnits = [.minute, .second]
formatter.zeroFormattingBehavior = .dropTrailing //magic here
}
let formattedDuration = formatter.string(from: duration) ?? "0"
答案 3 :(得分:0)
想出了这个解决方案,使用了一个正则表达式,似乎涵盖了所有情况:
let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.hour, .minute, .second]
formatter.unitsStyle = .positional
formatter.zeroFormattingBehavior = .pad
func durationString(for duration: TimeInterval) -> String {
formatter.string(from: duration)!
.replacingOccurrences(of: #"^00[:.]0?|^0"#, with: "", options: .regularExpression)
}
durationString(for: 0) // 0:00
durationString(for: 1) // 0:01
durationString(for: 10) // 0:10
durationString(for: 60) // 1:00
durationString(for: 600) // 10:00
durationString(for: 3600) // 1:00:00
durationString(for: 36000) // 10:00:00