Swift中Firebase存储时间戳显示相同却比较不相等?
问题原因与解决方案
你的猜测完全正确!问题根源就是时间戳的精度差异——具体来说是Swift中时间值的精度和Firebase Storage返回的时间戳精度不匹配导致的。
详细原因
- Swift里的
Date类型本质是基于TimeInterval(一个Double浮点数),它理论上可以精确到纳秒级别,但实际存储和传输时,浮点数的精度特性可能会带来微小的误差。 - Firebase Storage返回的文件修改时间,一般只精确到毫秒(也就是纪元时间小数点后3位);而你本地手动设置文件属性时生成的
Date,可能包含了更高的精度(比如微秒,小数点后6位),或者两者在小数点后第6位及之后的数值存在差异。直接用!=比较Date对象时,这些微乎其微的精度差会被判定为“不相等”。 - 至于转成
String(describing:)后比较结果正确,是因为这个方法生成的字符串默认会截断过高的精度(通常只显示到秒或毫秒),相当于间接做了精度统一,所以看起来“匹配”的时间会被判定为相等。另外你打印时看到的日期匹配,也是因为默认的日期输出只展示到秒级,隐藏了微秒/纳秒的差异。
解决方案
不要直接比较Date对象,而是对两个时间做精度截断后再比较,这里提供两种常用方法:
方法1:基于时间戳截断到指定精度
比如统一截断到毫秒级(和Firebase返回的精度对齐):
func truncatedToMilliseconds(_ date: Date) -> TimeInterval { let millisecondValue = floor(date.timeIntervalSince1970 * 1000) return millisecondValue / 1000 } // 使用示例 if truncatedToMilliseconds(localModDate) != truncatedToMilliseconds(serverModDate) { // 重新下载文件 }
如果只需要精确到秒,把1000改成1即可。
方法2:用Calendar按时间粒度比较
这种方法更语义化,适合需要按特定时间单位(比如秒、分钟)比较的场景:
let calendar = Calendar.current // 只比较到秒级,忽略更小的时间单位 if !calendar.isDate(localModDate, equalTo: serverModDate, toGranularity: .second) { // 重新下载文件 }
你可以根据需求把.second换成.millisecond、.minute等粒度。
内容的提问来源于stack exchange,提问作者Rob.R
相关产品推荐
相关产品推荐

