NSDate - 将日期转换为GMT

Mic*_*ick 50 objective-c nsdate gmt ios swift

我需要能够将NSDate值转换为GMT日期.

如何将NSDate值转换为GMT格式的NSDate值,与iPhone设备使用的日期区域设置无关?

小智 132

    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.dateFormat = @"yyyy-MM-dd'T'HH:mm";

    NSTimeZone *gmt = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
    [dateFormatter setTimeZone:gmt];
    NSString *timeStamp = [dateFormatter stringFromDate:[NSDate date]];
    [dateFormatter release];
Run Code Online (Sandbox Code Playgroud)

  • 我想详细说明Olaf的评论,并补充说,NSDate描述不仅显示GMT中的日期/时间,而且timeIntervalSinceReferenceDate反映自GMT 2001-01-01以来的秒数(不在您当地的时区)也是. (2认同)

Ale*_*lex 42

在Cocoa中使用时间可能很复杂.获得NSDate对象时,它位于本地时区.[[NSTimeZone defaultTimeZone] secondsFromGMT]为您提供GMT当前时区的偏移量.然后你可以这样做:

NSDate *localDate = // get the date
NSTimeInterval timeZoneOffset = [[NSTimeZone defaultTimeZone] secondsFromGMT]; // You could also use the systemTimeZone method
NSTimeInterval gmtTimeInterval = [localDate timeIntervalSinceReferenceDate] - timeZoneOffset;
NSDate *gmtDate = [NSDate dateWithTimeIntervalSinceReferenceDate:gmtTimeInterval];
Run Code Online (Sandbox Code Playgroud)

现在gmtDate应该在GMT中拥有正确的日期.为了显示它,请NSDateFormatter特别注意setDateStylesetTimeStyle方法.您创建一个NSDateFormatter,按照您想要的方式配置它,然后调用stringFromDate:以获得格式良好的字符串.

  • 虽然这一开始似乎很好,但我强烈建议不要使用这种方法,这会导致很多混乱.日期表示单个时间点.问题是您需要此日期的不同*表示*.同一时间点在德里和纽约等地有不同的"名字".因此,要认真思考你的背景.您可以在UIDatePickers上设置calendar.timeZone属性以使它们使用其他时区,并且如Howard所示,您可以自定义日期格式化程序以使用不同的区域. (8认同)
  • NSDate对象表示一个时间点,与时区等无关......您永远不需要将NSDate转换为另一个...只有在您序列化(转换为字符串和从字符串转换)时才会出现时区/区域设置, GMT或其他考虑在内.霍华德的回答是正确的. (4认同)
  • NSTimeInterval gmtTimeInterval = [localDate timeIntervalSinceReferenceDate] - timeZoneOffset; 如果你在世界的+那边是误导,那么它应该是NSTimeInterval gmtTimeInterval = [localDate timeIntervalSinceReferenceDate] + timeZoneOffset; (2认同)
  • 我同意,这个例子中的代码不正确,导致我的应用程序中出现错误.然后我花了相当多的时间挖掘它,现在我明白了发生了什么.[NSDate date]为您提供在GMT内部存储的日期.如果您使用NSLog(@"%@",localDate),您会看到类似2012-12-06 15:22:45 +0000的内容; "+0000"表示GMT.此外,timeIntervalSinceReferenceDate值反映了自GMT时区*中2001-01-01*以来的当前秒数,正如我通过数学验证的那样.如果需要本地时间间隔,则必须添加时区偏移量. (2认同)

Aku*_*ete 16

霍华德的回答是正确的,请将其投票并接受.

作为参考,我认为解释日期对象和本地化日期表示之间的区别是有用的.

在许多编程语言中,日期对象用于表示独特的时间点.忽略相对论论证可以假设在任何情况下我们都可以定义一个时间点,对于每个时间点而言,无论我们如何测量时间,它都是普遍相同的.

如果我们可以为每个时间点构建一个唯一的标签,那么该标签可以被传递并明确引用.date对象的目的是作为给定时间点的唯一通用标签.

人们可以提出任何数量的技术来构建这样的标签方案,每个日期对象选择这样做的方式对使用它们的任何人来说都是无关紧要的.

一个例子可能是使用来自普遍事件的数字偏移(自太阳爆炸以来X秒).

只有当我们希望采用时间点并将其序列化为人类可读的字符串时,我们必须处理时区,语言环境等的复杂性......

(本地日期字符串)+(日期格式化程序)=>时间点

时间点+(日期格式化程序)=>(本地日期字符串)

每个时间点都是通用的... 只有在将时间点转换为本地字符串(使用日期格式化程序)时,才会出现纽约时间点gmt时间点,并且会出现与时区的任何关联.

注意:我确定在这个问题上有很多博客/文章,但是我的google foo在这个时候失败了.如果有人有热情扩展这个问题,请随时这样做.


the*_*oid 5

虽然亚历克斯的答案是一个良好的开端,但它没有处理夏令时(夏令时)并且在参考日期之外增加了不必要的转换.以下适用于我:

要将localDate转换为GMT,请考虑DST:

NSDate *localDate = <<your local date>>
NSTimeInterval timeZoneOffset = [[NSTimeZone systemTimeZone] secondsFromGMTForDate:localDate];
NSDate *gmtDate = [localDate dateByAddingTimeInterval:-timeZoneOffset]; // NOTE the "-" sign!
Run Code Online (Sandbox Code Playgroud)

要将GMT日期转换为localDate,请将DST考虑在内:

NSDate *gmtDate  = <<your gmt date>>
NSTimeInterval timeZoneOffset = [[NSTimeZone systemTimeZone] secondsFromGMTForDate:gmtDate];
NSDate *localDate = [gmtDate dateByAddingTimeInterval:timeZoneOffset];
Run Code Online (Sandbox Code Playgroud)

一个小注释:我使用了dateByAddingTimeInterval,它只是iOS 4.如果您使用的是OS 3或更早版本,请使用addTimerInterval.


Kru*_*nal 5

斯威夫特4

//UTC or GMT ? Local 

extension Date {

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

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

}
Run Code Online (Sandbox Code Playgroud)