2009-12-07 89 views
50

Tôi cần khả năng chuyển đổi giá trị NSDate thành Ngày GMT.NSDate - Chuyển đổi ngày thành GMT

Làm cách nào để chuyển đổi giá trị NSDate thành giá trị GMT NSDate, độc lập với bất kỳ cài đặt ngôn ngữ ngày nào mà thiết bị iPhone đang sử dụng?

Trả lời

42

Làm việc với thời gian ở Ca cao có thể phức tạp. Khi bạn nhận được đối tượng NSDate, nó sẽ ở múi giờ địa phương. [[NSTimeZone defaultTimeZone] secondsFromGMT] cho phép bạn bù đắp múi giờ hiện tại từ GMT. Sau đó, bạn có thể làm điều này:

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

Bây giờ gmtDate nên có đúng ngày trong giờ cho bạn. Để hiển thị, hãy xem NSDateFormatter, cụ thể là các phương pháp setDateStylesetTimeStyle. Bạn tạo một NSDateFormatter, định cấu hình theo cách bạn muốn và sau đó gọi stringFromDate: để nhận chuỗi được định dạng độc đáo.

+8

Trong khi điều này có vẻ tốt lúc đầu, tôi muốn lời khuyên mạnh mẽ chống lại sử dụng phương pháp này, có thể dẫn đến rất nhiều sự nhầm lẫn. Một ngày đại diện cho một điểm duy nhất trong thời gian. Vấn đề là bạn muốn các đại diện * khác nhau * của ngày này. Cùng một điểm trong thời gian có khác nhau "tên" ở Delhi và ở New York, vv Vì vậy, suy nghĩ khó khăn về những gì bối cảnh của bạn. Bạn có thể đặt thuộc tính calendar.timeZone trên UIDatePickers để làm cho chúng sử dụng múi giờ khác và như Howard hiển thị, bạn có thể tùy chỉnh định dạng ngày để làm việc với các vùng khác nhau. – Felixyz

+4

Một đối tượng NSDate đại diện cho một điểm trong thời gian, độc lập với múi giờ vv ... bạn không bao giờ cần phải chuyển đổi NSDate sang ... ... chỉ khi bạn tuần tự hóa (chuyển đổi thành và từ chuỗi) là múi giờ/miền địa phương, cho dù GMT hay khác có tính đến. Howards trả lời là chính xác. – Akusete

+0

@ Bỏ qua các điểm tuần tự hóa khác là UIDatePicker và NSCalendar. –

3

Bạn đã thử xem tài liệu về NSDateFormatter chưa?

NSDateFormatter

NSDateFormatter dường như có một số phương pháp để chơi với các múi giờ, đặc biệt là

-setTimeZone:

tôi đã không kiểm tra nó bản thân mình, nhưng tôi tưởng tượng rằng nếu bạn đặt giờ như các múi giờ trên một ngày ban đầu được trình bày trong một múi giờ khác, nó sẽ hiển thị ngày với các điều chỉnh chính xác để phù hợp với múi giờ mới.

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 có hoạt động với cả hai loại mã "% d" ... và chỉ các mã kiểu "d" không? – Donna

+0

@Donna: NSDateFormatter mới nhất sử dụng tiêu chuẩn UTS # 35. http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns. Nó sẽ không hoạt động với cú pháp% d kiểu C. – Akusete

+1

Chủ đề cũ, nhưng tôi cũng khuyến khích sử dụng phương pháp tiếp cận của Howard thay vì làm rối tung với ngày chính nó như một số gợi ý khác làm. Đáng chú ý là "mô tả" của một NSDate luôn trong GMT. Điều này ngụ ý rằng một NSLog (@ "% @", [ngày NSDate]) luôn hiển thị ngày đã cho trong GMT. –

5

Trong khi câu trả lời của Alex là khởi đầu tốt, nó không xử lý DST (giờ tiết kiệm ánh sáng ban ngày) và thêm chuyển đổi không cần thiết vào/từ ngày tham chiếu. Các công trình sau đây cho tôi:

