ios 日期到毫秒并在 Swift 中返回到日期

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40134323/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 10:37:19  来源:igfitidea点击:

Date to milliseconds and back to date in Swift

iosswiftdatetime

提问by user1079052

I am taking the current time, in UTC, and putting it in nanaoseconds and then I need to take the nanoseconds and go back to a date in local time. I am able to do get the time to nanoseconds and then back to a date string but the time gets convoluted when I go from a string to date.

我正在使用 UTC 中的当前时间,并将其设置为纳秒,然后我需要使用纳秒并返回到本地时间的日期。我能够将时间设置为纳秒,然后返回到日期字符串,但是当我从字符串转到日期时,时间会变得很复杂。

    //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 ) )!
        }
    }

//The timestamp is correct but the date returned isn't

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

回答by Travis Griggs

I don't understand why you're doing anything with strings...

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

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

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


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

回答by Prashant Tukadiya

As @Travis Solution works but in some cases

由于@Travis 解决方案有效,但在某些情况下

var millisecondsSince1970:IntWILL CAUSE CRASH APPLICATION,

var millisecondsSince1970:Int会导致应用程序崩溃

with error

有错误

Double value cannot be converted to Int because the result would be greater than Int.max if it occurs Please update your answer with Int64

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

Here is Updated Answer

这是更新的答案

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.

关于 Int 定义。

On 32-bit platforms, Int is the same size as Int32, and on 64-bit platforms, Int is the same size as Int64.

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

Generally, I encounter this problem in iPhone 5, which runs in 32-bit env. New devices run 64-bit env now. Their Intwill be Int64.

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

Hope it is helpful to someone who also has same problem

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

回答by J.S.R - Silicornio

@Travis solution is right, but it loses milliseconds when a Date is generated. I have added a line to include the milliseconds into the date:

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

If you don't need this precision, use the Travis solution because it will be faster.

如果您不需要这种精度,请使用 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 ))
    }

}

回答by user28434

//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)
    }
}

I removed seemingly useless conversion via string and all those random !.

我通过 string 和所有这些 random 删除了看似无用的转换!

回答by MAhipal Singh

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)

回答by Victor Pacheo

@Prashant Tukadiya answer works. But if you want to save the value in UserDefaults and then compare it to other date you get yout int64 truncated so it can cause problems. I found a solution.

@Prashant Tukadiya 答案有效。但是,如果您想将值保存在 UserDefaults 中,然后将其与其他日期进行比较,则会将 int64 截断,因此可能会导致问题。我找到了解决方案。

Swift 4:

斯威夫特 4:

You can save int64 as string in UserDefaults:

您可以在 UserDefaults 中将 int64 保存为字符串:

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

Like that you avoid Int truncation.

这样你就避免了 Int 截断。

And then you can recover the original value:

然后你可以恢复原始值:

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

This allow you to compare it with other date values:

这允许您将其与其他日期值进行比较:

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

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

Hope this helps someone who has same problem

希望这可以帮助有同样问题的人

回答by Rodrigo Fava

Watch out if you are going to compare dates after the conversion!

如果您要在转换后比较日期,请注意!

For instance, I got simulator's asset with date as TimeInterval(366144731.9), converted to milliseconds Int64(1344451931900) and back to TimeInterval(366144731.9000001), using

例如,我得到了模拟器的资产,日期为 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))
}

I tried to fetch the asset by creationDate and it doesn't find the asset, as you could figure, the numbers are not the same.

我试图通过 creationDate 获取资产,但没有找到资产,正如您所想象的,数字不一样。

I tried multiple solutions to reduce double's decimal precision, like round(interval*1000)/1000, use NSDecimalNumber, etc... with no success.

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

I ended up fetching by interval -1 < creationDate < interval + 1, instead of creationDate == Interval.

我最终通过时间间隔 -1 < creationDate < 时间间隔 + 1,而不是创建日期 == 时间间隔来获取。

There may be a better solution!?

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