2009-12-07 53 views
50

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

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

回答

42

在可可中使用时间可能很复杂。当你得到一个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]; 

现在gmtDate应该在格林尼治标准时间正确的日期为您服务。为了显示它,请看NSDateFormatter,特别是setDateStylesetTimeStyle方法。你创建一个NSDateFormatter,按照你想要的方式进行配置,然后调用stringFromDate:来得到一个很好格式化的字符串。

+8

虽然这看起来不错,首先,我要对使用这种方法,这会导致很多混乱的强烈建议。日期代表单个时间点。问题是你需要这个日期的不同*表示*。同样的时间点在德里和纽约等地有不同的“名称”。因此,请认真思考你的背景是什么。您可以在UIDatePickers上设置calendar.timeZone属性,使其使用另一个时区,如Howard所示,您可以自定义日期格式化程序以使用不同的区域。 – Felixyz 2010-04-25 09:50:33

+4

NSDate对象表示一个时间点,与时区等无关......您永远不需要将NSDate转换为另一个......只有当您序列化(转换为字符串和从字符串转换)时区/区域设置时,是否考虑GMT或其他。霍华德的回答是正确的。 – Akusete 2010-08-09 21:53:39

+0

@Akusete其他序列化点是UIDatePicker和NSCalendar。 – 2011-07-08 08:07:54

3

你有没有试过看NSDateFormatter的文档?

NSDateFormatter

NSDateFormatter显得有一些方法与时区玩,特别是

-setTimeZone:

我没有测试它自己,但我想,如果你设定GMT的时区一个最初在另一个时区表示的日期,它将显示具有正确调整的日期以匹配新时区。

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

DateFormatter是否可以同时使用“%d”类型的代码...和只是“d”类型的代码? – Donna 2010-01-27 04:16:52

+0

@Donna:最新的NSDateFormatter使用UTS#35标准。 http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns。它不适用于C风格的%d语法。 – Akusete 2010-08-09 21:59:01

+1

旧的线程,但我也鼓励使用霍华德的方法,而不是像其他建议一样搞乱日期本身。 值得注意的是,NSDate的“描述”始终在GMT。这意味着NSLog(@“%@”,[NSDate date])总是以GMT显示给定的日期。 – 2011-11-29 22:02:03

5

虽然Alex的答案是一个良好的开端,它没有处理DST(夏令时间),并增加了不必要的转换到/距基准日期。对我来说,以下工作:

要从LOCALDATE的到GMT转换,同时DST考虑:

NSDate *localDate = <<your local date>> 
NSTimeInterval timeZoneOffset = [[NSTimeZone systemTimeZone] secondsFromGMTForDate:localDate]; 
NSDate *gmtDate = [localDate dateByAddingTimeInterval:-timeZoneOffset]; // NOTE the "-" sign! 

要从GMT日期转换为LOCALDATE的,同时DST考虑:

NSDate *gmtDate = <<your gmt date>> 
NSTimeInterval timeZoneOffset = [[NSTimeZone systemTimeZone] secondsFromGMTForDate:gmtDate]; 
NSDate *localDate = [gmtDate dateByAddingTimeInterval:timeZoneOffset]; 

小记:我使用了dateByAddingTimeInterval,它只是iOS 4。如果您使用OS 3或更早版本,请使用addTimerInterval。

+0

这也不是理想的解决方案。正如Felixyz在对Alex的回应中指出的那样,你不想干扰NSDate本身,而是想要表达自己的想法。霍华德的回答将给出NSDate的“本地化”表示。 – 2010-08-09 21:49:59

+0

NSDate表示一个时间点,与时区无关。您的对象localDate表示与gmtDate相同的点。当你将它转换为字符串时,你仍然需要在两者上使用DateFormatter,并获得相同的结果。 – Akusete 2010-08-09 21:57:05

+0

查看Howards的回答。 – 2011-07-18 16:33:38

16

Howard's Answer是正确的,请投它并接受它。

仅供参考我认为这有助于解释日期对象和本地化日期表示之间的区别。

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

如果对于每个时间点我们都可以构建一个独特的标签,那么该标签可以被传递并被明确地引用。日期对象的目的是作为给定时间点的唯一通用标签。

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

一个示例可能是使用来自通用事件(X秒自太阳爆炸以来)的数字偏移量。

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

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

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

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

注意:我确信有很多关于这个问题的博客/文章,但是我的谷歌foo在这个小时并没有让我失望。如果有人有这个问题的热情扩大,请随时这样做。

+0

假设有一台服务器说我只计算和工作在GMT时间,并没有考虑时区的概念。它基本上会让你在谈论同样的事情。所有的时区处理都可以在客户端完成。服务器在独特的参考点上工作。 – penduDev 2015-02-09 11:17:23

2

斯威夫特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) 
    } 

}