What I want to do is convert an epoch time (seconds since midnight 1/1/1970) to "real" time (m/d/y h:m:s)
So far, I have the following algorithm, which to me feels a bit ugly:
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; }
you can assume that the members seconds
, minutes
, hours
, month
, day
, and year
all exist.
Using the for
loops to modify the original time feels a little off, and I was wondering if there is a "better" solution to this.
Because our Epoch time is specified in milliseconds, we may convert it to seconds. To convert milliseconds to seconds, first, divide the millisecond count by 1000. Later, we use DATEADD() to add the number of seconds since the epoch, which is January 1, 1970 and cast the result to retrieve the date since the epoch.
use strict; use warnings; use Time::Piece; my $datestring = '07-06-2019 21:13:00'; my $time = localtime->strptime($datestring, '%d-%m-%Y %H:%M:%S'); my $epoch = $time->epoch; ... my $time = localtime($epoch); my $datestring = $time->strftime('%d-%m-%Y %H:%M:%S');
The gmtime() function in C++ converts the given time since epoch to calendar time which is expressed as UTC time rather than local time. The gmtime() is defined in <ctime> header file.
Be careful about leap years in your daysInMonth function.
If you want very high performance, you can precompute the pair to get to month+year in one step, and then calculate the day/hour/min/sec.
A good solution is the one in the 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; }
The standard library provides functions for doing this. gmtime()
or localtime()
will convert a time_t
(seconds since the epoch, i.e.- Jan 1 1970 00:00:00) into a struct tm
. strftime()
can then be used to convert a struct tm
into a string (char*
) based on the format you specify.
see: http://www.cplusplus.com/reference/clibrary/ctime/
Date/time calculations can get tricky. You are much better off using an existing solution rather than trying to roll your own, unless you have a really good reason.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With