Thread: Converting timestamp to date and time

  1. #1
    Registered User
    Join Date
    Jun 2016
    Posts
    6

    Converting timestamp to date and time

    Hello!

    I need to read a timestamp that contains the number of seconds since 1/1/1904 00:00:00 and print the date and time (the timestamp is a TDMS timestamp value calles wf_start_time).
    I used the localtime() function from the time.h , and took down 66 years(the difference between 1904 and 1970) from the year value of the tm structure.
    This works perfectly when the date is from 1970 and up. When I try a file that contains a date that is before 1/1/1970 00:00:00, I get wrong values(year and month are ok, the rest is wrong).
    The timestamp also contains another value to calculate the hundredth of seconds, that is calculates by multiplying the value by 2^-64, however this one is not a problem.
    This is the function I wrote:
    Code:
    void time_print(unsigned long long int hundredth_of_sec,signed long long int date){
    
    
    struct tm start_time;
    double hundredth_calc=(double)hundredth_of_sec*pow(2.0,-64.0);//calculates the hundredth of sec value.
    time_t seconds_for_calc=date;
    hundredth_calc=(int)(hundredth_calc*100+0.5)*10;
    
    
    start_time=*localtime(&seconds_for_calc);
    start_time.tm_year=start_time.tm_year-66;
    
    
    printf("wf_start_time %d/%d/%d %d:%d:%d.%.0f\n",start_time.tm_mday,(start_time.tm_mon+1),(start_time.tm_year+1900),start_time.tm_hour,start_time.tm_min,start_time.tm_sec,hundredth_calc);
    
    
    }
    I would appreciate any help with this kind of convertion.
    Thank you

  2. #2
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    It's probably better to subtract the 66 years of seconds first instead of the 66 years later. I think the correct number of seconds is 2082844800 ((365 * 66 + 17 leap days) * 24*60*60, ignoring leap seconds).

    You should check the size of time_t:
    Code:
    printf("time_t: %zu\n", sizeof(time_t));
    It must be 64 bits, but just to be sure!

  3. #3
    Registered User
    Join Date
    Jun 2016
    Posts
    6
    Hi! thank you for your response.
    I will try this but I'm not sure if this would work.
    If I have a timestamp before 1/1/1970, substracting the 66 years in seconds will result in a negative number.
    Can the localtime() function of time.h deal with a negative number of seconds?

    Thanks

    Guy

  4. #4
    Registered User
    Join Date
    Jun 2016
    Posts
    6
    I just tried this now. For timestamp after 1970 it works, and before 1970 the program gets stuck. I am guessing it is the negative number of seconds that causes that using the localtime() function.
    Any other ideas?

  5. #5
    Registered User
    Join Date
    May 2010
    Posts
    4,633
    Any other ideas?
    Don't use localtime()? If you plan on using localtime() you must first compute and subtract out the number of seconds from 1/1/1904 to 1/1/19701. You need to be sure that this result can safely be held in a time_t.

    1. This is assuming that the epoch used for localtime() on your system is based on 1/1/1970, I believe that the C standard doesn't actually specify the actual epoch, it is an implementation defined value, as is the actual type of variable used as a time_t.

    Jim
    Last edited by jimblumberg; 06-17-2016 at 06:38 AM.

  6. #6
    Registered User
    Join Date
    Jun 2016
    Posts
    6
    Quote Originally Posted by jimblumberg View Post
    you must first compute and subtract out the number of seconds from 1/1/1904 to 1/1/19701. You need to be sure that this result can safely be held in a time_t.
    exactly,I tried this and apparently time_t is a signed value or the function localtime() can only deal with signed values. Either way, the use of localtime() is not possible for timestamps before 1970 since substracting the number of seconds from 1904 to 1970 will result with a negative number if the timestamp is before 1/1/1970 00:00:00.0 .
    I am now trying to write my own algorithm, I'll update here when I'm done.

  7. #7
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Of course time_t can deal with negative values! How else would it represent dates before the epoch?
    Code:
    #include <stdio.h>
    #include <string.h>
    #include <time.h>
    #include <inttypes.h>
    int main() {
        struct tm tm;
        memset(&tm, 0, sizeof(tm));
        tm.tm_year = 4;
        tm.tm_mday = 1;
        time_t t = mktime(&tm);
        printf("%"PRId64"\n", (int64_t)t);
        return 0;
    }
    Last edited by algorism; 06-17-2016 at 09:24 AM.

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Guyb
    I tried this and apparently time_t is a signed value or the function localtime() can only deal with signed values. Either way, the use of localtime() is not possible for timestamps before 1970 since substracting the number of seconds from 1904 to 1970 will result with a negative number if the timestamp is before 1/1/1970 00:00:00.0 .
    Your reasoning does not follow: "signed" means that negative values can be represented. I suggest posting the smallest and simplest compilable program that demontrates the error. Include the test input, expected output, and actual output.

    Quote Originally Posted by algorism
    Of course time_t can deal with negative values! How else would it represent dates before the epoch?
    It's not a given though: the trade-off is that fewer date/times after the epoch date/time can be represented, so until the convention of signed integer representations was established, time_t could well have been reasonably suspected to be unsigned.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Quote Originally Posted by laserlight View Post
    It's not a given though: the trade-off is that fewer date/times after the epoch date/time can be represented, so until the convention of signed integer representations was established, time_t could well have been reasonably suspected to be unsigned.
    I see what you mean, but it's not really a trade off, is it. If you want the "arithmetic type" time_t to be unsigned then you would set the epoch to be the earliest time instead of the "middle" time.

    I suppose the reason unix uses a signed value is that if they used an unsigned value then to extend the representable dates they would have to change the epoch (or keep it as the old earliest time, which is suboptimal). By setting the epoch at 1970 and using a signed time_t value, they were able to extend the time_t type from 32 to 64 bits and retain the old epoch so that all the old 32-bit times were still easily interpretted.

  10. #10
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Can anyone solve this mystery?
    For me the following code prints 1767223568 sec
    But from calculations it should be (56 * 365 + 14 leap days) * 24 * 60 * 60 = 1767225600
    The difference is 2032, which is about 33.87 minutes
    Why would it be off by 33.87 minutes?
    Code:
    #include <stdio.h>
    #include <string.h>
    #include <time.h>
    
    int main() {
        struct tm tm;
    
        // Jan 1, 1960, 00:00:00
        memset(&tm, 0, sizeof(tm));
        tm.tm_year = 60;
        tm.tm_mday = 1;
        time_t t1 = mktime(&tm);
    
        // Jan 1, 1904, 00:00:00
        memset(&tm, 0, sizeof(tm));
        tm.tm_year = 4;
        tm.tm_mday = 1;
        time_t t2 = mktime(&tm);
    
        printf("%.0f sec\n", difftime(t1, t2));
    
        return 0;
    }

  11. #11
    Registered User
    Join Date
    May 2010
    Posts
    4,633
    When I ran the program I got 1767225600 as the result.

    By the way I'm running Linux, 64 and 32 bit using gcc 6.1.

    What operating system and compiler did you use?

    Jim

  12. #12
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Quote Originally Posted by jimblumberg View Post
    When I ran the program I got 1767225600 as the result.

    By the way I'm running Linux, 64 and 32 bit using gcc 6.1.

    What operating system and compiler did you use?

    Jim
    I ran it on 64-bit Ubuntu 16.04 (the latest LTS version; could have some bugs?).

  13. #13
    Registered User
    Join Date
    May 2010
    Posts
    4,633
    What version of the compiler are you using?

    What if any optimization flags?

    Jim

  14. #14
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Quote Originally Posted by jimblumberg View Post
    What version of the compiler are you using?

    What if any optimization flags?

    Jim
    gcc (Ubuntu 5.3.1-14ubuntu2.1) 5.3.1 20160413

    No flags. Just gcc timetest.c

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. converting 64 bit time and date
    By pastitprogram in forum C++ Programming
    Replies: 29
    Last Post: 07-02-2008, 03:53 PM
  2. Help on converting date
    By knutso in forum C Programming
    Replies: 15
    Last Post: 10-14-2007, 06:00 AM
  3. Converting FILETIME to timestamp
    By maxorator in forum Windows Programming
    Replies: 5
    Last Post: 01-13-2007, 04:14 PM
  4. Converting Zulu Time to Current Time
    By Caldus in forum C++ Programming
    Replies: 3
    Last Post: 06-08-2006, 08:54 PM
  5. convert integer unix timestamp to time
    By rotis23 in forum C Programming
    Replies: 2
    Last Post: 11-18-2002, 09:20 AM

Tags for this Thread