2013-05-14 9 views
11

Ho un'epoca arbitraria, come il 13 luglio 1988. In sostanza, voglio misurare il tempo relativo a questo. Stavo pensando di scrivere una classe di orologio personalizzata, in modo che potessi scrivere un codice come questo:Come creare un orologio personalizzato per l'uso nelle funzioni std :: chrono?

using std::chrono; 
time_point<My_Clock> tp; 
std::cout << duration_cast<seconds>(tp.time_since_epoch()).count() << std::endl; 

È possibile? In caso contrario, qual è il modo più pulito per realizzare questo?

+0

Scommetto che lo standard ha requisiti elencati. – chris

+0

'time_point' accetta' Orologio' come modello, che è un concetto. Potresti semplicemente scrivere la tua classe che soddisfa i requisiti imposti da quel particolare concetto. Ma non fidarti della mia parola, sto solo pensando ad alta voce. –

+0

@DanielKamilKozar Ho cercato nell'origine system_clock come esempio, ma non sono andato molto lontano. Non vedo dove sia specificata l'epoca attuale. Penso che sia dipendente dal sistema. Dove troverei la documentazione su come fare qualcosa del genere? – sagargp

risposta

22

La parte difficile di scrivere questo orologio personalizzato è capire come scrivere la sua funzione now(). Nell'esempio seguente, il now() è basato sullo now()now(). Per prima cosa faccio un po 'di lavoro investigativo per scoprire che il mio system_clock ha un'epoca di New Years 1970, trascurando lo leap seconds. Questo è noto come unix time. A quanto pare, ogni implementazione di cui sono a conoscenza (e penso di averli controllati tutti) ha questa stessa epoca (ma non è specificata dallo standard C++ 11).

Successivamente ho calcolato che 1988-07-13 è 6768 giorni dopo 1970-01-01. L'utilizzo di questi due fatti, il resto è facile:

#include <chrono> 

struct My_Clock 
{ 
    typedef std::chrono::seconds    duration; 
    typedef duration::rep      rep; 
    typedef duration::period     period; 
    typedef std::chrono::time_point<My_Clock> time_point; 
    static const bool is_steady =    false; 

    static time_point now() noexcept 
    { 
     using namespace std::chrono; 
     return time_point 
      (
      duration_cast<duration>(system_clock::now().time_since_epoch()) - 
      hours(6768*24) 
     ); 
    } 
}; 

MyClock esigenze typedef annidati per descrivere la sua duration, rep, period e time_point. In base alla tua domanda, ho scelto seconds come duration, ma puoi scegliere qualsiasi cosa desideri.

Per la funzione , chiamo semplicemente il system_clock::now() e sottraggo l'epoca in unità di secondi. Ho ottenuto un po 'di intelligenza con questo calcolo scrivendo tutto in termini di MyClock::duration in modo da poter cambiare più facilmente duration. Si noti che sono stato in grado di sottrarre l'epoca in termini di hours, che converte implicitamente in duration (che è seconds). In alternativa avrei potuto costruita me una consuetudine duration di giorni:

typedef std::chrono::duration<int, std::ratio_multiply<std::chrono::hours::period, 
                 std::ratio<24>>> days; 

E poi il ritorno di now() avrebbe potuto essere scritto:

 return time_point 
      (
      duration_cast<duration>(system_clock::now().time_since_epoch()) - 
      days(6768) 
     ); 

In ogni caso, ora è possibile utilizzare questo tipo:

#include <iostream> 

int 
main() 
{ 
    using namespace std::chrono; 
    time_point<My_Clock> tp = My_Clock::now(); 
    std::cout << tp.time_since_epoch().count() << '\n'; 
} 

che per me appena stampati:

786664963 

Che dimostra che oggi (2013-06-16) è di circa 24,9 anni dopo 1988-07-13.

+0

Questo è fantastico, esattamente quello di cui avevo bisogno. Grazie! – sagargp

Problemi correlati