Mac下stat与Objective-C获取文件创建时间戳不一致及跨设备疑问
先直接回应你的核心疑问:macOS的文件系统创建时间(Birth Time)确实是存储在文件元数据中的绝对值,在使用保留元数据的方式复制(比如Finder拖拽、cp -p、rsync -a)时,跨设备复制通常能保持不变。但你遇到的2秒差异,大概率是两个问题:要么你对stat输出字段的对应关系判断有误,要么你用WMMediaAsset获取的不是文件系统的创建时间,而是媒体内容本身的创建时间(比如拍摄时间)。
下面是具体的排查方向:
1. 先确认stat输出的创建时间是否准确
你用stat -t "%s" filename得到的输出字段顺序容易混淆,建议用更直观的命令查看文件时间戳:
stat -x filename
这个命令会输出带字段名的结果,比如:
Birth: 2019-09-01 12:00:29 UTC
直接核对Birth字段的时间,确保你之前从stat -t输出中挑的是正确的创建时间戳,避免因字段数错导致的误解。
另外,也可以用stat -f "%B" filename直接输出创建时间的epoch秒数(支持小数精度),和后续Objective-C获取的精确值对比。
2. 区分「文件系统创建时间」和「媒体内容创建时间」
你用((WMMediaAsset *)section.assets[index]).creationDate获取的时间,大概率不是文件系统层面的创建时间:
WMMediaAsset看起来是媒体资产相关的类(比如照片、视频库中的资源),它的creationDate通常对应媒体内容的创建时间(比如照片的拍摄时间、视频的录制时间,存储在文件的EXIF/QuickTime元数据中),而非文件被写入磁盘的时间。
如果要获取文件系统的创建时间,应该直接通过文件URL获取系统元数据,用以下Objective-C代码:
NSString *filePath = @"/path/to/your/file"; NSURL *fileURL = [NSURL fileURLWithPath:filePath]; NSDate *fileCreationDate; NSError *error = nil; BOOL success = [fileURL getResourceValue:&fileCreationDate forKey:NSURLCreationDateKey error:&error]; if (success) { NSString *timestamp = [NSString stringWithFormat:@"%lld", (long long)[fileCreationDate timeIntervalSince1970]]; NSLog(@"文件系统创建时间戳:%@", timestamp); } else { NSLog(@"获取创建时间失败:%@", error.localizedDescription); }
用这段代码获取的时间,再和stat输出的创建时间对比,应该能对齐。
3. 检查文件复制/迁移的方式是否保留元数据
如果你的文件是从其他设备复制过来的,要确认复制方式是否保留了文件元数据:
- 默认的Finder复制、
cp -p、rsync -a会保留创建时间; - 如果用不带参数的
cp或者某些第三方同步工具,可能会将创建时间替换为复制时的系统时间; - 跨文件系统迁移(比如从HFS+到APFS,或者外部FAT32磁盘),部分文件系统不支持存储创建时间,会导致时间被修改。
4. 排查时间戳的精度与取整问题
macOS的APFS文件系统支持纳秒级的时间戳,而stat -t "%s"输出的是截断到秒的整数(比如实际时间是1567413629.9秒,会被截断为1567413629),而NSDate的timeIntervalSince1970返回的是带小数的精确值,当你用%lld格式化时会做四舍五入,可能导致1秒的差异——不过你的情况是2秒,这个可能性较低,但可以通过输出精确的时间值(比如保留小数)来排查:
NSLog(@"精确时间间隔:%f", [fileCreationDate timeIntervalSince1970]);
5. 排除系统时钟调整的影响
如果你的Mac系统时钟曾被手动调整过,或者通过NTP同步过,理论上不会影响已存储的文件时间戳,但可以检查系统当前时间是否正常,避免因时钟偏差导致的误解。
内容的提问来源于stack exchange,提问作者lukeaxu