Để chuyển đổi từ một LOCALDATE lấy múi giờ GMT, lấy DST vào tài khoản:

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

Để chuyển đổi từ một ngày giờ để một LOCALDATE, lấy DST vào tài khoản:

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

Một lưu ý nhỏ: Tôi đã sử dụng dateByAddingTimeInterval, chỉ có iOS 4. Nếu bạn đang sử dụng OS 3 hoặc cũ hơn, hãy sử dụng addTimerInterval.

+0

Đây cũng là giải pháp ít lý tưởng. Như Felixyz đã chỉ ra trong phản ứng của mình đối với Alex, bạn không muốn bị rối tung với NSDate mà là đại diện của nó. Câu trả lời của Howard sẽ cung cấp cho một đại diện "bản địa hóa" của NSDate. –

+0

Một NSDate đại diện cho một điểm trong thời gian, độc lập của một múi giờ. Đối tượng localDate của bạn đại diện cho cùng một điểm với gmtDate. Khi bạn chuyển đổi nó thành một chuỗi, bạn vẫn sẽ cần sử dụng DateFormatter trên cả hai và nhận được kết quả tương tự. – Akusete

+0

Xem Howards trả lời. –

16

Howard's Answer là chính xác và vui lòng bỏ phiếu và chấp nhận.

Để tham khảo, tôi nghĩ hữu ích khi giải thích sự khác biệt giữa các đối tượng ngày tháng và biểu diễn ngày được bản địa hóa là gì.

Trong nhiều ngôn ngữ lập trình ngày, các đối tượng được sử dụng để thể hiện các điểm độc đáo theo thời gian. Bỏ qua các đối số Relativistic có thể giả định rằng ở bất kỳ trường hợp nào, chúng ta có thể xác định một điểm trong thời gian bằng nhau cho mọi người, bất kể chúng ta đo thời gian như thế nào.

Nếu cho mỗi thời điểm chúng ta có thể xây dựng một nhãn duy nhất, nhãn đó có thể được truyền đi xung quanh và được tham chiếu một cách rõ ràng.Mục đích của các đối tượng ngày tháng là hoạt động như một nhãn chung duy nhất cho một điểm nhất định trong thời gian.

Người ta có thể đưa ra bất kỳ số kỹ thuật nào để xây dựng một lược đồ ghi nhãn và cách mỗi đối tượng ngày chọn làm như vậy là không quan trọng đối với bất kỳ ai sử dụng chúng.

Ví dụ có thể là sử dụng bù đắp số từ sự kiện chung (X giây kể từ khi mặt trời phát nổ).

Nó chỉ là khi chúng ta muốn tham gia một thời điểm và serialize nó thành một chuỗi có thể đọc được con người mà chúng ta phải đối phó với sự phức tạp của các múi giờ, miền địa phương, vv ...

(ngày Local Chuỗi) + (ngày Formatter) => Thời gian Point

Time Point + (ngày Formatter) => (địa phương ngày Chuỗi)

Mọi điểm thời gian là phổ quát ... không có điểm nào là điểm thời gian new york hoặc thời gian gmt, chỉ khi bạn chuyển đổi điểm thời gian thành chuỗi cục bộ (sử dụng trình định dạng ngày) đến một múi giờ xuất hiện.

Lưu ý: Tôi chắc chắn có rất nhiều blog/bài viết về vấn đề này, nhưng google foo của tôi không làm tôi vào giờ này. Nếu bất cứ ai có sự nhiệt tình để mở rộng về vấn đề này xin vui lòng làm như vậy.

+0

Hãy nói rằng có một máy chủ mà nói rằng tôi chỉ tính toán và làm việc trên giờ GMT và không giải trí các khái niệm về múi giờ. Về cơ bản nó sẽ làm cho cùng một điều bạn đang nói đến. Tất cả việc xử lý múi giờ có thể được thực hiện trên máy khách. Máy chủ hoạt động trên một điểm tham chiếu duy nhất. – penduDev

2

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

} 
Các vấn đề liên quan