2009-12-07 24 views
50

Necesito la capacidad de convertir un valor NSDate en una fecha GMT.NSDate - Convertir fecha a GMT

¿Cómo puedo hacer para convertir un valor de NSDate a un valor de NSDate con formato GMT, independientemente de la configuración regional de fecha que esté usando el dispositivo iPhone?

Respuesta

42

Trabajar con el tiempo en Cocoa puede ser complicado. Cuando obtiene un objeto NSDate, se encuentra en la zona horaria local. [[NSTimeZone defaultTimeZone] secondsFromGMT] le da el desplazamiento de la zona horaria actual desde GMT. A continuación, puede hacer esto:

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

Ahora gmtDate debe tener la fecha correcta en GMT para usted. Para mostrarlo, mira NSDateFormatter, específicamente los métodos setDateStyle y setTimeStyle. Crea un NSDateFormatter, configúrelo de la manera que desee y luego llame al stringFromDate: para obtener una cadena con un formato agradable.

+8

Si bien esto parece bueno en primer lugar, quiero a fuertemente consejos contra el uso de este método, que puede conducir a una gran confusión. Una fecha representa un solo punto en el tiempo. El problema es que quieres diferentes * representaciones * de esta fecha. El mismo punto en el tiempo tiene diferentes "nombres" en Delhi y en Nueva York, etc. Por lo tanto, piense mucho sobre cuál es su contexto. Puede establecer la propiedad calendar.timeZone en UIDatePickers para hacer que usen otra zona horaria, y como muestra Howard, puede personalizar los formateadores de fechas para que funcionen con diferentes zonas. – Felixyz

+4

Un objeto NSDate representa un punto en el tiempo, independientemente de la zona horaria, etc. ... nunca es necesario convertir un NSDate a otro ... solo la serialización (conversión ay desde cadenas) de la zona horaria/configuración regional, si GMT u otro viene en cuenta. La respuesta de Howards es correcta. – Akusete

+0

@Akusete otros puntos de serialización son UIDatePicker y NSCalendar. –

3

¿Ha intentado con mirar la documentación de NSDateFormatter?

NSDateFormatter

NSDateFormatter parece tener algunos métodos para jugar con TimeZones, particularmente

-setTimeZone:

no he probado yo mismo, pero me imagino que si se establece como la zona horaria GMT de una fecha que está originalmente representada en otra zona horaria, mostrará la fecha con los ajustes correctos para coincidir con la nueva zona horaria.

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

¿Funciona el DateFormatter con los códigos de tipo "% d" ... y con los códigos de tipo "d"? – Donna

+0

@Donna: el último NSDateFormatter usa el estándar UTS # 35. http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns. No funcionará con la sintaxis de estilo C de% d. – Akusete

+1

Tema antiguo, pero también animo a utilizar el enfoque de Howard en lugar de jugar con la fecha, como lo hacen algunas de las otras sugerencias. Vale la pena señalar que la "descripción" de un NSDate siempre está en GMT. Esto implica que un NSLog (@ "% @", [fecha de NSDate]) siempre muestra la fecha indicada en GMT también. –

5

Si bien la respuesta de Alex fue un buen comienzo, que no se ocupaba de horario de verano (horario de verano) y se añadió una conversión innecesaria a/desde la fecha de referencia. Las siguientes obras para mí:

convertir de un LocalDate a GMT, teniendo el horario de verano en cuenta:

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

convertir de una fecha GMT a una LocalDate, teniendo el horario de verano en cuenta:

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

Una pequeña nota: utilicé dateByAddingTimeInterval, que es solo iOS 4. Si está en OS 3 o anterior, use addTimerInterval.

+0

Esta es también una solución menos que ideal. Como señaló Felixyz en su respuesta a Alex, no querrás estar jugando con el NSDate en sí mismo sino con su representación. La respuesta de Howard dará una representación "localizada" de NSDate. –

+0

Un NSDate representa un punto en el tiempo, independiente de una zona horaria. Su objeto localDate representa el mismo punto que gmtDate. Cuando vaya a convertirlo en una cadena, deberá usar un DateFormatter en ambos y obtener los mismos resultados. – Akusete

+0

Ver respuesta de Howards. –

16

Howard's Answer es correcto y por favor vote y agréguela.

Como referencia, creo que es útil explicar la diferencia entre los objetos de fecha y las representaciones de fecha localizadas.

En muchos lenguajes de programación, los objetos de fecha se utilizan para representar puntos únicos en el tiempo. Ignorando los argumentos de Relativistic se puede suponer que en cualquier instancia podemos definir un punto en el tiempo que sea universal para todos, independientemente de cómo midamos el tiempo.

Si para cada punto en el tiempo pudiéramos construir una etiqueta única, esa etiqueta podría pasarse y referenciarse sin ambigüedades.El objetivo de los objetos de fecha es actuar como una etiqueta universal única para un punto dado en el tiempo.

Uno puede inventar cualquier cantidad de técnicas para construir un esquema de etiquetado así y la forma en que cada objeto de fecha elige hacerlo es irrelevante para cualquiera que lo use.

Un ejemplo puede ser utilizar un desplazamiento numérico de un evento universal (X segundos desde que el sol explotó).

Es sólo cuando se quiere tomar un punto de tiempo y serializar en una cadena legible por humanos que tenemos que hacer frente a las complejidades de las zonas horarias, locales, etc ...

(Fecha Local cadena) + (Fecha formateador) => Tiempo Punto

Tiempo Punto + (Fecha formateador) => (cadena de fecha local)

Cada vez que el punto es universal ... no existe un new york time point, o gmt time point, solo una vez que convierte un punto de tiempo en una cadena local (usando un formateador de fecha) hace cualquier asociación a una zona horaria aparece.

Nota: Estoy seguro de que hay muchos blogs/artículos sobre este tema, pero mi google foo me está fallando a esta hora. Si alguien tiene el entusiasmo de ampliar este tema, siéntase libre de hacerlo.

+0

Digamos que hay un servidor que dice que solo calculo y trabajo en horarios GMT y no entretiene el concepto de zonas horarias. Básicamente, hará lo mismo de lo que estás hablando. Todo el manejo de la zona horaria se puede hacer en el cliente. El servidor funciona en un punto de referencia único. – 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) 
    } 

} 
Cuestiones relacionadas