2009-12-07 142 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) 
    } 

}