2009-08-12 13 views
8

ho la mia C++ DateTime classe definita come:C++ DateTime classe

class DateTime 
{ 
public: 
    int year; 
    int month; 
    int day; 
    int hour; 
    int min; 
    int sec; 
    int millisec; 
}; 

Ho 2 DateTime che ho bisogno di confrontare per vedere quale è più grande di (più recente) l'altra.

C'è qualche liberamente disponibili C++ DateTime classe che posso usare per

  1. Convertire mia classe DateTime alla loro classe DateTime
  2. loro classe dovrebbe fornire <,>, < =,> = operatori per il confronto

Se un esempio concreto potrebbe essere fornito che sarebbe bello. Si noti che ho bisogno di confrontare fino al millisecondo.

Stavo pensando a Boost o Qt. Preferito Boost.

+3

Se hai la tua classe, perché ne hai bisogno di un'altra? –

+7

O, ancora più importante, se stai per utilizzare la classe di qualcun altro, perché usarlo solo per i confronti? Usa la loro classe. Il lavoro è fatto per te. Abbandona la tua classe. – GManNickG

+0

Il motivo è perché la mia applicazione è una libreria C++ che verrà utilizzata da un'altra applicazione. 1) Non voglio che debbano includere librerie Boost per far uso della mia libreria. 2) Questa classe DateTime è già stata utilizzata in molti posti di un sistema legacy. Grazie per i commenti però. – sivabudh

risposta

18

Vedi Boost Date Time library

E la classe assomiglia molto struct tm

EDIT: Hai ragione che struct tm non supporta la precisione millisecondo.

Dai un'occhiata a Boost example. Questo aiuta?

+0

ho già dato un'occhiata a quella documentazione ... ma era così denso. anche io non sono riuscito a trovare un esempio con millisec. stavo cercando un esempio lungo questa linea: http://doc.trolltech.com/4.5/qdatetime.html. – sivabudh

+0

è vero che la mia classe è molto simile a struct tm ... tuttavia, la distinzione cruciale è che ho anche un campo millisecondo. – sivabudh

+0

struct tm non supporta i millisecondi poiché è una cosa POSIX e il normale tempo di stile UNIX viene assegnato solo al secondo. –

2

Cosa c'è di sbagliato nell'usare il contenuto di <time.h> per l'implementazione della classe? È standard C90.

+0

non c'è niente di sbagliato in questo ... potresti per favore fornire un esempio di come potrei usare l'? – sivabudh

+3

Questo è C++. Questo dovrebbe essere '#include ' – GManNickG

5

Non so di alcun fuori dalla parte superiore della mia testa. Ma considererei la riscrittura della classe data per contenere un singolo intero a 64 bit che descrive millisecondi dall'epoca convenzionale (1970 è?). Quindi sei libero di dividere semplicemente per 1000 e utilizzare le normali funzioni CRT per la formattazione come stringa, inoltre puoi prendere il valore modulo 1000 per ottenere la parte in millisecondi.

operatori di confronto poi diventato facile ..

+0

Vorrei raccomandare qualcosa di simile. Memorizza internamente i tempi come un numero intero come questo, in modo che i confronti siano facili e quindi fornisci agli utenti l'accesso per ottenere le varie parti del tempo di interruzione (ora, mese, ecc.). Se l'efficienza è un problema, puoi memorizzare nella cache il tempo di interruzione fino a quando non viene modificato l'orario interno, in modo da non dover continuare a ricalcolare l'anno per ottenere il mese, ecc. –

+0

Cioè, se non stai pianificando usare boost. –

+0

Se solo potessi passare più di una volta ... – phonetagger

8

Si consiglia di controllare QDateTime da Qt, che vanta gli operatori necessari e la precisione ms.

conversione dalla classe potrebbe essere fatto tramite

class DateTime 
{ 
public: 
    int year; 
    int month; 
    int day; 
    int hour; 
    int min; 
    int sec; 
    int millisec; 

    QDateTime toQDateTime() { 
    return QDateTime(QDate(year, month, day), QTime(hour, min, sec, millisec)); 
    } 
}; 

Il contrario è simile ;-)

1

GNU R utilizza una sostituzione struct tm con precisione microsecondo - invece di (intero) secondi sin dall'epoca utilizza ora un numero in virgola mobile. Questo è davvero molto utile. Per molte delle mie applicazioni, ho appena raddoppiato eppure ottengo le conversioni di tempo. Vedere R-2.9.1/src/main/datetime.c nelle sorgenti R correnti.

Avere che in una classe C++ autonoma sarebbe comunque utile.

4

Ok, ecco lo snippet di codice finale che risponde alla mia domanda. Ho pensato di condividerlo nel caso in cui potrebbe essere utile per altre persone in futuro. Grazie a Fred Larson per aver indicato l'esempio Boost.

