web-dev-qa-db-fra.com

Objective-C, Comment puis-je obtenir la date actuelle dans le fuseau horaire UTC?

J'essaie:

NSDate *currentDateInLocal = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:SS.SSS'Z'"];
NSString *currentLocalDateAsStr = [dateFormatter stringFromDate:currentDateInLocal];

NSDateFormatter * dateFormatter2 = [[NSDateFormatter alloc] init];
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:@"UTC"];
[dateFormatter2 setTimeZone:timeZone];
[dateFormatter2 setDateFormat:@"yyyy-MM-dd'T'HH:mm:SS.SSS'Z'"];
NSDate *currentDateInUTC = [dateFormatter2 dateFromString:currentLocalDateAsStr];

mais cela ne représente toujours pas l'heure UTC actuelle, comment puis-je y parvenir?

Merci

37
Baconbeastnz
NSDate *currentDate = [[NSDate alloc] init];

Maintenant, il est en UTC, (au moins après avoir utilisé la méthode ci-dessous)
Pour enregistrer cette heure au format UTC (depuis la date de référence 1970), utilisez

double secsUtc1970 = [[NSDate date]timeIntervalSince1970];

Définissez le formateur de date pour afficher l'heure locale:

NSTimeZone *timeZone = [NSTimeZone defaultTimeZone];
// or Timezone with specific name like
// [NSTimeZone timeZoneWithName:@"Europe/Riga"] (see link below)
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeZone:timeZone];
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
NSString *localDateString = [dateFormatter stringFromDate:currentDate];

Noms NSTimeZone disponibles

Un objet NSDate utilise toujours UTC comme référence temporelle, mais la représentation sous forme de chaîne d'une date n'est pas nécessairement basée sur le fuseau horaire UTC.

Veuillez noter que l’UTC n’est pas (uniquement) un fuseau horaire, c’est un système qui mesure le temps sur Terre, le coordonne (le C dans UTC signifie coordonné).
La date NSDate est liée à une date de référence datée du 1.1.1970 UTC à minuit, quoique légèrement décrite à tort par Apple comme étant le 1.1.1970 GMT.

Dans la question initiale, le dernier fuseau horaire Word n'est pas parfait.

41
AlexWien

Vous compliquez les choses trop.

NSDates n'ont pas de fuseau horaire ou de calendrier. [NSDate date] obtient la date actuelle, qui est une mesure d'un moment de l'histoire. Si je lance [NSDate date] en Europe exactement au même moment qu'en Amérique, nous aurons exactement la même valeur.

La manière dont vous imprimez une date dépend du calendrier et du fuseau horaire. Ainsi, une date imprimée dans le calendrier grégorien est différente de la même que celle imprimée dans le calendrier julien. Et une date imprimée dans le calendrier grégorien UTC est différente de la même que celle imprimée dans le calendrier grégorien PST. Mais ils sont toujours la même date.

Donc, vous voulez aller directement à votre dateFormatter2.

49
Tommy

Le accepté réponse de Alex Wien est incorrect

Par défaut, NSDateFormatter ajuste la valeur date-heure de NSDate de l'heure UTC au fuseau horaire local de l'utilisateur. Pour éviter cet ajustement, indiquez à NSDateFormatter d'utiliser le fuseau horaire pour UTC.

Pour vérifier les résultats, google "heure actuelle utc".

Mon code source ci-dessous devrait faire le travail, ce qui signifie obtenir la date-heure actuelle sous forme de chaîne au format format ISO 8601 au format UTC ( Zulu ) zone désignée par une Z à la fin.

NSDate* datetime = [NSDate date];
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]]; // Prevent adjustment to user's local time zone.
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
NSString* dateTimeInIsoFormatForZuluTimeZone = [dateFormatter stringFromDate:datetime];

Vous pouvez mettre cette logique dans une paire de méthodes pratiques quelque part dans votre application.

- (NSString*)now
{
    // Purpose: Return a string of the current date-time in UTC (Zulu) time zone in ISO 8601 format.
    return [self toStringFromDateTime:[NSDate date]];
}

…et…

