2009-11-07 16 views
17

Co chcę zrobić, to przekonwertować czas epoki (sekundy od północy 1/1/1970) na "rzeczywisty" czas (m/d/y: m: s)Konwersja czasu epoki na "prawdziwą" datę/czas

tej pory mam następujący algorytm, który do mnie czuje się trochę brzydki:

void DateTime::splitTicks(time_t time) { 
    seconds = time % 60; 
    time /= 60; 
    minutes = time % 60; 
    time /= 60; 
    hours = time % 24; 
    time /= 24; 

    year = DateTime::reduceDaysToYear(time); 
    month = DateTime::reduceDaysToMonths(time,year); 
    day = int(time); 
} 

int DateTime::reduceDaysToYear(time_t &days) { 
    int year; 
    for (year=1970;days>daysInYear(year);year++) { 
     days -= daysInYear(year); 
    } 
    return year; 
} 

int DateTime::reduceDaysToMonths(time_t &days,int year) { 
    int month; 
    for (month=0;days>daysInMonth(month,year);month++) 
     days -= daysInMonth(month,year); 
    return month; 
} 

można założyć, że członkowie seconds, minutes, hours, month, day i year ogóle istnieje.

Używanie pętli for do modyfikowania oryginalnego czasu wydaje się nieco dziwne i zastanawiałem się, czy istnieje "lepsze" rozwiązanie tego problemu.

+1

OK, więc wiem, że szukasz rozwiązania proceduralnego ... ale jeśli jeszcze go nie widziałeś, sprawdź http://www.epochconverter.com. Jest to bardzo przydatny sposób sprawdzenia twojej pracy :) – Tom

+0

Co jest złego w zwykłym wywołaniu tej funkcjonalności wyeksponowanym przez 'time.h', np. autor: [gmtime] (http: //www.cplusplus.com/reference/clibrary/ctime/gmtime /) czy GMT, a nie jakaś konkretna strefa czasowa, jest tym, o co prosisz? –

+0

Nic w tym złego, nawet nie wiedziałem, że istnieje. Dzięki! Ale nadal jestem zainteresowany tym, jak moja implementacja może być lepsza. –

Odpowiedz

17

Uważaj na lata przestępne w swojej funkcji DaysInMonth.

Jeśli chcesz uzyskać bardzo wysoką wydajność, możesz wstępnie obliczyć parę, aby uzyskać miesiąc + rok w jednym kroku, a następnie obliczyć dzień/godzinę/min/sekundę.

Dobrym rozwiązaniem jest jeden w gmtime source code:

/* 
* gmtime - convert the calendar time into broken down time 
*/ 
/* $Header: gmtime.c,v 1.4 91/04/22 13:20:27 ceriel Exp $ */ 

#include  <time.h> 
#include  <limits.h> 
#include  "loc_time.h" 

struct tm * 
gmtime(register const time_t *timer) 
{ 
     static struct tm br_time; 
     register struct tm *timep = &br_time; 
     time_t time = *timer; 
     register unsigned long dayclock, dayno; 
     int year = EPOCH_YR; 

     dayclock = (unsigned long)time % SECS_DAY; 
     dayno = (unsigned long)time/SECS_DAY; 

     timep->tm_sec = dayclock % 60; 
     timep->tm_min = (dayclock % 3600)/60; 
     timep->tm_hour = dayclock/3600; 
     timep->tm_wday = (dayno + 4) % 7;  /* day 0 was a thursday */ 
     while (dayno >= YEARSIZE(year)) { 
       dayno -= YEARSIZE(year); 
       year++; 
     } 
     timep->tm_year = year - YEAR0; 
     timep->tm_yday = dayno; 
     timep->tm_mon = 0; 
     while (dayno >= _ytab[LEAPYEAR(year)][timep->tm_mon]) { 
       dayno -= _ytab[LEAPYEAR(year)][timep->tm_mon]; 
       timep->tm_mon++; 
     } 
     timep->tm_mday = dayno + 1; 
     timep->tm_isdst = 0; 

     return timep; 
} 
+0

Oto zaktualizowany link do pełnego źródła: http: //www.cise .ufl.edu/~ cop4600/cgi-bin/lxr/http/source.cgi/lib/ansi/gmtime.c –

11

Standardowa biblioteka zapewnia funkcje do tego. gmtime() lub localtime() skonwertuje time_t (sekundy od epoki) do struct tm. Strftime() może być następnie użyty do przekonwertowania struct tm na ciąg znaków w oparciu o określony format.

patrz: Obliczenia http://www.cplusplus.com/reference/clibrary/ctime/

data/czas może się trudne. Lepiej korzystasz z istniejącego rozwiązania, niż próbujesz wywrócić własne, chyba że masz naprawdę dobry powód.

+3

Zaczęło się od pracy domowej jakiś czas temu, ale teraz jestem zainteresowany jej ulepszeniem. Normalnie chciałbym pójść na rozwiązanie biblioteki, ale 1) Nie wiedziałem, że funkcje czasu zostały wbudowane i 2) Chcę udoskonalić moją implementację. –

0

Jeśli pierwotnym typem czasu jest time_t, musisz użyć funkcji z time.h, np. Gmtime itp., Aby uzyskać przenośny kod. Standardy C/C++ nie określają formatu wewnętrznego (lub nawet dokładnego) dla time_t, więc nie można bezpośrednio konwertować ani modyfikować wartości time_t.

Wiadomo tylko, że time_t jest "typem arytmetycznym", ale wyniki operacji arytmetycznych nie są określone - nie można nawet dodawać/odejmować niezawodnie. W praktyce wiele systemów używa typu całkowitego dla time_t z wewnętrznym formatem sekund od epoki, ale nie jest to wymuszane przez standardy.

Podsumowując, należy użyć funkcji gmtime (i ogólnie time.h).

2

Łatwym sposobem (choć inny niż format chciałeś):

std::time_t result = std::time(nullptr); 
std::cout << std::asctime(std::localtime(&result)); 

wyjściowa: Wed Sep 21 10:27:52 2011

Zauważ, że zwracany wynik zostanie automatycznie łączone z "\ n" .. można go usunąć za pomocą:

std::string::size_type i = res.find("\n"); 
if (i != std::string::npos) 
    res.erase(i, res.length()); 

albumu: http://en.cppreference.com/w/cpp/chrono/c/time

Powiązane problemy