Ho scelto Boost per eseguire il calcolo DateTime perché la mia applicazione utilizza già Boost da qualche altra parte. Penso che avrei potuto usare anche Qt, anche se non posso assolutamente confermarlo.

Supponendo DateTime è definito come:

class DateTime 
{ 
public: 
    int year; 
    int month; 
    int day; 
    int hour; 
    int min; 
    int sec; 
    int millisec; 
}; 

Per fare un semplice confronto DateTime

bool DateTime::operator < (const DateTime& dt_) 
{ 
    using namespace boost::posix_time; 
    using namespace boost::gregorian; 

    ptime thisTime(date(this->year,this->month,this->day), 
        hours(this->hour) + 
        minutes(this->min) + 
        seconds(this->sec) + 
        boost::posix_time::millisec(int(this->millisec))); 

    ptime thatTime(date(dt_.year,dt_.month,dt_.day), 
        hours(dt_.hour) + 
        minutes(dt_.min) + 
        seconds(dt_.sec) + 
        boost::posix_time::millisec(int(dt_.millisec))); 

    return thisTime < thatTime; 
} 

Per aggiungere 2 DateTime insieme per restituire un nuovo DateTime

DateTime DateTime::operator + (const DateTime& dt_) 
{ 
    using namespace boost::posix_time; 
    using namespace boost::gregorian; 

    date thisDate(this->year, this->month, this->day); 
    date newDate = thisDate + years(dt_.year) + months(dt_.month) + days(dt_.day); 

    ptime newDateTime(newDate, 
    hours(this->hour) + hours(dt_.hour) + 
    minutes(this->min) + minutes(dt_.min) + 
    seconds(this->sec) + seconds(dt_.sec) + 
    boost::posix_time::millisec(int(this->millisec)) + 
    boost::posix_time::millisec(int(dt_.millisec)) 
    ); 

    DateTime dateTime; 

    date t1_date = newDateTime.date(); 

    dateTime.year = t1_date.year(); 
    dateTime.month = t1_date.month(); 
    dateTime.day = t1_date.day(); 

    time_duration t1_time = newDateTime.time_of_day(); 

    dateTime.hour  = t1_time.hours(); 
    dateTime.min  = t1_time.minutes(); 
    dateTime.sec  = t1_time.seconds(); 
    dateTime.millisec = t1_time.fractional_seconds()/1000.0f; 

    return dateTime; 
} 
4

I fossa che memorizza le date in epoche gregoriane fa. Memorizzo le date come un numero intero a 32 bit (una specie di data giuliana). Quindi la data è composta da (Anno * 1000) + DOY (DOY è il giorno dell'anno). I.e. - 2.009.001 Is 1 gennaio 2009 - 2.009.365 è 31 Dicembre 2009

La mia classe data del corso fornisce metodi per ottenere l'anno, mese e giorno, aggiungendo, sottraendo, incremento e decremento, il confronto, ottenendo il numero di giorni tra date ecc.

Per la data e l'ora, utilizzo il float a 64 bit in cui la parte intera del numero reale è uguale alle date intero (simile a Julian) descritte sopra e la frazione rappresenta il tempo in frazione di un giorno.

I.e.

  • 2009001,04166666666 ~ è Jan 1,2009 1:00
  • 2009001,06249999999 ~ è Jan 1,2009 1:30
  • 2009001,95833333333 ~ è Jan 1,2009 11:00

Se solo bisogno di precisione minuscola, è possibile utilizzare 32bit float per data e ora, ma non è possibile in modo accurato memorizza secondi e millisecondi.

I vantaggi di memorizzazione di date (e tempo) in questo modo sono:

  • Hai solo bisogno 8bytes per rappresentare i dati e il tempo rispetto a 28bytes (supponendo interi a 32 bit) utilizzati dal DateTime classe nella domanda.

  • Rispetto date memorizzati come secondi da un'epoca, quando guardando il numero (ad esempio nel debugger) si può più o meno identificare dal il numero l'anno e il giorno dell'anno, e l'approssimativa ora del giorno (per ottenere l'ora, i minuti, il secondo dopo la mezzanotte semplicemente moltiplicare per 24, 1440, 86400 rispettivamente).

  • Confrontare le date è banale, è sufficiente confrontare i numeri (una singola operazione CPU rispetto ai diversi che avrebbe preso per l'esempio DateTime).

  • Meno operazioni di confronto per eseguire l'aritmetica della data.

Il disadvange di questo (per il tempo di tempo) è una leggera perdita di precisione (questo è praticamente un punto muto) e si deve fare qualche semplice arrotondamento per ottenere valori interi belle quando convering ai valori interi di ore minuti e secondi.

+0

Mi piace questo stile. –