Swift中的日期到毫秒和更新

时间:2016-10-19 14:29:30

标签: ios swift date time

我正在以UTC为单位拍摄当前时间,然后将其置于nanaoseconds,然后我需要花费纳秒并回到当地时间的某个日期。我能够把时间缩短到纳秒,然后回到日期字符串,但是当我从字符串到日期时,时间会变得复杂。

    //Date to milliseconds
     func currentTimeInMiliseconds() -> Int! {
            let currentDate = NSDate()
            let dateFormatter = DateFormatter()
            dateFormatter.dateFormat = format
            dateFormatter.timeZone = NSTimeZone(name: "UTC") as TimeZone!
            let date = dateFormatter.date(from: dateFormatter.string(from: currentDate as Date))
            let nowDouble = date!.timeIntervalSince1970
            return Int(nowDouble*1000)
        }

    //Milliseconds to date
    extension Int {
        func dateFromMilliseconds(format:String) -> Date {
            let date : NSDate! = NSDate(timeIntervalSince1970:Double(self) / 1000.0)
            let dateFormatter = DateFormatter()
            dateFormatter.dateFormat = format
            dateFormatter.timeZone = TimeZone.current
            let timeStamp = dateFormatter.string(from: date as Date)

let formatter = DateFormatter()
            formatter.dateFormat = format
            return ( formatter.date( from: timeStamp ) )!
        }
    }

//时间戳是正确的,但返回的日期不是

10 个答案:

答案 0 :(得分:110)

我不明白为什么你要用字符串做任何事情......

extension Date {
    var millisecondsSince1970:Int {
        return Int((self.timeIntervalSince1970 * 1000.0).rounded())
    }

    init(milliseconds:Int) {
        self = Date(timeIntervalSince1970: TimeInterval(milliseconds) / 1000)
    }
}


Date().millisecondsSince1970 // 1476889390939
Date(milliseconds: 0) // "Dec 31, 1969, 4:00 PM" (PDT variant of 1970 UTC)

答案 1 :(得分:33)

正如@Travis解决方案有效但在某些情况下

var millisecondsSince1970:Int 会导致崩溃申请

有错误

  

Double值无法转换为Int,因为如果出现,结果将大于Int.max 请使用Int64更新您的答案

这是更新的答案

extension Date {
 var millisecondsSince1970:Int64 {
        return Int64((self.timeIntervalSince1970 * 1000.0).rounded()) 
        //RESOLVED CRASH HERE
    }

    init(milliseconds:Int) {
        self = Date(timeIntervalSince1970: TimeInterval(milliseconds / 1000))
    }
}

希望对有同样问题的人有帮助

About Int definitions.

  

在32位平台上,Int与Int32的大小相同,在64位平台上,Int与Int64的大小相同。

通常,我在iPhone 5中遇到此问题,该问题以32位环境运行。新设备现在运行64位环境。他们的Int将为Int64

答案 2 :(得分:9)

@Travis解决方案是正确的,但是在生成Date时会丢失毫秒。我添加了一行以包含日期中的毫秒数:

如果您不需要这种精确度,请使用Travis解决方案,因为它会更快。

extension Date {

    func toMillis() -> Int64! {
        return Int64(self.timeIntervalSince1970 * 1000)
    }

    init(millis: Int64) {
        self = Date(timeIntervalSince1970: TimeInterval(millis / 1000))
        self.addTimeInterval(TimeInterval(Double(millis % 1000) / 1000 ))
    }

}

答案 3 :(得分:8)

//Date to milliseconds
func currentTimeInMiliseconds() -> Int {
    let currentDate = Date()
    let since1970 = currentDate.timeIntervalSince1970
    return Int(since1970 * 1000)
}

//Milliseconds to date
extension Int {
    func dateFromMilliseconds() -> Date {
        return Date(timeIntervalSince1970: TimeInterval(self)/1000)
    }
}

我通过字符串和所有随机!删除了看似无用的转换。

答案 4 :(得分:3)

let dateTimeStamp = NSDate(timeIntervalSince1970:Double(currentTimeInMiliseconds())/1000)  //UTC time  //YOUR currentTimeInMiliseconds METHOD
let dateFormatter = NSDateFormatter()
dateFormatter.timeZone = NSTimeZone.localTimeZone() 
dateFormatter.dateFormat = "yyyy-MM-dd"
dateFormatter.dateStyle = NSDateFormatterStyle.FullStyle
dateFormatter.timeStyle = NSDateFormatterStyle.ShortStyle


