Convertendo tempo de época para “real” data / hora
Pergunta
O que eu quero fazer é converter um tempo de época (segundos desde a meia-noite 1/1/1970) ao tempo "real" (m / d / y h: m: s)
Até agora, eu tenho o seguinte algoritmo, que para mim se sente um pouco feio:
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;
}
você pode assumir que os membros seconds
, minutes
, hours
, month
, day
e year
toda existir.
Usando o for
loops para modificar o horário original se sente um pouco fora, e eu queria saber se existe uma "melhor" solução para isso.
Solução
Tenha cuidado com os anos bissextos em sua função DaysInMonth.
Se você quer muito alto desempenho, você pode precompute o par para chegar ao mês + ano em uma única etapa, e depois calcular o dia / hora / min / seg.
Uma boa solução é a do fonte gmtime :
/*
* 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;
}
Outras dicas
A biblioteca padrão fornece funções para fazer isso. gmtime()
ou localtime()
irá converter um time_t
(segundos desde a época, i.e.- 01 de janeiro de 1970 00:00:00) em um struct tm
. strftime()
pode então ser usado para converter um struct tm
em um string (char*
) baseado no formato especificado.
ver: http://www.cplusplus.com/reference/clibrary/ctime/
cálculosData / Hora pode ficar complicado. Está muito melhor fora de usar uma solução existente ao invés de tentar rolar o seu próprio, a menos que tenha uma razão muito boa.
Uma maneira fácil (embora diferente do formato que você queria):
std::time_t result = std::time(nullptr);
std::cout << std::asctime(std::localtime(&result));
Saída: Wed 21 de setembro 10:27:52 de 2011
Observe que o resultado retornado será concatenado automaticamente com "\ n" .. você pode removê-lo usando:
std::string::size_type i = res.find("\n");
if (i != std::string::npos)
res.erase(i, res.length());
Retirado de: http://en.cppreference.com/w/cpp / crono / c / tempo
time_t t = unixTime;
cout << ctime(&t) << endl;
Se o seu tipo de tempo original é time_t, você tem que usar funções de time.h ou seja gmtime etc. para obter o código portátil. Os padrões de C / C ++ não especificar formato interno (ou mesmo tipo exato) para o time_t, então você não pode converter diretamente ou manipular time_t valores.
Tudo o que se sabe é que time_t é "tipo de aritmética", mas os resultados das operações aritméticas não são especificados - você não pode mesmo adicionar / subtrair de forma confiável. Na prática, muitos sistemas usam inteiro tipo para time_t com formato interno de segundos desde época, mas isso não é imposta pelos padrões.
Em suma, o uso gmtime (e time.h funcionalidade em geral).