In this FREE six-day email course, you'll learn from Janis Griffin, Database Performance Evangelist. She'll teach 12 steps that you can use to optimize your queries as much as possible and see measurable results in your work. Get started today!

Hi there everyone.

I am trying to convert a 32 bit UTC timestamp, which represents the number of seconds from the year 1900, into the current year, month, , date, day, hr, min, se. Does anyone have the algorithm to calculate this and can help explain how the algorithm works? Thanks.

I am trying to convert a 32 bit UTC timestamp, which represents the number of seconds from the year 1900, into the current year, month, , date, day, hr, min, se. Does anyone have the algorithm to calculate this and can help explain how the algorithm works? Thanks.

Ozo, thanks for your interest again. I used your answer last time and it worked fine. This time around though, I would like to see the actual algorithm and understand exactly how the year, date, month, etc is calculated.

I tried looking at some of the standard C routines, but couldn't make heads or tail of the advanced stuff it was doing. Can anyone propose an efficient yet easy to understand algorithm for converting the timestamp to smaller time units? Thanks.

I mean,

hours === __ to __ bits

min === __ to __ bits

sec === __ to __ bits

#include<stdio.h>

void datum(unsigned long secs,long *year,long *month,long *day,long *hour,

long *min, long *sec)

{

long tdays;

int tyear;

int year4; \

int leap = 0;

tdays = secs / ((unsigned long) 24 * 3600);

if (tdays < 1461)

{

tyear = tdays / 365;

tdays = tdays - 365 * tyear;

leap = 0;

}

else

{

year4 = (tdays - 1460) / 1461 + 1;

tdays = (tdays -1460) % 1461;

if (tdays > 366)

{

tyear = year4 * 4 + (tdays - 366)/365+1;

tdays = (tdays - 366) % 365;

leap = 0;

}

else

{

tyear = year4 * 4;

leap = 1;

}

}

if (tdays < 31)

{

*month = 1;

*day = tdays;

}

else

{

if(tdays < 59 + leap)

{

*month = 2;

*day = tdays - 31;

}

else

{

if(tdays < 90 + leap)

{

*month = 3;

*day = tdays - 59 - leap;

}

else

{

if(tdays < 120 + leap)

{

*month = 4;

*day = tdays - 90 - leap;

}

else

{

if(tdays < 151 + leap)

{

*month = 5;

*day = tdays - 120 - leap;

}

else

{

if(tdays < 181 + leap)

{

*month = 6;

*day = tdays - 151 - leap;

}

else

{

if(tdays < 212 + leap)

{

*month = 7;

*day = tdays - 181 - leap;

}

else

{

if(tdays < 243 + leap)

{

*month = 8;

*day = tdays - 212 - leap;

}

else

{

if(tdays < 273 + leap)

{

*month = 9;

*day = tdays - 243 - leap;

}

else

{

if(tdays < 304 + leap)

{

*month = 10;

*day = tdays - 273 - leap;

}

else

{

if(tdays < 334 + leap)

{

*month = 11;

*day = tdays - 304 - leap;

}

else

{

if(tdays < 365 + leap)

{

*month = 12;

*day = tdays - 365 - leap;

}

}}}}}}}}}}}

++(*day);

*sec = secs % 60;

*min = (secs / 60) % 60;

*hour = (secs / 3600) % 24;

*year = tyear;

}

main()

{

unsigned long s,y,m,d,h,min,sec;

do{

printf("\nSeconds ");

scanf("%li",&s);

datum(s,&y,&m,&d,&h,&min,&

printf("\n %li:%li:%li %li/%li/%li\n",h,min,sec,m

} while(s!=0);

}

I'm looking for an efficient algorithm, and someone to explain to me how that algorithm works. Ozo, if you could explain to me step by step how that algorithm worked it would be great too.

Sorry, opening up question to more suggestions

I've got a hard time explaining it too.

My algorithm is not inefficient, not as efficient as the ozo formula, but i developed it to be more readily understandable.

#define seconds_per_minute (60L)

#define seconds_per_hour (60L * seconds_per_minute)

#define seconds_per_day (24L * seconds_per_hour)

const short __month_to_days[2][13] =

{

{0,31,59,90, 120, 151, 181, 212, 243, 273, 304,334, 365 },

{0,31,60,91, 121, 152, 182, 213, 244, 274, 305,335, 366 }

};

/*

* leap_year - return nonzero if year is a leap year, zero otherwise (year 0 = 1900)

*/

int __leap_year(int year);

int __leap_year(int year)

{

return(__mod(year, 4) == 0 && (__mod(year, 100) != 0 || __mod(year, 400) == 100));

}

/*

* __time2tm - convert seconds since midnight, 1/1/1900 (or 1970 on Win32),

* to broken-down time

*/

#if (__dest_os == __win32_os || __dest_os == __wince_os)

static void __time2tm(time_t inTime, struct tm * tm)

#else

static void __time2tm(time_t time, struct tm * tm)

#endif

{

unsigned long years, months, days, seconds;

int is_leap_year;

#if (__dest_os == __win32_os || __dest_os == __wince_os)

/* Since Win32 time_t is relative to 1970 rather than 1900.

* This must be of type unsigned long rather than a signed

* time_t to prevent overflow */

unsigned long time = inTime + ((365 * 70UL) + 17) * 24 * 60 * 60;

#endif

if (!tm)

return;

tm->tm_isdst = -1;

days = time / seconds_per_day;

seconds = time % seconds_per_day;

tm->tm_wday = (days + 1) % 7;

/* January 1, 1900 was a Monday */

years = 0;

for (;;)

{

unsigned long days_this_year = __leap_year(years) ? 366 : 365;

if (days < days_this_year)

break;

days -= days_this_year;

years += 1;

}

tm->tm_year = years;

tm->tm_yday = days;

months = 0;

is_leap_year = __leap_year(years);

for (;;)

{

unsigned long days_thru_this_month = __month_to_days[is_leap_ye

if (days < days_thru_this_month)

{

days -= __month_to_days[is_leap_ye

break;

}

++months;

}

tm->tm_mon = months;

tm->tm_mday = days + 1;

tm->tm_hour = seconds / seconds_per_hour;

seconds %= seconds_per_hour;

tm->tm_min = seconds / seconds_per_minute;

tm->tm_sec = seconds % seconds_per_minute;

}

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.

I also meant it to keep the indentation. Sorry about that. Oh well, it's not that complicated.