问题描述
iOS Date()
返回日期的精度至少为微秒。
我通过调用 Date()来检查此语句.timeIntervalSince1970
会导致 1490891661.074981
iOS Date()
returns date with at least microsecond precision.
I checked this statement by calling Date().timeIntervalSince1970
which results in 1490891661.074981
然后我需要将日期转换为字符串微秒精度。
我以以下方式使用 DateFormatter
:
Then I need to convert date into string with microsecond precision.
I am using DateFormatter
in following way:
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSZZZZZ"
print(formatter.string(from: date))
这会导致
2017-03 -30T16:34:21.075000Z
现在,如果我们比较两个结果:
1490891661.074981
和 2017-03-30T16:34:21.075000Z
我们可以注意到 DateFormatter
将日期四舍五入为毫秒精度,同时仍然显示零微秒。
Now if we compare two results:1490891661.074981
and "2017-03-30T16:34:21.075000Z"
we can notice that DateFormatter
rounds date to millisecond precision while still presenting zeros for microseconds.
有人知道如何配置 DateFormatter
所以我可以p微秒并获得正确结果: 2017-03-30T16:34:21.074981Z
?
Does anybody know how to configure DateFormatter
so I can keep microseconds and get correct result: "2017-03-30T16:34:21.074981Z"
?
推荐答案
感谢@MartinR解决了我的问题的上半部分,并感谢@ForestKunecke给了我解决问题的后半部分的技巧。
Thanks to @MartinR for solving first half of my problem and to @ForestKunecke for giving me tips how to solve second half of the problem.
基于他们的帮助,我创建了现成的解决方案,该解决方案可以毫秒精度将字符串中的日期转换为字符串,反之亦然:
Based on their help I created ready to use solution which converts date from string and vice versa with millisecond precision:
public final class MicrosecondPrecisionDateFormatter: DateFormatter {
private let microsecondsPrefix = "."
override public init() {
super.init()
locale = Locale(identifier: "en_US_POSIX")
timeZone = TimeZone(secondsFromGMT: 0)
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override public func string(from date: Date) -> String {
dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
let components = calendar.dateComponents(Set([Calendar.Component.nanosecond]), from: date)
let nanosecondsInMicrosecond = Double(1000)
let microseconds = lrint(Double(components.nanosecond!) / nanosecondsInMicrosecond)
// Subtract nanoseconds from date to ensure string(from: Date) doesn't attempt faulty rounding.
let updatedDate = calendar.date(byAdding: .nanosecond, value: -(components.nanosecond!), to: date)!
let dateTimeString = super.string(from: updatedDate)
let string = String(format: "%@.%06ldZ",
dateTimeString,
microseconds)
return string
}
override public func date(from string: String) -> Date? {
dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
guard let microsecondsPrefixRange = string.range(of: microsecondsPrefix) else { return nil }
let microsecondsWithTimeZoneString = String(string.suffix(from: microsecondsPrefixRange.upperBound))
let nonDigitsCharacterSet = CharacterSet.decimalDigits.inverted
guard let timeZoneRangePrefixRange = microsecondsWithTimeZoneString.rangeOfCharacter(from: nonDigitsCharacterSet) else { return nil }
let microsecondsString = String(microsecondsWithTimeZoneString.prefix(upTo: timeZoneRangePrefixRange.lowerBound))
guard let microsecondsCount = Double(microsecondsString) else { return nil }
let dateStringExludingMicroseconds = string
.replacingOccurrences(of: microsecondsString, with: "")
.replacingOccurrences(of: microsecondsPrefix, with: "")
guard let date = super.date(from: dateStringExludingMicroseconds) else { return nil }
let microsecondsInSecond = Double(1000000)
let dateWithMicroseconds = date + microsecondsCount / microsecondsInSecond
return dateWithMicroseconds
}
}
用法:
let formatter = MicrosecondPrecisionDateFormatter()
let date = Date(timeIntervalSince1970: 1490891661.074981)
let formattedString = formatter.string(from: date) // 2017-03-30T16:34:21.074981Z
这篇关于如何配置DateFormatter捕获微秒的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!