iOS: converti UTC NSDate in fuso orario locale


139

Come faccio a convertire un UTC NSDatein fuso orario locale NSDate in Obiettivo C o / e Swift?


14
Le date hanno certamente dei fusi orari.
Glenn Maynard,

1
Se aiuta, pensa alle temperature. Possono essere espressi in Fahrenheit, Celsius o Kelvin. Ma l'informazione che viene espressa (il movimento medio delle molecole) non ha unità intrinseca, sebbene sia significativa per noi solo quando espressa in qualche unità.
software si è evoluto il

7
@DaveDeLong NSDate ha un fuso orario. Dal riferimento alla classe NSDate: "Questo metodo restituisce un valore temporale relativo a una data di riferimento assoluta, il primo istante del 1 ° gennaio 2001, GMT." Nota il riferimento chiaro e specifico al GMT.
Murray Sagal,

3
Non sono d'accordo. NSDate NON ha un fuso orario. Per specificare il fuso orario per NSDate, utilizzare un oggetto NSCalendar o un oggetto NSDateFormatter. Se si crea un NSDate da una stringa che non ha un fuso orario specificato, NSDate supporrà che la stringa sia nell'ora GMT.
Rickster,

1
@MurraySagal Solo perché quel particolare metodo restituisce un valore di ora relativo a una data in un fuso orario specifico, ciò non significa che NSDate modella una data come relativa a un fuso orario.
eremzeit,

Risposte:


139
NSTimeInterval seconds; // assume this exists
NSDate* ts_utc = [NSDate dateWithTimeIntervalSince1970:seconds];

NSDateFormatter* df_utc = [[[NSDateFormatter alloc] init] autorelease];
[df_utc setTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]];
[df_utc setDateFormat:@"yyyy.MM.dd G 'at' HH:mm:ss zzz"];

NSDateFormatter* df_local = [[[NSDateFormatter alloc] init] autorelease];
[df_local setTimeZone:[NSTimeZone timeZoneWithName:@"EST"]];
[df_local setDateFormat:@"yyyy.MM.dd G 'at' HH:mm:ss zzz"];

NSString* ts_utc_string = [df_utc stringFromDate:ts_utc];
NSString* ts_local_string = [df_local stringFromDate:ts_utc];

// you can also use NSDateFormatter dateFromString to go the opposite way

Tabella dei parametri della stringa di formattazione:

https://waracle.com/iphone-nsdateformatter-date-formatting-table/

Se le prestazioni sono una priorità, potresti prendere in considerazione l'utilizzo strftime

https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man3/strftime.3.html


probabilmente vale la pena ricordare che puoi usare il formattatore per leggere anche le date delle stringhe
slf

34
@DaveDeLong va bene se stai visualizzando la data come stringa. Ma ci sono ragioni perfettamente valide per fare conversioni di fuso orario in una data. Ad esempio, se si desidera impostare la data predefinita su un UIDatePicker utilizzando setDate :. Le date restituite dai servizi Web sono spesso UTC, ma rappresentano un evento nel fuso orario locale dell'utente, come un elenco TV. Il passaggio in una data non convertita visualizzerà l'ora errata nel selettore.
Christopher Pickslay,

5
@GlennMaynard Non sono d'accordo. L'essenza di questa risposta è che non NSDateè necessaria alcuna conversione all'oggetto, il che è corretto. La conversione in un fuso orario avviene quando la data è formattata, non quando viene creata, perché le date non hanno fusi orari.
Dave DeLong,

1
@GlennMaynard ... tranne che NSCalendarDateè deprecato.
Dave DeLong,

1
Nota anche questo: oleb.net/blog/2011/11/… dove dice "GMT! = UTC"
huggie

106

EDIT Quando ho scritto questo non sapevo che avrei dovuto usare un dateformatter che probabilmente è un approccio migliore, quindi dai un'occhiata anche slfalla risposta.

Ho un servizio web che restituisce le date in UTC. Uso toLocalTimeper convertirlo in ora locale e toGlobalTimeper riconvertire se necessario.

È qui che ho ricevuto la mia risposta:

https://agilewarrior.wordpress.com/2012/06/27/how-to-convert-nsdate-to-different-time-zones/

@implementation NSDate(Utils)

-(NSDate *) toLocalTime
{
  NSTimeZone *tz = [NSTimeZone defaultTimeZone];
  NSInteger seconds = [tz secondsFromGMTForDate: self];
  return [NSDate dateWithTimeInterval: seconds sinceDate: self];
}

-(NSDate *) toGlobalTime
{
  NSTimeZone *tz = [NSTimeZone defaultTimeZone];
  NSInteger seconds = -[tz secondsFromGMTForDate: self];
  return [NSDate dateWithTimeInterval: seconds sinceDate: self];
}

@end

25
Non farlo Le date NSD sono sempre in UTC. Questo confonde il problema.
JeremyP

