web-dev-qa-db-ja.com

Swiftで日付をミリ秒に戻し、日付に戻す

現在の時間を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 ) )!
        }
    }

//タイムスタンプは正しいが、返される日付は正しくない

36
user1079052

なぜあなたが文字列で何かをしているのか分かりません...

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)
124
Travis Griggs

@Travis Solutionは機能しますが、場合によっては

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

Int定義について

32ビットプラットフォームでは、IntはInt32と同じサイズであり、64ビットプラットフォームでは、IntはInt64と同じサイズです。

通常、32ビット環境で実行されるiPhone 5でこの問題が発生します。新しいデバイスは64ビット環境を実行します。 IntInt64になります。

同じ問題を抱えている人にも役立つことを願っています

35

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

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

文字列およびそれらすべてのランダム!を介して、一見役に立たない変換を削除しました。

9
user28434
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)
3
MAhipal Singh

@Prashant Tukadiyaの回答は動作します。ただし、UserDefaultsに値を保存してから他の日付と比較したい場合は、int64が切り捨てられて問題が発生する可能性があります。私は解決策を見つけました。

スウィフト4:

UserDefaultsに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
}

これが同じ問題を抱えている人を助けることを願っています

0
Victor Pacheo

変換後の日付を比較する場合は注意してください!

たとえば、TimeInterval(366144731.91.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でアセットを取得しようとしましたが、アセットが見つからないため、数字が同じではないことがわかります。

Round(interval * 1000)/ 1000などのdoubleの小数精度を下げるために複数のソリューションを試しましたが、NSDecimalNumberなどを使用しましたが、成功しませんでした。

CreationDate == Intervalではなく、interval -1 <creationDate <interval + 1でフェッチしました。

より良い解決策があるかもしれません!?

0
Rodrigo Fava