iOS: UTC NSDate'i yerel Saat Dilimi'ne dönüştürme


139

Bir NSDateUTC'yi Objective C veya / ve Swift'te yerel saat dilimi NSDate'e nasıl dönüştürebilirim ?


14
Tarihler kesinlikle saat dilimlerine sahiptir.
Glenn Maynard

1
Yardımcı olursa, sıcaklıkları düşünün. Fahrenheit, Celsius veya Kelvin olarak ifade edilebilirler. Ancak ifade edilen bilgilerin (moleküllerin ortalama hareketinin) içsel bir birimi yoktur, ancak bazı birimlerde ifade edildiğinde bizim için anlamlıdır.
yazılım

7
@DaveDeLong NSDate'in saat dilimi var. NSDate sınıfı başvurusundan: "Bu yöntem mutlak başvuru tarihine göre bir zaman değeri döndürür - 1 Ocak 2001'in ilk anında GMT." GMT ile ilgili açık ve spesifik referanslara dikkat edin.
Murray Sagal

3
Katılmıyorum. NSDate'in saat dilimi YOKTUR. NSDate için saat dilimini belirtmek için bir NSCalendar nesnesi veya NSDateFormatter nesnesi kullanırsınız. Herhangi bir saat dilimi belirtilmemiş bir dizeden bir NSDate oluşturursanız, NSDate dizenin GMT zamanında olduğunu varsayar.
Rickster

1
@MurraySagal Belirli bir yöntemin belirli bir saat dilimindeki bir tarihe göre bir zaman değeri döndürmesi NSDate'in bir tarihi bir saat dilimine göre modellediği anlamına gelmez.
eremzeit

Yanıtlar:


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

Dize parametrelerini biçimlendirme tablosu:

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

Performans bir öncelikse, aşağıdakileri kullanmayı düşünebilirsiniz: strftime

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


Muhtemelen bahsetmeye değer, dizelerden de tarihleri ​​okumak için biçimlendiriciyi kullanabilirsiniz
slf

34
@DaveDeLong, tarihi bir dize olarak görüntülüyorsanız, her şey yolunda ve iyi. Ancak bir tarihte saat dilimi dönüşümleri yapmak için mükemmel geçerli nedenler vardır. Örneğin, setDate: kullanarak bir UIDatePicker'daki tarihi varsayılan olarak ayarlamak istiyorsanız. Web servisleri tarafından döndürülen tarihler genellikle UTC'dir, ancak kullanıcının yerel saat dilimindeki bir TV listesi gibi bir etkinliği temsil eder. Dönüştürülmemiş bir tarihte geçmek, seçicide yanlış saati görüntüler.
Christopher Pickslay

5
@GlennMaynard Ben katılmıyorum. Bu cevabın özü, NSDatenesneye dönüştürmenin gerekli olmadığı, ki bu doğru. Bir saat dilimine dönüştürme, tarih oluşturulurken değil, biçimlendirildiğinde gerçekleşir, çünkü tarihler saat dilimlerine sahip değildir.
Dave DeLong

1
@ GlenNaynard ... bunun dışında NSCalendarDate.
Dave DeLong

1
Ayrıca şunu da unutmayın: "GMT! = UTC" yazan oleb.net/blog/2011/11/…
huggie

106

EDIT Bunu yazdığımda muhtemelen daha iyi bir yaklaşım olan bir dateformatter kullanmalıyım bilmiyordum, bu yüzden slfcevabını da kontrol et .

UTC'de tarihleri ​​döndüren bir web servisim var. Kullandığım toLocalTimeyerel saate dönüştürmek için ve toGlobalTimegerekirse geri dönüştürün.

Yanıtımı buradan aldım:

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
Bunu yapma. NSDates her zaman UTC'dir. Bu sadece sorunu karıştırıyor.
JeremyP

