Solved

# Convert 32bit UTC timestamp to yr, mo, da, sec, etc.

Posted on 2000-02-22
Medium Priority
625 Views
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.
0
Question by:sailwind
[X]
###### Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

• Help others & share knowledge
• Earn cash & points
• Learn & ask questions
• 3
• 2
• 2
• +2

LVL 84

Expert Comment

ID: 2548287
#include <time.h>
struct tm *gmtime (const time_t *timer);
0

LVL 3

Author Comment

ID: 2548474

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.
0

LVL 84

Expert Comment

ID: 2548559
0

LVL 3

Expert Comment

ID: 2550229
If the time is divided in a single 32 bit number i.e. if it is bitfield then let me know how the fields are divided in bits?

I mean,
hours ===   __ to __ bits
min   ===   __ to __ bits
sec   ===   __ to __ bits
0

LVL 18

Expert Comment

ID: 2550572
This converts seconds to date & time.  I think it can be readily interpreted.

#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,&sec);
printf("\n %li:%li:%li  %li/%li/%li\n",h,min,sec,m,d,y);
} while(s!=0);
}

0

LVL 3

Author Comment

ID: 2551630
sumant, the timestamp is not a bit field. Rather, the 32bit timestamp is the number of seconds from the year 1900 to now. So you cannot just extract the time from the bitfield, but rather have to convert the seconds.
0

LVL 3

Author Comment

ID: 2551637
Deighton, thanks for your suggestion, I believe it works. However, does anyone know of a smaller, more efficient algorithm? Ozo offered one last time which was about 18 lines, but I have a hard time understanding what it was doing.

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
0

LVL 18

Expert Comment

ID: 2553674
ozo's formula was based on all sorts of mathematical trickery to implicitly adjust for leap years etc.

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.

0

LVL 4

Expert Comment

ID: 2560410
Well, here's an implementation that I think is both pretty understandable and acceptably efficient, and it even works with Windows ;)

#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_year][months+1];

if (days < days_thru_this_month)
{
days -= __month_to_days[is_leap_year][months];
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;
}
0

LVL 4

Accepted Solution

Alex Curylo earned 800 total points
ID: 2560418
Hrmph. I meant that last post to be an answer candidate.

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

## Featured Post

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Have you thought about creating an iPhone application (app), but didn't even know where to get started? Here's how: ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Important pre-programming comments: Iâ€™ve never triâ€¦
This is a short and sweet, but (hopefully) to the point article. There seems to be some fundamental misunderstanding about the function prototype for the "main" function in C and C++, more specifically what type this function should return. I see soâ€¦
The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use conditional statements in the C programming language.
###### Suggested Courses
Course of the Month8 days, 5 hours left to enroll

#### 765 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.