90 votes

Date en millisecondes et retour à la date en Swift

Je prends l'heure actuelle, en UTC, et je la mets en nanosecondes, puis je dois prendre les nanosecondes et revenir à une date en heure locale.

Je parviens à obtenir l'heure en nanosecondes, puis à revenir à une chaîne de date, mais l'heure devient compliquée 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 ne l'est pas.

3 votes

Quel est l'intérêt de convertir une date en chaîne de caractères et de revenir à la date (en currentTimeInMiliseconds() ) ?

0 votes

L'entreprise pour laquelle je travaille stocke toutes les dates en millisecondes

2 votes

Mais à quoi sert la double conversion date -> chaîne -> date et quelle est l'utilité de la double conversion date -> chaîne -> date ? format qui manque dans le code ?

257voto

Travis Griggs Points 2851

Je ne comprends pas pourquoi vous faites quoi que ce soit avec les cordes...

extension Date {
    var millisecondsSince1970:Int64 {
        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)

0 votes

Je fais la chaîne parce que j'ai besoin que millisecondsSince1970 soit en UTC et que init(milliseconds:Int) soit remis en heure locale.

3 votes

Les objets de date sont siempre dans UTC. Dans mon exemple, ces valeurs sont en UTC (notez que la méthode de description rend ensuite l'époque UTC commençant en PDT).

4 votes

Il est préférable de faire init(milliseconds:Double) au lieu de Int, sinon vous perdrez les millisecondes lors de la reconversion.

56voto

Prashant Tukadiya Points 6585

Comme @Travis La solution fonctionne mais dans certains cas

var millisecondsSince1970:Int FERA PLANTER L'APPLICATION ,

avec erreur

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

Voici la réponse actualisée

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

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

A propos des définitions d'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.

En général, je rencontre ce problème dans les cas suivants iPhone 5 qui fonctionne dans un environnement 32 bits. Les nouveaux appareils fonctionnent désormais en env 64 bits. Leur Int sera Int64 .

J'espère que cela sera utile à quelqu'un qui a le même problème.

3 votes

Pourquoi cette erreur se produit-elle ? L'intervalle de temps depuis 1970 est un nombre de 32 bits. Du moins jusqu'à ce que nous arrivions à ceci : fr.wikipedia.org/wiki/problème de l'année 2038

3 votes

@DoesData Si vous voyez que nous multiplions un nombre par 1000, cela sort de la plage de Int32.

3 votes

Certains anciens appareils iOS fonctionnent en 32 bits. C'est Int es Int32 . Mais un nouvel appareil iOS, ex : iPhone 6, c'est Int es Int64 . Le problème des 32 bits peut donc entraîner un plantage sur les anciens appareils iOS.

17voto

La solution de @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, qui 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 ))
    }

}

13voto

user28434 Points 3059
//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 supprimé les conversions apparemment inutiles via les chaînes de caractères et tous les éléments aléatoires. ! .

0 votes

Ce serait formidable, mais j'ai besoin de currentTimeInMilliseconds pour convertir l'heure locale en UTC et j'ai besoin de dateFromMilliseconds pour convertir l'heure UTC en heure locale.

0 votes

Horodatage es dans l'UTC. . > The number of seconds from the reference date (00:00:00 **UTC** on 1 January 1970)

0 votes

Pourquoi * 1000, je pense que nous avons perdu la miliseconde

3voto

MAhipal Singh Points 2302
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)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X