web-dev-qa-db-fra.com

Date en millisecondes et retour à ce jour dans Swift

Je prends l'heure actuelle, en UTC, et le mets en nanaosecondes, puis je dois prendre les nanosecondes et revenir à une date en heure locale. Je peux obtenir le temps en nanosecondes, puis revenir à une chaîne de date, mais le temps devient compliqué lorsque je passe d’une chaîne à une date.

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

// L'horodatage est correct mais la date renvoyée n'est pas

28
user1079052

Je ne comprends pas pourquoi tu fais quoi que ce soit avec des ficelles ...

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

Comme @Travis Solution fonctionne, mais dans certains cas 

var millisecondsSince1970:IntCAUSERA UNE APPLICATION D'AVERTISSEMENT D'AVERTISSEMENT

avec erreur

La valeur double ne peut pas être convertie en Int car le résultat serait supérieur à Int.max s'il se produisait Veuillez mettre à jour votre réponse avec Int64 

Voici la réponse mise à jour 

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

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

J'espère que c'est utile pour quelqu'un qui a aussi le même problème 


À propos des définitions Int.

Sur les plates-formes 32 bits, Int a la même taille que Int32 et sur les plates-formes 64 bits, Int a la même taille que Int64.

Généralement, je rencontre ce problème dans iPhone 5, qui s'exécute en env. 32 bits. Les nouveaux appareils fonctionnent maintenant avec env. 64 bits. Leur Int sera Int64.

27
Prashant Tukadiya

La solution @Travis est correcte, mais elle perd des millisecondes lorsqu’une date est générée. J'ai ajouté une ligne pour inclure les millisecondes dans la date:

Si vous n'avez pas besoin de cette précision, utilisez la solution Travis car elle sera plus rapide.

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

}
8
J.S.R - Silicornio
//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)
    }
}

J'ai enlevé la conversion apparemment inutile via une chaîne et tous ces ! aléatoires.

7
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)
2
MAhipal Singh

@Pashant Tukadiya répondre fonctionne. Mais si vous souhaitez enregistrer la valeur dans UserDefaults, puis la comparer à une autre date, vous obtiendrez votre image int64 tronquée, ce qui pourrait poser problème. J'ai trouvé une solution.

Swift 4:

Vous pouvez enregistrer int64 en tant que chaîne dans UserDefaults:

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

Ainsi, vous évitez la troncature internationale.

Et puis vous pouvez récupérer la valeur d'origine:

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

Cela vous permet de le comparer avec d'autres valeurs de date:

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

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

J'espère que cela aide quelqu'un qui a le même problème

0
Victor Pacheo

Faites attention si vous comparez les dates après la conversion!

Par exemple, j'ai eu l'actif du simulateur avec la date TimeInterval (366144731.9), convertie en millisecondes Int64 (1344451931900) et de nouveau en TimeInterval (366144731.9000001), avec 

func convertToMilli(timeIntervalSince1970: TimeInterval) -> Int64 {
    return Int64(timeIntervalSince1970 * 1000)
}

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

J'ai essayé de récupérer l'actif par creationDate et il ne trouve pas l'actif, comme vous pouvez l'imaginer, les chiffres ne sont pas les mêmes.

J'ai essayé plusieurs solutions pour réduire la précision décimale de double, comme round (intervalle * 1000)/1000, utiliser NSDecimalNumber, etc. sans succès.

J'ai fini par aller chercher par intervalle -1 <creationDate <intervalle + 1, au lieu de creationDate == Interval.

Il y a peut-être une meilleure solution !?

0
Rodrigo Fava