Преобразование эпохи в "настоящую" дату/время
То, что я хочу сделать, - это преобразовать время эпохи (секунды с полуночи 1/1/1970) в "реальное" время (m/d/y h: m: s)
До сих пор у меня есть следующий алгоритм, который мне кажется немного уродливым:
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;
}
вы можете предположить, что существуют члены seconds
, minutes
, hours
, month
, day
и year
.
Использование циклов for
для изменения первоначального времени немного немного, и мне было интересно, есть ли "лучшее" решение для этого.
Ответы
Ответ 1
Будьте осторожны с високосными годами в вашей функции daysInMonth.
Если вы хотите очень высокую производительность, вы можете предварительно скопировать пару, чтобы перейти на месяц + год за один шаг, а затем рассчитать день/час/мин/сек.
Хорошим решением является исходный код 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;
}
Ответ 2
Стандартная библиотека предоставляет функции для этого. gmtime() или localtime() преобразует time_t (секунды с эпохи) в структуру tm. strftime() может затем использоваться для преобразования struct tm в строку на основе указанного вами формата.
см. http://www.cplusplus.com/reference/clibrary/ctime/
Расчеты даты/времени могут оказаться сложными. Вам гораздо лучше использовать существующее решение, вместо того чтобы пытаться катиться самостоятельно, если у вас нет действительно веской причины.
Ответ 3
Простым способом (хотя и отличается от формата, который вы хотели):
std::time_t result = std::time(nullptr);
std::cout << std::asctime(std::localtime(&result));
Вывод:
Ср Сен 21 10:27:52 2011
Обратите внимание, что возвращенный результат будет автоматически связан с "\n".. вы можете удалить его, используя:
std::string::size_type i = res.find("\n");
if (i != std::string::npos)
res.erase(i, res.length());
Взято из: http://en.cppreference.com/w/cpp/chrono/c/time
Ответ 4
Если ваш исходный тип времени - time_t, вы должны использовать функции from time.h, т.е. gmtime и т.д., чтобы получить переносимый код. Стандарты C/С++ не определяют внутренний формат (или даже точный тип) для time_t, поэтому вы не можете напрямую преобразовывать или изменять значения time_t.
Все, что известно, это то, что time_t является "арифметическим типом", но результаты арифметических операций не указаны - вы даже не можете надежно добавить/вычесть. На практике многие системы используют целочисленный тип для time_t с внутренним форматом секунд с эпохи, но это не соблюдается стандартами.
Короче говоря, используйте функции gmtime (и time.h в целом).