iOS: UTC NSDate in lokale Zeitzone konvertieren

138

Wie konvertiere ich eine UTC NSDatein die lokale Zeitzone NSDate in Objective C oder / und Swift?

Krunal
quelle
14
Daten haben sicherlich Zeitzonen.
Glenn Maynard
1
Wenn es hilft, denken Sie an Temperaturen. Sie können in Fahrenheit, Celsius oder Kelvin ausgedrückt werden. Die ausgedrückte Information (die durchschnittliche Bewegung der Moleküle) hat jedoch keine intrinsische Einheit, obwohl sie für uns nur dann von Bedeutung ist, wenn sie in einer Einheit ausgedrückt wird.
Software entwickelt
7
@ DaveDeLong NSDate hat eine Zeitzone. Aus der NSDate-Klassenreferenz: "Diese Methode gibt einen Zeitwert relativ zu einem absoluten Referenzdatum zurück - dem ersten Zeitpunkt des 1. Januar 2001, GMT." Beachten Sie den klaren und spezifischen Verweis auf GMT.
Murray Sagal
3
Ich bin nicht einverstanden. NSDate hat KEINE Zeitzone. Um die Zeitzone für das NSDate anzugeben, verwenden Sie ein NSCalendar-Objekt oder ein NSDateFormatter-Objekt. Wenn Sie ein NSDate aus einer Zeichenfolge erstellen, für die keine Zeitzone angegeben ist, geht das NSDate davon aus, dass sich die Zeichenfolge in GMT-Zeit befindet.
Rickster
1
@MurraySagal Nur weil diese eine bestimmte Methode einen Zeitwert relativ zu einem Datum in einer bestimmten Zeitzone zurückgibt, bedeutet dies nicht, dass NSDate ein Datum als relativ zu einer Zeitzone modelliert.
Eremzeit

Antworten:

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

Tabelle der Formatierungszeichenfolgenparameter:

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

Wenn Leistung Priorität hat, sollten Sie die Verwendung in Betracht ziehen strftime

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

slf
quelle
Erwähnenswert ist wahrscheinlich, dass Sie den Formatierer verwenden können, um auch Daten aus Zeichenfolgen
einzulesen
34
@ DaveDeLong das ist alles schön und gut, wenn Sie nur das Datum als Zeichenfolge anzeigen. Es gibt jedoch durchaus gültige Gründe für die Durchführung von Zeitzonenumrechnungen an einem Datum. Wenn Sie beispielsweise das Datum in einem UIDatePicker mit setDate: als Standard festlegen möchten. Von Webdiensten zurückgegebene Daten sind häufig UTC-Daten, stellen jedoch ein Ereignis in der lokalen Zeitzone des Benutzers dar, z. B. eine TV-Liste. Wenn Sie ein nicht konvertiertes Datum eingeben, wird die falsche Uhrzeit in der Auswahl angezeigt.
Christopher Pickslay
5
@GlennMaynard Ich bin anderer Meinung. Das Wesentliche dieser Antwort ist, dass keine Konvertierung zum NSDateObjekt erforderlich ist, was korrekt ist. Die Konvertierung in eine Zeitzone erfolgt, wenn das Datum formatiert und nicht erstellt wird, da Datumsangaben keine Zeitzonen haben.
Dave DeLong
1
@GlennMaynard ... außer das NSCalendarDateist veraltet.
Dave DeLong
1
Beachten Sie auch Folgendes : oleb.net/blog/2011/11/… wo "GMT! = UTC" steht
huggie
106

BEARBEITEN Als ich dies schrieb, wusste ich nicht, dass ich einen Datumsformatierer verwenden sollte, was wahrscheinlich ein besserer Ansatz istslf Antwort an.

Ich habe einen Webservice, der Daten in UTC zurückgibt. ich benutzetoLocalTime , um es in Ortszeit umzuwandeln undtoGlobalTime konvertiere es bei Bedarf zurück.

Hier habe ich meine Antwort bekommen von:

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
Gyozo Kudor
quelle
25
Tu das nicht. NSDates sind immer in UTC. Dies verwirrt das Problem nur.
JeremyP
13
Dies kann für den oben genannten Fall "Webservice" sehr nützlich sein. Angenommen, Sie haben einen Server, auf dem Ereignisse in UTC gespeichert werden, und der Client möchte nach allen Ereignissen fragen, die heute aufgetreten sind. Dazu muss der Client das aktuelle Datum (UTC / GMT) abrufen und es dann um seinen Zeitzonenversatz verschieben, bevor er es an den Server sendet.
Taylor Lafrinere
@JeremyP Es wäre genauer zu sagen, dass NSDates immer in GMT sind. Aus der NSDate-Klassenreferenz: "Diese Methode gibt einen Zeitwert relativ zu einem absoluten Referenzdatum zurück - dem ersten Zeitpunkt des 1. Januar 2001, GMT." Beachten Sie den klaren und spezifischen Verweis auf GMT. Es gibt einen technischen Unterschied zwischen GMT und UTC, der jedoch für die Lösungen, nach denen die meisten Menschen suchen, größtenteils irrelevant ist.
Murray Sagal
3
Es wäre schön zu bemerken, wo Sie den Code kopiert haben von: agilewarrior.wordpress.com/2012/06/27/…
aryaxt
2
@aryaxt du hast recht, es tut mir leid. Ich habe mich ehrlich gesagt nicht daran erinnert, woher ich kopiert habe, als ich die Antwort gepostet habe.
Gyozo Kudor
49