- (NSString*)toStringFromDateTime:(NSDate*)datetime
{
    // Purpose: Return a string of the specified date-time in UTC (Zulu) time zone in ISO 8601 format.
    // Example: 2013-10-25T06:59:43.431Z
    NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
    [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
    NSString* dateTimeInIsoFormatForZuluTimeZone = [dateFormatter stringFromDate:datetime];
    return dateTimeInIsoFormatForZuluTimeZone;
}

Exemple d'utilisation…

NSString* now = [self now];

Ou alors, transformez ces signes moins en signes plus à utiliser comme méthodes de classe plutôt que comme méthodes d’instance…

NSString* now = [SomeClassNameHere now];

Astuce: pour une meilleure lisibilité par les humains, changez cette T dans le format en SPACE. Pour une meilleure interopérabilité par logiciel, conservez la variable T. La spécification ISO 8601 tolère un espace mais recommande de conserver la variable T.


Astuce: je n'ai pas testé, mais… Certaines personnes disent que instancier [NSDateFormatter][4] coûte cher. Si vous le faites souvent (comme dans une boucle), envisagez de mettre en cache une instance unique pour la réutiliser.

37
Basil Bourque

S'IL VOUS PLAÎT CONFIGURER Identificateur de calendrier !!!

Je ne suis pas trop en retard! Parce que je n'ai vu personne configurer le Identificateur de calendrier . C'est vraiment important pour les utilisateurs du monde entier. De nombreux utilisateurs utilisent un calendrier non grégorien. Ils se tromperont d'année en année. Surtout quand vous avez besoin de le stocker dans votre propre base de données. (Nous avons rencontré ce problème avant)

NSCalendarIdentifierGregorian
NSCalendarIdentifierBuddhist
NSCalendarIdentifierChinois
NSCalendarIdentifierHebrew
NSCalendarIdentifierIslamic
NSCalendarIdentifierIslamicCivil
NSCalendarIdentifierJapanese
NSCalendarIdentifierRepublicOfChina
NSCalendarIdentifierPersian
NSCalendarIdentifierIndian
NSCalendarIdentifierISO8601 

Code: 

-(NSString *)getUTCFormateDate:(NSDate *)localDate
{
    NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:@"UTC"];
    NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
    [dateFormatter setCalendar:gregorianCalendar];
    [dateFormatter setTimeZone:timeZone];
    [dateFormatter setLocale:locale];
    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    NSString *dateString = [dateFormatter stringFromDate:localDate];
    return dateString;
}  
10
Yi Jiang

[NSDate date] est UTC. Peut-être que vous vous faites avoir en regardant dans les locaux? Ensuite, il est converti dans votre fuseau horaire.

Si vous voyez la valeur dans les sections locales, vous la voyez en heure locale, mais si vous l'imprimez dans la console, vous la voyez en UTC.

Quand vous voyez '+0000' après l'heure, vous savez que c'est en UTC

2
Cub71

Swift 3

let utcTimestamp = Date().timeIntervalSince1970
print("timeStamp = \(utcTimestamp)")

Mai prolongation serait plus facile.

Swift 4 : UTC/GMT ⟺ Local (courant/système) 

extension Date {

    // Convert local time to UTC (or GMT)
    func toGlobalTime() -> Date {
        let timezone = TimeZone.current
        let seconds = -TimeInterval(timezone.secondsFromGMT(for: self))
        return Date(timeInterval: seconds, since: self)
    }

    // Convert UTC (or GMT) to local time
    func toLocalTime() -> Date {
        let timezone = TimeZone.current
        let seconds = TimeInterval(timezone.secondsFromGMT(for: self))
        return Date(timeInterval: seconds, since: self)
    }

}


// Try it
let utcDate = Date().toGlobalTime()
let localDate = utcDate.toLocalTime()

print("utcDate - (utcDate)")
print("localDate - (localDate)")
1
Krunal

Une autre façon de procéder est la même chose dans une classe C++ de votre projet Objective C. (Créez donc un fichier .mm et construisez une classe C++ avec des parties publiques et privées et collez-le dans la partie publique (sauf si vous en avez besoin privé).) Ensuite, faites-le comme NSString *sNowUTC = MyClass::getUTCTimestamp();.

static NSString *getUTCTimestamp(){
  time_t rawtime;
  struct tm * timeinfo;
  char buffer [80];
  time (&rawtime);
  timeinfo = gmtime (&rawtime);
  // make format like "2016-06-16 02:37:00" for 
  //   June 16, 2016 @ 02:37:00 UTC time
  strftime (buffer,80,"%F %T",timeinfo);
  std::string sTime(buffer);
  NSString *sUTC = @(sTime.c_str());
  return sUTC;
}
0
Volomike