iOS: แปลง UTC NSDate เป็นเขตเวลาท้องถิ่น


139

ฉันจะแปลง UTC เป็นโซนเวลาNSDateท้องถิ่น NSDate ใน Objective C หรือ / และ Swift ได้อย่างไร


14
วันที่แน่นอนมีโซนเวลา
Glenn Maynard

1
ถ้าช่วยได้ให้นึกถึงอุณหภูมิ สามารถแสดงเป็นฟาเรนไฮต์เซลเซียสหรือเคลวิน แต่ข้อมูลที่แสดงออก (การเคลื่อนไหวโดยเฉลี่ยของโมเลกุล) ไม่มีหน่วยภายในแม้ว่ามันจะมีความหมายกับเราเมื่อแสดงในบางหน่วยเท่านั้น
ซอฟต์แวร์พัฒนาเมื่อ

7
@DaveDeLong NSDate มีเขตเวลา จากการอ้างอิงระดับ NSDate: "วิธีนี้จะส่งกลับค่าเวลาที่เกี่ยวข้องกับวันที่อ้างอิงแน่นอน - ทันทีแรกของ 1 มกราคม 2001, GMT." สังเกตการอ้างอิงที่ชัดเจนและเฉพาะเจาะจงกับ GMT
Murray Sagal

3
ฉันไม่เห็นด้วย. NSDate ไม่มีเขตเวลา ในการระบุเขตเวลาสำหรับ NSDate คุณใช้วัตถุ NSCalendar หรือวัตถุ NSDateFormatter หากคุณสร้าง NSDate จากสตริงที่ไม่มีเขตเวลาระบุ NSDate จะถือว่าสตริงนั้นอยู่ในเวลา GMT
Rickster

1
@MurraySagal เพียงเพราะวิธีการหนึ่งส่งกลับค่าเวลาเทียบกับวันที่ในเขตเวลาที่เฉพาะเจาะจงมันไม่ได้หมายความว่า NSDate จำลองวันที่ว่าสัมพันธ์กับเขตเวลา
eremzeit

คำตอบ:


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

ตารางการจัดรูปแบบพารามิเตอร์สตริง:

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

หากประสิทธิภาพมีความสำคัญคุณอาจต้องพิจารณาการใช้ strftime

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


อาจคุ้มค่าที่จะกล่าวถึงคุณสามารถใช้ตัวจัดรูปแบบเพื่ออ่านวันที่กลับมาจากสตริงได้เช่นกัน
slf

34
@DaveDeLong นั้นทำได้ดีและดีถ้าคุณเพียงแค่แสดงวันที่เป็นสตริง แต่มีเหตุผลที่ถูกต้องอย่างสมบูรณ์สำหรับการแปลงโซนเวลาในวันที่ ตัวอย่างเช่นหากคุณต้องการเริ่มต้นวันที่บน UIDatePicker โดยใช้ setDate: วันที่ส่งคืนโดยบริการบนเว็บมักจะเป็น UTC แต่เป็นตัวแทนเหตุการณ์ในเขตเวลาท้องถิ่นของผู้ใช้เช่นรายการทีวี การผ่านในวันที่ไม่กลับจะแสดงเวลาที่ไม่ถูกต้องในตัวเลือก
Christopher Pickslay

5
@GlennMaynard ฉันไม่เห็นด้วย สาระสำคัญของคำตอบนี้คือไม่NSDateจำเป็นต้องทำการแปลงวัตถุใด ๆ ซึ่งถูกต้อง การแปลงเป็นเขตเวลาเกิดขึ้นเมื่อมีการจัดรูปแบบวันที่ไม่ใช่เมื่อมีการสร้างเนื่องจากวันที่ไม่มีเขตเวลา
Dave DeLong

1
@GlennMaynard ... ยกเว้นที่NSCalendarDateเลิกใช้แล้ว
Dave DeLong

1
โปรดทราบด้วยว่า: oleb.net/blog/2011/11/ …ที่มันบอกว่า "GMT! = UTC"
huggie

106

แก้ไขเมื่อฉันเขียนสิ่งนี้ฉันไม่รู้ว่าฉันควรใช้ Dateformatter ซึ่งอาจเป็นวิธีที่ดีกว่าดังนั้นลองดูslfคำตอบด้วย

ฉันมีเว็บเซอร์วิซที่ส่งคืนวันที่ใน UTC ฉันใช้toLocalTimeเพื่อแปลงเป็นเวลาท้องถิ่นและtoGlobalTimeแปลงกลับหากจำเป็น

นี่คือที่ฉันได้รับคำตอบจาก:

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
อย่าทำอย่างนี้ NSDates อยู่ใน UTC เสมอ นี่แค่ทำให้เกิดปัญหา
JeremyP

