2013-05-14 11 views
11

Mam pewną dowolną epokę, jak 13 lipca 1988 roku. Zasadniczo chcę zmierzyć czas w stosunku do tego. Zastanawiałem się nad napisaniem niestandardowej klasy zegara, aby móc napisać kod:Jak utworzyć niestandardowy zegar do użycia w funkcjach std :: chrono?

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

Czy to możliwe? Jeśli nie, jaki jest najczystszy sposób, aby to osiągnąć?

+0

Założę się, że standard ma wymienione wymagania. – chris

+0

'time_point' akceptuje' Clock' jako szablon, który jest pojęciem. Możesz po prostu napisać własną klasę, która spełnia wymagania narzucone przez tę konkretną koncepcję. Ale nie wierz mi na słowo, po prostu myślę głośno. –

+0

@DanielKamilKozar Zajrzałem do źródła system_clock na przykład, ale nie za bardzo się posunąłem. Nie widzę, gdzie określona jest aktualna epoka. Myślę, że to zależy od systemu. Gdzie znajdę dokumentację, jak zrobić coś takiego? – sagargp

Odpowiedz

22

Trudną częścią napisania tego niestandardowego zegara jest ustalenie, jak napisać jego funkcję now(). W poniższym przykładzie podstawię now() off of system_clock 's . Najpierw wykonuję pracę detektywistyczną, aby odkryć, że moja system_clock ma epokę Nowego Roku 1970, zaniedbując leap seconds. Jest to znane jako unix time. Jak się okazuje, każda implementacja, o której wiem (i myślę, że sprawdziłem wszystkie), ma tę samą epokę (ale nie jest to określone w standardzie C++ 11).

Następnie obliczam, że 1988-07-13 to 6768 dni po 1970-01-01. Stosując te dwa fakty, reszta jest prosta:

#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 potrzeby zagnieżdżone typedefs opisać jego duration, rep, period i time_point. Na podstawie Twojego pytania wybrałem seconds jako duration, ale możesz wybrać, co chcesz.

Dla funkcji now() po prostu nazywam system_clock::now() i odejmuję epokę w jednostkach sekund. Z tą kalkulacją zrobiłem trochę sprytnie, pisząc wszystko pod kątem MyClock::duration, dzięki czemu mogę łatwiej zmienić duration. Zauważ, że udało mi się odjąć epokę pod względem hours, która niejawnie przekształca się w duration (która jest seconds). Ewentualnie mogę zbudowali sobie zwyczaj duration dni:

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

a następnie powrót now() mogło być napisane:

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

W każdym razie, teraz można korzystać z tego rodzaju:

#include <iostream> 

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

co dla mnie po prostu wydrukować:

786664963 

Co pokazuje, że dzisiaj (2013-06-16) wynosi około 24,9 lat po 1988-07-13.

+0

To jest niesamowite, dokładnie to, czego potrzebowałem. Dzięki! – sagargp

Powiązane problemy