I am trying to implement in C two simple convertors, date/time to time-stamp and vice versa, without any dependencies on time library routines, such as mktime, etc.
The time-stamp is in seconds, and the date/time structure is in the following format:
unsigned char year: 0 to 99 (representing the range 2000 to 2099)
unsigned char month: 1 to 12
unsigned char day: 1 to 31
unsigned char hour: 0 to 23
unsigned char minute: 0 to 59
unsigned char second: 0 to 59
I would like to have a second opinion on the dt2ts convertor (assuming that the input is legal):
unsigned int dt2ts(const dt_t* dt)
{
static unsigned short days[] = {0,31,59,90,120,151,181,212,243,273,304,334};
return ((((dt->year*365+dt->year/4)+days[dt->month-1]+dt->day)*24+dt->hour)*60+dt->minute)*60+dt->second;
}
In addition to that, I would appreciate some help completing the ts2dt convertor:
void ts2dt(unsigned int ts,dt_t* dt)
{
dt->second = ts%60; ts /= 60;
dt->minute = ts%60; ts /= 60;
dt->hour = ts%24; ts /= 24;
dt->day = ?????;
dt->month = ?????;
dt->year = ?????;
}
Thanks
OP is all ready well handling the hours, minutes, seconds. Just a bit of assist on Y,M,D.
Note: The number of days from Jan 1, 2000 to Dec 31, 2099 needs at least a 16 bit integer. Following should work even if unsigned
is 2 bytes.
unsigned DivRem(unsigned Dividend, unsigned Divisor, unsigned *Remainder) {
unsigned Quotient = Dividend/Divisor;
*Remainder = Dividend - Quotient*Divisor;
return Quotient;
}
void Day2000ToYMD(unsigned DaySince2000Jan1, unsigned *Y, unsigned *M, unsigned *D) {
unsigned OlympiadDay; // Every 4 years is an Olympiad
*Y = 4*DivRem(DaySince2000Jan1, 365*4+1, &OlympiadDay);
*D = 1;
if (OlympiadDay >= (31+29-1)) { // deal with Feb 29th and after
OlympiadDay--;
if (OlympiadDay == (31+29-1)) {
(*D)++;
}
}
unsigned YearDay; // Day of the year 0 to 364
*Y += DivRem(OlympiadDay, 365, &YearDay);
static const unsigned short days[] = {0,31,59,90,120,151,181,212,243,273,304,334,365};
*M = 1;
while (days[*M] <= YearDay) (*M)++;
*D += YearDay - days[*M - 1];
}
[Edit] The answer provided tries to keep the concept of the year as Jan 1 to Dec 31. As this answer does not need to handle the leap year years about 100 and 400 years, I've kept with this style.
In general, once those 2 rules are added, the math becomes easier to if one shifts the beginning of the year to March 1 and ending on Feb 28/29. FWIW, this is a more consistent view of the ancient development of the Julian/Gregorian calendar. Thus *Oct*ober is then the 8th month and *Dec*ember is the 10th month.