Die einfachste Methode, die ich gefunden habe, ist folgende:

NSDate *someDateInUTC = …;
NSTimeInterval timeZoneSeconds = [[NSTimeZone localTimeZone] secondsFromGMT];
NSDate *dateInLocalTimezone = [someDateInUTC dateByAddingTimeInterval:timeZoneSeconds];
Sendoa
quelle
3
Diese Antwort fühlt sich tragbarer an. Bei der folgenden Antwort wird davon ausgegangen, dass die Zeitzone zur Laufzeit festgelegt ist, während bei der obigen Antwort die Zeitzone von der Plattform abgeleitet wird.
bleeckerj
9
Sehr hilfreich. Ein Zusatz secondsFromGMTForDatesollte verwendet werden, wenn Sie die Sommerzeit berücksichtigen möchten. Siehe Apple Docs
Sergey Markelov
1
Dies berücksichtigt keine Sommerzeitänderungen.
lkraider
36

Swift 3+ : UTC zu Local und Local zu 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)
    }
}
Krunal
quelle
Es wird jede Zeitzone in UTC konvertieren oder umgekehrt?
Mitesh
26

Wenn Sie lokales Datum und Uhrzeit möchten. Versuchen Sie diesen Code: -

NSString *localDate = [NSDateFormatter localizedStringFromDate:[NSDate date] dateStyle:NSDateFormatterMediumStyle timeStyle:NSDateFormatterMediumStyle];
Mohd Iftekhar Qurashi
quelle
Gute Antwort! Dadurch wird das aktuelle Datum erfasst. Eine Anpassung dieser , die ein Datum Zeichenfolge verwendet wäre zu ersetzen [NSDate date]mit [NSDate dateWithNaturalLanguageString:sMyDateString].
Volomike
7

Konvertieren Sie Ihr UTC-Datum in ein lokales Datum

-(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];
}

Verwenden Sie so

NSString *localDate = [self getLocalDateTimeFromUTC:@"yourUTCDate"];
Vvk
quelle
1
Nicht für mich arbeiten, meine Ortszeit ist +3 und dieser Code gibt +2 zurück
Fadi Abuzant
6

Hier ist die Eingabe eine Zeichenfolge currentUTCTime (im Format 30.08.2012 11:11), die die Eingabezeit in GMT in die vom System eingestellte Zonenzeit konvertiert

//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;
Ashwin Kumar
quelle
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
Linh Nguyen
quelle
2

Ich schreibe diese Methode, um Datum und Uhrzeit in unsere LocalTimeZone umzuwandeln

-Hier (NSString *) TimeZone-Parameter ist eine Server-Zeitzone

-(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;
}
imjaydeep
quelle
1

Da niemand zu verwenden schien NSDateComponents, dachte ich, ich würde einen in ... In dieser Version wird no NSDateFormatterverwendet, daher kein String-Parsing, und NSDatewird nicht verwendet, um die Zeit außerhalb von GMT (UTC) darzustellen. Das Original NSDatebefindet sich in der Variablen 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_anotherCalendarkönnte NSCalendarIdentifierGregorianoder irgendein anderer Kalender sein. Das NSStringZulässige i_anotherTimeZonekann mit erworben werden [NSTimeZone knownTimeZoneNames], anotherCalendar.timeZonekönnte aber [NSTimeZone defaultTimeZone]oder [NSTimeZone localTimeZone]oder sein[NSTimeZone systemTimeZone] insgesamt sein.

Es hält tatsächlich anotherComponentsdie Zeit in der neuen Zeitzone. Sie werden feststellen , dass es anotherDategleich ist i_date, weil es Zeit in GMT (UTC) hält.

techniao
quelle
0

Sie können dieses versuchen:

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);
Kalpesh Satasiya
quelle
-1

Konvertieren Sie die UTC-Zeit in die aktuelle Zeitzone.

Funktion aufrufen

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];

Funktion

-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;
}
Alan10977
quelle