13
Bu, yukarıda belirtilen "webservice" davası için çok yararlı olabilir. Diyelim ki UTC'de olayları depolayan bir sunucunuz var ve istemci bugün gerçekleşen tüm olayları sormak istiyor. Bunu yapmak için, istemcinin sunucuya göndermeden önce geçerli tarihi (UTC / GMT) alması ve ardından saat dilimi uzaklığı ile kaydırması gerekir.
Taylor Lafrinere

@JeremyP NSDates'in her zaman GMT'de olduğunu söylemek daha doğru olur. NSDate sınıfı başvurusundan: "Bu yöntem mutlak başvuru tarihine göre bir zaman değeri döndürür - 1 Ocak 2001'in ilk anında GMT." GMT ile ilgili açık ve spesifik referanslara dikkat edin. GMT ve UTC arasında teknik bir fark var, ancak bu çoğu insanın aradığı çözümlerle alakasız.
Murray Sagal

3
Kodu nereden kopyaladığınızı not etmek güzel olurdu: agilewarrior.wordpress.com/2012/06/27/…
aryaxt

2
@aryaxt haklısın, üzgünüm. Cevabı gönderdiğim zaman nereden kopyaladığımı hatırlamıyordum.
gyozo kudor

49

Bulduğum en kolay yöntem şudur:

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

3
Bu cevap daha taşınabilir geliyor. Aşağıdaki cevap saat diliminin çalışma zamanında sabit olduğunu varsayarken yukarıdaki cevap saat dilimini platformdan alır.
bleeckerj

9
Çok yararlı. secondsFromGMTForDateYaz saatini hesaba katmak istiyorsanız , bir ek daha kullanılmalıdır. Bkz Elma Dokümanlar
Sergey Markelov

1
Bu, DST değişikliklerini dikkate almaz.
lkraider

36

Swift 3+ : UTC'den Yerel ve Yerel'den UTC'ye

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

Herhangi bir saat dilimini UTC'ye veya tam tersine dönüştürür?
Mitesh

26

Yerel Tarih ve saat istiyorsanız. Bu kodu deneyin: -

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

Mükemmel cevap! Bu, geçerli tarihi alır. Tarih dizesini kullanan Buna bir adaptasyon değiştirmek şeklinde olur [NSDate date]ile [NSDate dateWithNaturalLanguageString:sMyDateString].
Volomike

7

UTC tarihinizi Yerel Tarih'e dönüştürün

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

Bunun gibi kullan

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

1
Benim için çalışmıyor, benim yerel saat +3 ve bu kod dönüş +2
Fadi Abuzant

6

Burada giriş currentUTCTime (08/30/2012 11:11 biçiminde) bir dizedir GMT'deki giriş süresini sistem ayarlı bölge saatine dönüştürür

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

Bu yöntemi tarih saatini LocalTimeZone'umuza dönüştürmek için yazıyorum

-Burada (NSString *) TimeZone parametresi bir sunucu saat dilimidir

-(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

Kimse kullanmak gibi görünmediği için NSDateComponents, ben bir adım olacağını düşündüm ... Bu sürümde, hayır NSDateFormatterkullanılır, dolayısıyla dize ayrıştırma yok ve NSDateGMT (UTC) dışında zaman temsil etmek için kullanılmaz. Orijinal NSDatedeğişkendir 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_anotherCalendarolabilir NSCalendarIdentifierGregorianveya başka bir takvim olabilir. NSStringİzin i_anotherTimeZoneile elde edilebilir [NSTimeZone knownTimeZoneNames], ancak anotherCalendar.timeZoneolabilir [NSTimeZone defaultTimeZone]veya [NSTimeZone localTimeZone]veya[NSTimeZone systemTimeZone] tamamen.

Aslında anotherComponentsyeni zaman diliminde zamanı tutuyor. Fark edeceksiniz , çünkü GMT (UTC) anotherDatecinsinden i_datezamanı tutuyor.


0

Bunu deneyebilirsiniz:

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

UTC saatini geçerli saat dilimine dönüştürün.

çağrı fonksiyonu

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

fonksiyon

-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;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.