let strDateSelect = dateFormatter.stringFromDate(dateTimeStamp)
print("Local Time", strDateSelect) //Local time


let dateFormatter2 = NSDateFormatter()
dateFormatter2.timeZone = NSTimeZone(name: "UTC") as NSTimeZone!
dateFormatter2.dateFormat = "yyyy-MM-dd"

let date3 = dateFormatter.dateFromString(strDateSelect)
print("DATE",date3)

答案 5 :(得分:1)

在Swift 5 / iOS 13中有一个简单的解决方案。

extension Date {
    
    func toMilliseconds() -> Int64 {
        Int64(self.timeIntervalSince1970 * 1000)
    }

    init(milliseconds:Int) {
        self = Date().advanced(by: TimeInterval(integerLiteral: Int64(milliseconds / 1000)))
    }
}

但是,这假设您已经计算了UTF时间与本地时间之间的时差,并以毫秒为单位进行了调整和说明。为此,请看日历

var cal = Calendar.current
cal.timeZone = TimeZone(abbreviation: "UTC")!
let difference = cal.compare(dateGiven, to: date, toGranularity: .nanosecond)

答案 6 :(得分:0)

当心您要在转换后比较日期!

例如,我使用

将日期为TimeInterval(366144731.9)的模拟器的资产转换为毫秒Int64(1344451931900),然后又转换回TimeInterval(366144731.9000001)
func convertToMilli(timeIntervalSince1970: TimeInterval) -> Int64 {
    return Int64(timeIntervalSince1970 * 1000)
}

func convertMilliToDate(milliseconds: Int64) -> Date {
    return Date(timeIntervalSince1970: (TimeInterval(milliseconds) / 1000))
}

我试图通过creationDate来获取资产,但找不到资产,正如您所看到的那样,数字并不相同。

我尝试了多种解决方案来降低double的十进制精度,例如round(interval * 1000)/ 1000,使用NSDecimalNumber等,但没有成功。

我最终以间隔-1

可能有更好的解决方案!?

答案 7 :(得分:0)

@Prashant Tukadiya回答作品。但是,如果要将值保存在UserDefaults中,然后将其与其他日期进行比较,则会将int64截断,这样可能会引起问题。我找到了解决方法。

迅速4:

您可以在用户默认设置中将int64另存为字符串:

let value: String(Date().millisecondsSince1970)
let stringValue = String(value)
UserDefaults.standard.set(stringValue, forKey: "int64String")

就像避免Int截断一样。

然后您可以恢复原始值:

let int64String = UserDefaults.standard.string(forKey: "int64String")
let originalValue = Int64(int64String!)

这使您可以将其与其他日期值进行比较:

let currentTime = Date().millisecondsSince1970
let int64String = UserDefaults.standard.string(forKey: "int64String")
let originalValue = Int64(int64String!) ?? 0 

if currentTime < originalValue {
     return false
} else {
     return true
}

希望这可以帮助遇到相同问题的人

答案 8 :(得分:0)

除非绝对必须将日期转换为整数,否则请考虑使用Double来表示时间间隔。毕竟,这是timeIntervalSince1970返回的类型。转换为整数的所有答案都失去了亚毫秒级的精度,但是这种解决方案更加精确(尽管由于浮点不精确度,您仍然会失去一些精度)。

public extension Date {
    
    /// The interval, in milliseconds, between the date value and
    /// 00:00:00 UTC on 1 January 1970.
    /// Equivalent to `self.timeIntervalSince1970 * 1000`.
    var millisecondsSince1970: Double {
        return self.timeIntervalSince1970 * 1000
    }

    /**
     Creates a date value initialized relative to 00:00:00 UTC
     on 1 January 1970 by a given number of **milliseconds**.
     
     equivalent to
     ```
     self.init(timeIntervalSince1970: TimeInterval(milliseconds) / 1000)
     ```
     - Parameter millisecondsSince1970: A time interval in milliseconds.
     */
    init(millisecondsSince1970: Double) {
        self.init(timeIntervalSince1970: TimeInterval(milliseconds) / 1000)
    }

}

答案 9 :(得分:0)

UInt64 中获取时间令牌的简单一行代码

让时间 = UInt64(Date().timeIntervalSince1970 * 1000)

print(time) <----- 在 UInt64 中打印时间

额外提示:

对于自 1970 年以来 API 调用的 10 位毫秒的时间戳然后

让 timeStamp = Date().timeIntervalSince1970

print(timeStamp) <-- 打印当前时间戳