13
สิ่งนี้มีประโยชน์มากสำหรับกรณี "webservice" ที่ระบุไว้ข้างต้น สมมติว่าคุณมีเซิร์ฟเวอร์ที่จัดเก็บกิจกรรมใน UTC และลูกค้าต้องการขอเหตุการณ์ทั้งหมดที่เกิดขึ้นในวันนี้ ในการทำเช่นนี้ลูกค้าจะต้องได้รับวันที่ปัจจุบัน (UTC / GMT) จากนั้นเลื่อนตามเขตเวลาชดเชยก่อนที่จะส่งไปยังเซิร์ฟเวอร์
Taylor Lafrinere

@JeremyP มันจะแม่นยำกว่าที่จะบอกว่า NSDates อยู่ใน GMT เสมอ จากการอ้างอิงระดับ NSDate: "วิธีนี้จะส่งกลับค่าเวลาที่เกี่ยวข้องกับวันที่อ้างอิงแน่นอน - ทันทีแรกของ 1 มกราคม 2001, GMT." สังเกตการอ้างอิงที่ชัดเจนและเฉพาะเจาะจงกับ GMT มีความแตกต่างทางเทคนิคระหว่าง GMT และ UTC แต่ส่วนใหญ่ไม่เกี่ยวข้องกับโซลูชันที่คนส่วนใหญ่มองหา
Murray Sagal

3
จะดีที่จะทราบที่คุณคัดลอกรหัสจาก: agilewarrior.wordpress.com/2012/06/27/ …
aryaxt

2
@aryaxt คุณพูดถูกฉันขอโทษ ฉันจำไม่ได้ว่าฉันคัดลอกมาจากที่ใดเมื่อฉันโพสต์คำตอบ
gyozo kudor

49

วิธีที่ง่ายที่สุดที่ฉันพบคือ:

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

3
คำตอบนี้ให้ความรู้สึกพกพามากขึ้น คำตอบด้านล่างจะถือว่าเขตเวลาได้รับการแก้ไขที่รันไทม์ในขณะที่คำตอบข้างต้นมาจากเขตเวลาจากแพลตฟอร์ม
bleeckerj

9
มีประโยชน์มาก นอกจากนี้secondsFromGMTForDateควรใช้หนึ่งรายการหากคุณต้องการบัญชีสำหรับการปรับเวลาตามฤดูกาล ดูเอกสารของ Apple
Sergey Markelov

1
สิ่งนี้ไม่สามารถพิจารณาการเปลี่ยนแปลง DST ได้
lkraider

36

Swift 3+ : UTC เป็น Local และ Local เป็น 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)
    }
}

มันจะแปลงโซนเวลาเป็น UTC หรือในทางกลับกัน?
Mitesh

26

หากคุณต้องการวันที่และเวลาท้องถิ่น ลองรหัสนี้: -

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

คำตอบที่ดี! สิ่งนี้จะคว้าวันที่ปัจจุบัน การปรับนี้ซึ่งใช้สตริงวันที่จะแทนที่ด้วย[NSDate date] [NSDate dateWithNaturalLanguageString:sMyDateString]
Volomike

7

แปลงวันที่ UTC ของคุณเป็นวันที่ท้องถิ่น

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

ใช้แบบนี้

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

1
ไม่ทำงานสำหรับฉันเวลาท้องถิ่นของฉันคือ +3 และรหัสนี้จะส่งคืน +2
Fadi Abuzant

6

อินพุตที่นี่คือสตริงปัจจุบัน UTCTime (ในรูปแบบ 08/30/2012 11:11) แปลงเวลาอินพุตใน GMT เป็นเวลาที่ตั้งค่าระบบ

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

3

แปลงวันที่จากปฏิทิน UTC การหนึ่งที่มีในท้องถิ่นที่เหมาะสมNSTimeZone


2

ฉันเขียนวิธีนี้เพื่อแปลงเวลาวันที่เป็น LocalTimeZone ของเรา

- ที่นี่ (NSString *) พารามิเตอร์ TimeZone เป็นเขตเวลาของเซิร์ฟเวอร์

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

เนื่องจากดูเหมือนจะไม่มีใครใช้NSDateComponentsฉันคิดว่าฉันจะเลือกหนึ่งใน ... ในรุ่นนี้ไม่มีการNSDateFormatterใช้จึงไม่มีการแยกสตริงและNSDateไม่ได้ใช้เพื่อแสดงเวลานอก GMT (UTC) เดิมอยู่ในตัวแปรNSDatei_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_anotherCalendarอาจเป็นNSCalendarIdentifierGregorianหรือปฏิทินอื่น ๆ NSStringได้รับอนุญาตให้i_anotherTimeZoneสามารถซื้อได้ด้วย[NSTimeZone knownTimeZoneNames]แต่anotherCalendar.timeZoneอาจจะ[NSTimeZone defaultTimeZone]หรือ[NSTimeZone localTimeZone]หรือ[NSTimeZone systemTimeZone]ทั้งหมด

มันanotherComponentsถือเวลาในเขตเวลาใหม่ คุณจะสังเกตanotherDateได้ว่าเท่ากับi_dateเพราะถือเวลาใน GMT (UTC)


0

คุณสามารถลองอันนี้:

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 เป็นโซนเวลาปัจจุบัน

ฟังก์ชั่นการโทร

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

ฟังก์ชัน

-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;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.