2010-11-03 9 views
6

Sto scrivendo una categoria in Xcode, che estenderebbe l'attuale classe NSDate. Voglio aggiungere due metodi che uso regolarmente e in qualche modo non riesco a farli funzionare correttamente.Ottenere NSDate per oggi con 00:00:00 come orario

Attualmente ho questo codice:

+ (NSDate*) today 
{ 
    NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; 

    NSDateComponents *todayComponents = [gregorian components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:[NSDate date]]; 
    NSInteger theDay = [todayComponents day]; 
    NSInteger theMonth = [todayComponents month]; 
    NSInteger theYear = [todayComponents year]; 

    NSDateComponents *components = [[NSDateComponents alloc] init]; 
    [components setDay:theDay]; 
    [components setMonth:theMonth]; 
    [components setYear:theYear]; 

    NSDate* todayDate = [gregorian dateFromComponents:components]; 

    [components release]; 
    [gregorian release]; 

    return todayDate; 
} 

voglio che per restituire un data così: "2010-11-03 00:00:00 +01". Ma in qualche modo il fuso orario continua a buggin me, perché questo codice restituisce "2010-11-02 23:00:00 +0000".

Qualcuno può dirmi come risolvere questo codice per restituire effettivamente la data corretta? Oppure posso usare questa data e la mia applicazione la convertirà automaticamente a causa del fuso orario impostato sulla macchina.

Devo registrare determinati eventi nella mia app in un database, che utilizza anche il metodo [Data NSDate]. Significa che il metodo [Data NSDate] usa anche il tempo senza informazioni sul fuso orario?

MODIFICA: Penso che abbia qualcosa a che fare con il bug del tempo di risparmio di luce del giorno. Le cose che vedo sono esattamente le stesse che hanno le app di Clock, con il bug che fa svegliare la gente tardi. Inoltre, il fuso orario predefinito è il fuso orario attualmente impostato sul dispositivo, quindi dovrebbe rimanere invariato finché non si modifica il fuso orario nella schermata delle impostazioni.

EDIT2: Ok, qualche altro test:

NSLog(@"CurrentDate: %@", [NSDate date]); 
NSLog(@"TZ: %@", [NSTimeZone defaultTimeZone]); 

mi dà i seguenti risultati:

2010-11-03 23:23:49.000 App[8578:207] CurrentDate: 2010-11-03 22:23:49 +0000 
2010-11-03 23:23:49.001 App[8578:207] TZ: Europe/Amsterdam (GMT+01:00) offset 3600 

risposta

5

Vedi Using Time Zones. Ti consigliamo di impostare il fuso orario del calendario utilizzando il metodo -setTimeZone: di NSCalendar prima di iniziare a chiederlo per le date.

+0

Nozzi ... davvero? Mi stai seguendo? : P. Penso che abbia qualcosa a che fare con il bug del tempo di risparmio Daylight. Le cose che vedo sono esattamente le stesse che hanno le app di Clock, con il bug che fa svegliare la gente tardi. –

+0

Non conosco questa persona @jnozzi su Twitter che hai menzionato. Che cosa? Non hai menzionato? DANNAZIONE! Oh bene, sì, sono io. ;-) Hmm. Non ne ho sentito parlare. Potrebbe voler taggare l'iPhone quando si utilizza la roba di base, poiché Mac/iOS non è chiaro in questi casi. :-) –

+0

Muhaha, so dove trovarti ovunque. Aggiornato di nuovo il mio post. Devo davvero aggiungere quell'offset quando chiamo [data NSDate]? Speravo che il sistema operativo lo avrebbe fatto automaticamente. –

0

Per quanto posso vedere, è la risposta corretta se il fuso orario è GMT + 1. A mezzanotte il tuo tempo è alle 23:00 del giorno precedente in GMT.

Il problema è probabilmente nella formattazione della data restituita per l'output. Ti viene fornita una stringa per GMT anziché le impostazioni internazionali correnti.

1

Sto ancora cercando di capire esattamente perché questo errore si verifica, ma conosco una soluzione. Impostare il fuso orario del tuo NSCalendar su GMT prima di inviarlo dataFromComponents: risolverà il problema.

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

PS se c'è una soluzione diversa che trovate su suggerimento di Joshua, potrebbe farci sapere di cosa si tratta? Sembra che tu abbia risolto il problema da quando hai accettato la sua risposta, ma non è chiaro cosa hai fatto. Grazie!

3

Questa è una domanda interessante e ho lavorato a una soluzione per molte ore. Questi sono i miei risultati:

NSLog(@"CurrentDate: %@", [NSDate date]); 

il codice mostrato sopra avrà lo stesso risultato il codice riportato di seguito:

NSLog(@"CurrentDate: %@", [[NSDate date] description]); 

Leggendo il NSDate Class Reference produce questa documentazione sul metodo del NSDatedescription.

La rappresentazione non è garantita per rimanere costante tra diverse versioni del sistema operativo. Per formattare una data, è necessario utilizzare un oggetto data formattatore invece (vedi NSDateFormatter e dati Formattazione)

Inoltre ho fatto funzionare all'interno della documentazione per descriptionWithLocale: (id) locale:

“restituisce una rappresentazione di stringa del ricevitore utilizzando la data locale.”

Quindi, cambiare il codice

NSLog(@"CurrentDate: %@", [NSDate date]); 

A:

NSLog(@"CurrentDate: %@", [[NSDate date] descriptionWithLocale:[NSLocale currentLocale]]); 

che dovrebbe sfociare in quello che stai cercando. E posso anche provare che la data corretta è [NSDate date], ma viene visualizzata solo con il metodo sbagliato:

Possiamo usare lo [today] (Wim Haanstra) per creare due date.

dateLastDay: 2010-11-02 23:59:00 +01
dateToday: 2010-11-03 24:01:00 +01

Poi usiamo il codice qui sotto per mostrare le due date:

NSLog(@"CurrentDate: %@", dateLastDay); 
NSLog(@"CurrentDate: %@", dateToday); 

O:

NSLog(@"CurrentDate: %@", [dateLastDay description]); 
NSLog(@"CurrentDate: %@", [dateToday description]); 

I due gruppi mostrano gli stessi risultati, come questo: "2010-11- 22:59:00 +0000" e "2010-11- 23:01:00 +0000". Sembra che le due date abbiano lo stesso "giorno", ma in realtà?

Ora confrontiamo i giorni delle date:

NSCalendar *gregorian = [[NSCalendar alloc] 
         initWithCalendarIdentifier:NSGregorianCalendar]; 

NSUInteger unitFlags = NSDayCalendarUnit; 
NSDateComponents *lastDayComponents = [gregorian components:unitFlags fromDate:dateLastDay]; 
NSDateComponents *todayComponents = [gregorian components:unitFlags fromDate:dateToday]; 
NSInteger lastDay = [lastDayComponents day]; 
NSInteger today = [todayComponents day]; 

return (lastDay == today) ? YES : NO; 

Avremo NO! Anche se le due date sembrano avere lo stesso giorno, mese e anno, NON lo fanno. Appare solo in questo modo perché li abbiamo mostrati nel modo sbagliato.

2

Hai provato utilizzando:

NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 
[formatter setDateFormat:@"yyyy-MM-dd"]; 
todayAtOO = [formatter dateFromString:[formatter stringFromDate:[NSDate date]]]; 
Problemi correlati