繁体   English   中英

Swift:具有 timeIntervalSince1970 的精度

[英]Swift: Precision with timeIntervalSince1970

当我将 Unix 纪元时间转换为毫秒时,它变得四舍五入。

代码:

import Foundation

extension Date {
    public func getMilliSeconds()-> TimeInterval {
        return TimeInterval(self.timeIntervalSince1970)
    }
}

let epochTime: TimeInterval = 1597269862.9328
print("\(epochTime) Precise Epoch Time /// (notice the 8 is the last digit)")

let convertedTime = Date(timeIntervalSince1970: epochTime)
print("\(convertedTime) Time converted To Swift Date")

let df = DateFormatter()
df.dateFormat = "y-MM-dd H:m:ss.SSSS"
let withMilli = df.string(from: convertedTime)
print("\(withMilli) Time with milliseconds using Date Formatter /// (notice 8 is missing and this was rounded to .9330")

if let convertedBackToEpochTime = df.date(from: withMilli) {
    print("\(convertedBackToEpochTime.getMilliSeconds()) Time converted back to Unix epoch time")
}

日志:

1597269862.9328 Precise Epoch Time /// (notice the 8 is the last digit)
2020-08-12 22:04:22 +0000 Time converted To Swift Date
2020-08-12 15:4:22.9330 Time with milliseconds using Date Formatter /// (notice 8 is missing and this was rounded to .9330
1597269862.933 Time converted back to Unix epoch time

我开始与1597269862.9328和止带1597269862.933 我怎样才能让日期回到我开始的时候: 1597269862.9328

Date 的所有组件(年、月、日、小时、分钟、秒等)都是整数。 毫秒,顾名思义,只能精确到千分之一秒(即:3 个十进制数字)。

您想要获得的是nanosecond属性。 这是使用 Swift 5.0 中添加的自定义插值功能的示例:

import Foundation

extension String.StringInterpolation {
    /// Our custom interpolator for Date
    mutating func appendInterpolation(custom date: Date) {
        let components: Set<Calendar.Component> = [
            .year, .month, .day, .hour, .minute, .second, .nanosecond, .timeZone
        ]
        let values = Calendar.current.dateComponents(components, from: date)
        appendLiteral(values.description)
    }
}

let epochTime: TimeInterval = 1597269862.9328
print("\(epochTime) Precise Epoch Time (notice the 8 is the last digit)")

let convertedTime = Date(timeIntervalSince1970: epochTime)
print("\(custom: convertedTime)")

结果:

1597269862.9328 Precise Epoch Time (notice the 8 is the last digit)
timeZone: America/Toronto (current) year: 2020 month: 8 day: 12 hour: 18 minute: 4 second: 22 nanosecond: 932800054 isLeapMonth: false

注意nanosecond: 932800054 该值与原始输入的差异是由于浮点精度造成的,这是不可避免的。

问题在于DateFormatter仅限于毫秒。 使用它无法显示超过 3 个小数位数。

extension Formatter {
    static let iso8601withFractionalSeconds: DateFormatter = {
        let formatter = DateFormatter()
        formatter.calendar = Calendar(identifier: .iso8601)
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.timeZone = TimeZone(secondsFromGMT: 0)
        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSSXXXXX"
        return formatter
    }()
}

Formatter.iso8601withFractionalSeconds.string(from: Date())  // "2020-10-29T16:12:27.111000000Z"

如果您想取回初始值,您只需要 top 从您的 ConvertTime 日期获取 timeIntervalSince1970 :

let epochTime: TimeInterval = 1597269862.9328
print("\(epochTime) Precise Epoch Time")

let convertedTime = Date(timeIntervalSince1970: epochTime)
print("\(convertedTime) Time converted To Swift Date")

print(convertedTime.timeIntervalSince1970)   // "1597269862.9328\n"

请注意,Swift Date存储为自参考日期以来的时间间隔。 如果您想保留日期准确性,您应该在存档时使用 timeIntervalSinceReferenceDate 而不是 timeIntervalSince1970。 检查这个帖子

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM