iOS:将UTC NSDate转换为本地时区


138

如何NSDate在目标C或/和Swift中将UTC转换为本地时区NSDate?


14
日期肯定有时区。
Glenn Maynard

1
如果有帮助,请考虑温度。它们可以用华氏度,摄氏温度或开氏温度表示。但是,要表达的信息(分子的平均运动)没有固有单位,尽管仅对我们有意义。
软件

7
@DaveDeLong NSDate确实有一个时区。在NSDate类引用中:“此方法返回相对于绝对引用日期的时间值-GMT 2001年1月1日的第一时刻。” 请注意对GMT的明确而明确的引用。
Murray Sagal

3
我不同意。NSDate没有时区。要为NSDate指定时区,请使用NSCalendar对象或NSDateFormatter对象。如果您从未指定时区的字符串创建NSDate,则NSDate将假定该字符串以GMT时间表示。
Rickster

1
@MurraySagal仅仅因为一个特定的方法返回相对于特定时区中的日期的时间值,并不意味着NSDate将日期建模为相对于时区的日期。
eremzeit 2014年

Answers:


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 2011年

34
如果您只是将日期显示为字符串,那么@DaveDeLong很好。但是有完全正当的理由在日期上进行时区转换。例如,如果要使用setDate:在UIDatePicker上默认日期。Web服务返回的日期通常是UTC,但代表用户本地时区的事件,例如电视列表。传递未转换的日期将在选择器中显示错误的时间。
Christopher Pickslay 2011年

5
@GlennMaynard我不同意。这个答案的实质是不需要转换为NSDate对象,这是正确的。格式化日期时会发生到时区的转换,而不是在创建日期时发生,因为日期没有时区。
Dave DeLong

1
@GlennMaynard ...,NSCalendarDate不建议使用。
Dave DeLong

1
另请注意:oleb.net/blog/2011/11/…在其中显示“ GMT!= UTC”
huggie 2012年

106

编辑当我写这篇文章时,我不知道我应该使用dateformatter,这可能是一个更好的方法,所以也请查看slf的答案。

我有一个Web服务,它以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
不要这样 NSDate始终使用UTC。这只会使问题感到困惑。
JeremyP,2012年

13
这对于上面提到的“ webservice”情况非常有用。假设您有一台将事件存储在UTC中的服务器,而客户端希望查询今天发生的所有事件。为此,客户端需要获取当前日期(UTC / GMT),然后将其偏移其时区偏移量,然后再将其发送到服务器。
泰勒·拉弗里纳雷

@JeremyP说NSDates总是GMT会更准确。在NSDate类引用中:“此方法返回相对于绝对引用日期的时间值-GMT 2001年1月1日的第一时刻。” 请注意对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 2014年

9
很有帮助。secondsFromGMTForDate如果要考虑夏令时,应使用另一种。参阅Apple文件
Sergey Markelov 2014年

1
这不能考虑DST更改。
lkraider

36

Swift 3+UTC到本地,本地到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 17-10-25

6

这里的输入是字符串currentUTCTime(格式为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


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)以外的时间。原来NSDate在变量中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_anotherCalendar可以是NSCalendarIdentifierGregorian或任何其他日历。该NSString允许i_anotherTimeZone可以与被收购[NSTimeZone knownTimeZoneNames],但anotherCalendar.timeZone可能是[NSTimeZone defaultTimeZone][NSTimeZone localTimeZone][NSTimeZone systemTimeZone]干脆。

它实际上anotherComponents是在新时区保存时间。您会发现anotherDate它等于i_date,因为它以格林尼治标准时间(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;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.