2012-06-30 18 views
9

Sto cercando di utilizzare NSDateFormatter nella mia app che prende una stringa di data e la formatta in un NSDate in modo che io possa fare i confronti Data, tuttavia sto trovando quando uso dateFromString e formatta la data è perdere un giorno.Data NSDateFormatterFromString restituisce data errata

NSString *dateString = @"02-06-2012"; 
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 
[dateFormatter setDateFormat:@"dd-MM-yyyy"]; 
NSDate *dateFromString = [[NSDate alloc] init]; 
dateFromString = [dateFormatter dateFromString:dateString]; 
NSLog(@"My Date = %@", dateFromString); 
[dateFormatter release]; 

Emette alla console:

My Date = 2012-06-01 23:00:00 +0000

risposta

19

I Non credere che la risposta di Dhruv sia corretta. In realtà, non è chiaro se ci siano problemi. Sembra che tu abbia un'aspettativa errata su ciò che dovrebbe accadere e/o sull'interpretazione di ciò che sta accadendo.

NSDate rappresenta un momento nel tempo. Questo momento non ha un nome unico. Sarà conosciuto con nomi diversi in luoghi diversi e con diversi sistemi di denominazione (fusi orari, calendari). NSDate non tratta nulla di ciò, ad eccezione del metodo -description, dove deve produrre una rappresentazione di stringa di quel momento.

In secondo luogo, una stringa come "02-06-2012" non specifica un momento preciso nel tempo. Prima di tutto, è solo una data senza informazioni sull'orario, quindi NSDateFormatter è impostato per default al primo momento per quella data. In secondo luogo, non specifica il fuso orario. Il primo momento del giorno di calendario è un momento diverso in ogni fuso orario. A meno che non si specifichi un fuso orario con -setTimeZone: o che la stringa stessa contenga informazioni sul fuso orario, NSDateFormatter presuppone che tutte le stringhe di data che si chiedono di analizzare si trovino nel fuso orario corrente.

Quindi, l'oggetto dateFromString rappresenta il primo momento della data specificata, 02-06-2012, nel fuso orario. Mi aspetto che questo sia quello che volevi. Tuttavia, ti sei confuso dal modo in cui NSDate si descrive da solo quando viene registrato. Come ho detto, lo NSDate deve scegliere un "nome" (rappresentazione stringa) per il momento in cui rappresenta e il nome scelto è abbastanza arbitrario. In questi giorni sta selezionando il nome con cui è noto il momento in UTC. Raccolgo dall'output del registro mostrato nella tua domanda che ti trovi a UTC + 0100. Quindi, la data potrebbe sembrare come se fosse un giorno prima, ma è davvero lo stesso momento specificato. In altre parole, "2012-06-01 23:00:00 +0000" e "2012-06-02 00:00:00 +0100" sono due nomi equivalenti esattamente per lo stesso momento nel tempo. Non sei abituato a vedere il primo e lo interpreti male.

La lezione è che devi smettere di fare affidamento sulla descrizione di NSDate in un particolare fuso orario. Davvero, non devi fare affidamento su nulla, dal momento che non è documentato. In effetti, i documenti per lo stato -[NSDate description], "La rappresentazione non è garantita per rimanere costante tra diverse versioni del sistema operativo."

soluzione di Dhruv sembra aiutare solo fatto che essa provoca NSDateFormatter e -[NSDate description] per concordare il fuso orario. Ma non è affidabile. Ad esempio, Snow Leopard non funzionava perché -[NSDate description] utilizzava il fuso orario locale anziché UTC in quella versione dei framework.

Ancora più importante, tuttavia, altera il momento reale rappresentato dall'oggetto che si ottiene dall'interpretazione della stringa di data da NSDateFormatter. Sospetto che tu voglia davvero che abbia un significato specifico - vuoi che la stringa venga interpretata come nel fuso orario locale - e la sua soluzione contrasta le tue intenzioni.

tl; dr: stavi ricevendo la data che volevi da sempre; non fare affidamento su -[NSDate description]; non utilizzare la soluzione di Dhruv

+0

Ciao Ken, Grazie per la risposta dettagliata, cosa consiglieresti di fare o usare? Nella mia app ho bisogno di controllare è uguale o maggiore di una specifica data hard coded che ho bisogno di inserire nella mia app. Grazie – MonkeyBlue

+1

Devi decidere in quale momento intendi veramente. La data codificata deve essere interpretata come in un determinato fuso orario fisso (come quello dell'ufficio principale della tua azienda)? O dovrebbe essere interpretato come nel fuso orario dell'utente? Se il primo, dovresti impostare il fuso orario fisso sul formattatore della data. Se è quest'ultimo, puoi lasciarlo come predefinito o puoi impostarlo esplicitamente su '[NSTimeZone defaultTimeZone]' (o '+ systemTimeZone'). –

+0

Grazie Ken, me ne occupo io - il tempo fissato è fondamentalmente una data specifica, quindi se apri l'App e la tua base in qualsiasi parte del mondo dovrebbe usare la data specifica e vedere se oggi è maggiore o uguale, stiamo facendo questo dato che dobbiamo mostrare diverse informazioni nella nostra app da una certa data. Anche la tua spiegazione ha più senso, quindi segnerò la tua risposta. Grazie – MonkeyBlue

49

Prova ad aggiungere queste righe al codice,

[dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT+0:00"]]; 

o

[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]]; 

SWIFT aggiornamento:

Codice da quetion,

let dateString = "02-06-2012" 
var dateFormatter = NSDateFormatter() 
dateFormatter.dateFormat = "dd-MM-yyyy" 
var dateFromString : NSDate = dateFormatter.dateFromString(dateString)! 
println("My Date \(dateFromString)") 

E Soluzione,

dateFormatter.timeZone = NSTimeZone(name: "GMT") 

O

dateFormatter.timeZone = NSTimeZone(abbreviation: "GMT+0:00") 
+0

Grazie è perfetto. – MonkeyBlue

+0

Non sarebbe una soluzione non generica? Cosa succede se il dispositivo non è su GMT? – Stavash

+4

@stavash Questo è il punto, GMT è lo stesso di UTC o Universal Time. È il fuso orario standardizzato che tutti possono utilizzare e non cambia mai (a causa dell'ora legale, ecc.). Ecco come iOS memorizza le date/gli orari ... – lnafziger

Problemi correlati