13
Questo può essere molto utile per il caso "webservice" sopra indicato. Supponiamo che tu abbia un server che memorizza gli eventi in UTC e che il cliente vuole chiedere tutti gli eventi accaduti oggi. Per fare ciò, il client deve ottenere la data corrente (UTC / GMT) e quindi spostarla in base al suo fuso orario prima di inviarla al server.
Taylor Lafrinere,

@JeremyP Sarebbe più preciso affermare che gli NSDate sono sempre in GMT. Dal riferimento alla classe NSDate: "Questo metodo restituisce un valore temporale relativo a una data di riferimento assoluta, il primo istante del 1 ° gennaio 2001, GMT." Nota il riferimento chiaro e specifico al GMT. C'è una differenza tecnica tra GMT e UTC, ma ciò è per lo più irrilevante per le soluzioni che la maggior parte delle persone sta cercando.
Murray Sagal,

3
Sarebbe bello notare da dove hai copiato il codice da: agilewarrior.wordpress.com/2012/06/27/…
aryaxt

2
@aryaxt hai ragione, mi dispiace. Onestamente non mi ricordavo da dove l'ho copiato quando ho pubblicato la risposta.
Gyozo Kudor,

49

Il metodo più semplice che ho trovato è questo:

NSDate *someDateInUTC = …;
NSTimeInterval timeZoneSeconds = [[NSTimeZone localTimeZone] secondsFromGMT];
NSDate *dateInLocalTimezone = [someDateInUTC dateByAddingTimeInterval:timeZoneSeconds];

3
Questa risposta sembra più portatile. La risposta di seguito presuppone che il fuso orario sia fissato in fase di esecuzione mentre la risposta sopra deriva il fuso orario dalla piattaforma.
bleeckerj,

9
Molto utile. Un'aggiunta, secondsFromGMTForDatedovrebbe essere utilizzata se si desidera tenere conto dell'ora legale. Vedi Apple Docs
Sergey Markelov

1
Ciò non tiene conto delle modifiche dell'ora legale.
Lkraider

36

Swift 3+ : UTC su Local e Local su UTC

