Solved

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

Posted on 2000-02-22
10
623 Views
Last Modified: 2010-05-18
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
Comment
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
10 Comments
 
LVL 84

Expert Comment

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

Author Comment

by:sailwind
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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 3

Expert Comment

by:sumant032199
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

by:deighton
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

by:sailwind
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

by:sailwind
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

by:deighton
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

by:Alex Curylo
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

by:
Alex Curylo earned 200 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

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

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…
An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
The goal of this video is to provide viewers with basic examples to understand opening and writing to files in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.

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

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

Join & Ask a Question