extension Date {

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

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

Convertirà qualsiasi fuso orario in UTC o viceversa?
Mitesh,

26

Se si desidera la data e l'ora locali. Prova questo codice: -

NSString *localDate = [NSDateFormatter localizedStringFromDate:[NSDate date] dateStyle:NSDateFormatterMediumStyle timeStyle:NSDateFormatterMediumStyle];

Bella risposta! Questo prenderà la data corrente. Un adattamento di questo, che utilizza una stringa data sarebbe quella di sostituire [NSDate date]con [NSDate dateWithNaturalLanguageString:sMyDateString].
Volomike,

7

Converti la tua data UTC in Data locale

-(NSString *)getLocalDateTimeFromUTC:(NSString *)strDate
{
    NSDateFormatter *dtFormat = [[NSDateFormatter alloc] init];
    [dtFormat setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    [dtFormat setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
    NSDate *aDate = [dtFormat dateFromString:strDate];

    [dtFormat setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    [dtFormat setTimeZone:[NSTimeZone systemTimeZone]];

    return [dtFormat stringFromDate:aDate];
}

Usa così

NSString *localDate = [self getLocalDateTimeFromUTC:@"yourUTCDate"];

1
Non funziona per me, la mia ora locale è +3 e questo codice restituisce +2
Fadi Abuzant,

6

Qui l'input è una stringa currentUTCTime (nel formato 30/08/2012 alle 11:11) converte l'ora di input in GMT nell'ora di zona impostata dal sistema

//UTC time
NSDateFormatter *utcDateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[utcDateFormatter setDateFormat:@"MM/dd/yyyy HH:mm"];
[utcDateFormatter setTimeZone :[NSTimeZone timeZoneForSecondsFromGMT: 0]];

// utc format
NSDate *dateInUTC = [utcDateFormatter dateFromString: currentUTCTime];

// offset second
NSInteger seconds = [[NSTimeZone systemTimeZone] secondsFromGMT];

// format it and send
NSDateFormatter *localDateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[localDateFormatter setDateFormat:@"MM/dd/yyyy HH:mm"];
[localDateFormatter setTimeZone :[NSTimeZone timeZoneForSecondsFromGMT: seconds]];

// formatted string
NSString *localDate = [localDateFormatter stringFromDate: dateInUTC];
return localDate;

4
//This is basic way to get time of any GMT time.

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"hh:mm a"];  // 09:30 AM
[formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:1]]; // For GMT+1
NSString *time = [formatter stringFromDate:[NSDate date]];  // Current time


2

Scrivo questo metodo per convertire l'ora della data nel nostro LocalTimeZone

-Qui (NSString *) Il parametro TimeZone è un fuso orario del server

-(NSString *)convertTimeIntoLocal:(NSString *)defaultTime :(NSString *)TimeZone
{
    NSDateFormatter *serverFormatter = [[NSDateFormatter alloc] init];
    [serverFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:TimeZone]];
    [serverFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    NSDate *theDate = [serverFormatter dateFromString:defaultTime];
    NSDateFormatter *userFormatter = [[NSDateFormatter alloc] init];
    [userFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    [userFormatter setTimeZone:[NSTimeZone localTimeZone]];
    NSString *dateConverted = [userFormatter stringFromDate:theDate];
    return dateConverted;
}

1

Dal momento che nessuno sembrava usare NSDateComponents, ho pensato di inserirne uno in ... In questa versione, non NSDateFormatterviene utilizzato, quindi nessuna analisi delle stringhe, e NSDatenon viene utilizzato per rappresentare l'ora al di fuori di GMT (UTC). L'originale NSDateè nella variabile i_date.

NSCalendar *anotherCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:i_anotherCalendar];
anotherCalendar.timeZone = [NSTimeZone timeZoneWithName:i_anotherTimeZone];

NSDateComponents *anotherComponents = [anotherCalendar components:(NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond | NSCalendarUnitNanosecond) fromDate:i_date];

// The following is just for checking   
anotherComponents.calendar = anotherCalendar; // anotherComponents.date is nil without this
NSDate *anotherDate = anotherComponents.date;

i_anotherCalendarpotrebbe essere NSCalendarIdentifierGregoriano qualsiasi altro calendario. Il NSStringpermesso per i_anotherTimeZonepuò essere acquisito con [NSTimeZone knownTimeZoneNames], ma anotherCalendar.timeZonepotrebbe essere [NSTimeZone defaultTimeZone]o [NSTimeZone localTimeZone]o[NSTimeZone systemTimeZone] tutto.

In realtà sta anotherComponentstrattenendo l'ora nel nuovo fuso orario. Noterai che anotherDateè uguale a i_date, perché contiene l'ora in GMT (UTC).


0

Puoi provare questo:

NSDate *currentDate = [[NSDate alloc] init];
NSTimeZone *timeZone = [NSTimeZone defaultTimeZone];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterLongStyle];
[dateFormatter setTimeStyle:NSDateFormatterLongStyle];
[dateFormatter setTimeZone:timeZone];
[dateFormatter setDateFormat:@"ZZZ"];
NSString *localDateString = [dateFormatter stringFromDate:currentDate];
NSMutableString *mu = [NSMutableString stringWithString:localDateString];
[mu insertString:@":" atIndex:3];
 NSString *strTimeZone = [NSString stringWithFormat:@"(GMT%@)%@",mu,timeZone.name];
 NSLog(@"%@",strTimeZone);

-1

Convertire l'ora UTC nel fuso orario corrente.

funzione di chiamata

NSLocale *locale = [NSLocale autoupdatingCurrentLocale];

NSString *myLanguageCode = [locale objectForKey: NSLocaleLanguageCode];
NSString *myCountryCode = [locale objectForKey: NSLocaleCountryCode];

NSString *rfc3339DateTimeString = @"2015-02-15 00:00:00"];
NSDate *myDateTime = (NSDate*)[_myCommonFunctions _ConvertUTCTimeToLocalTimeWithFormat:rfc3339DateTimeString LanguageCode:myLanguageCode CountryCode:myCountryCode Formated:NO];

Funzione

-NSObject*)_ConvertUTCTimeToLocalTimeWithFormat:rfc3339DateTimeString     LanguageCode:(NSString *)lgc CountryCode:(NSString *)ctc Formated:(BOOL) formated
{
    NSDateFormatter *sUserVisibleDateFormatter = nil;
    NSDateFormatter *sRFC3339DateFormatter = nil;

    NSTimeZone *timeZone = [NSTimeZone defaultTimeZone];

    if (sRFC3339DateFormatter == nil)
    {
        sRFC3339DateFormatter = [[NSDateFormatter alloc] init];

        NSLocale *myPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:[NSString stringWithFormat:@"%@", timeZone]];

        [sRFC3339DateFormatter setLocale:myPOSIXLocale];
        [sRFC3339DateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"];
        [sRFC3339DateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
    }

    // Convert the RFC 3339 date time string to an NSDate.
    NSDate *date = [sRFC3339DateFormatter dateFromString:rfc3339DateTimeString];

    if (formated == YES)
    {
        NSString *userVisibleDateTimeString;

        if (date != nil)
        {
            if (sUserVisibleDateFormatter == nil)
            {
                sUserVisibleDateFormatter = [[NSDateFormatter alloc] init];
                [sUserVisibleDateFormatter setDateStyle:NSDateFormatterMediumStyle];
                [sUserVisibleDateFormatter setTimeStyle:NSDateFormatterShortStyle];
            }

            // Convert the date object to a user-visible date string.
            userVisibleDateTimeString = [sUserVisibleDateFormatter stringFromDate:date];

            return (NSObject*)userVisibleDateTimeString;
        }
    }

    return (NSObject*)date;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.