Click here to Skip to main content
15,894,337 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Can anyone explain what is going on with localtime to me? I am aware that it uses a static tm structure that it returns a pointer to. What happens here is I pass two different values to it and it gives the same results with both.

I enclosed the code I use to test this. If you substitute trace with printf you will have console output. Here is the output I see from it:
16:11:37.571  PrimaryThread   time 1 data :
16:11:37.575  PrimaryThread   now is 1553123249
16:11:37.578  PrimaryThread   year  = 19
16:11:37.582  PrimaryThread   month =  2
16:11:37.585  PrimaryThread   day   = 30
16:11:37.588  PrimaryThread   hour  = 16
16:11:37.591  PrimaryThread   min   = 11
16:11:37.595  PrimaryThread   sec   = 37
16:11:37.598  PrimaryThread   time 2 data :
16:11:37.601  PrimaryThread   now is 1553987249
16:11:37.604  PrimaryThread   year  = 19
16:11:37.607  PrimaryThread   month =  2
16:11:37.610  PrimaryThread   day   = 30
16:11:37.613  PrimaryThread   hour  = 16
16:11:37.618  PrimaryThread   min   = 11
16:11:37.621  PrimaryThread   sec   = 37
16:11:37.624  PrimaryThread   difference in times is 864000 seconds
As you can from this, the time value pass is different and it differs by the equivalent of ten days but the values from localtime are the same. That's what I am puzzled about. I would be willing to use a different function if there is one available.

-edit- I found a different function. That is localtime_s and it takes a tm structure as an argument. When I changed to that function this test works correctly. BTW, this is with vs2017 and windows 10.

What I have tried:

C++
void TraceTime( time_t tv )
{
    struct tm *	ptm = localtime( &tv );

    trace( _T( "now is %I64d\n" ), tv );
    trace( _T( "year  = %2d\n" ), ptm->tm_year - 100 );
    trace( _T( "month = %2d\n" ), ptm->tm_mon );
    trace( _T( "day   = %2d\n" ), ptm->tm_mday );
    trace( _T( "hour  = %2d\n" ), ptm->tm_hour );
    trace( _T( "min   = %2d\n" ), ptm->tm_min );
    trace( _T( "sec   = %2d\n" ), ptm->tm_sec );
    trace( _T( "value = %d\n" ), value );
}


void DoLocaltimeTest()
{
    time_t now2 = 1553987249;
    time_t now1 = 1553123249;

    trace( _T( "time 1 data :\n" ) );
    TraceTime( now1 );

    trace( _T( "time 2 data :\n" ) );
    TraceTime( now2 );

    INT64 diff = now2 - now1;
    trace( _T( "difference in times is %I64d seconds\n" ), diff );
}
Posted
Updated 30-Mar-19 14:06pm
v2
Comments
Richard MacCutchan 31-Mar-19 3:51am    
Strange, I just ran that code and the results are correct. The local times are 10 days apart. I cannot see any way that using the non-threadsafe version would affect the output.
Rick York 31-Mar-19 13:12pm    
It really makes no sense to me. I went went the other version and it works correctly so I didn't want to spend any more time on it.
Stefan_Lang 2-Apr-19 7:36am    
Month 2, day 30? I am not aware of any calendar that has this date.
P.S.: maybe you should add 1 to tm_mon (it's 0-based). ;-)
Rick York 2-Apr-19 10:30am    
If I cared what those actual values were I would have. I was more concerned with why the values were the same between calls with different arguments.

1 solution

localtime is not thread safe, so you might experience troubles if you are calling it from different threads (is your the trace tool multithreaded?)

On my Linux box, the code

C
#include <stdlib.h>
#include <stdio.h>
#include <time.h>


#define trace printf
#define _T(s) s

void TraceTime( time_t tv )
{
    struct tm * ptm = localtime( &tv );

    trace( _T( "now is %ld\n" ), tv );
    trace( _T( "year  = %2d\n" ), ptm->tm_year - 100 );
    trace( _T( "month = %2d\n" ), ptm->tm_mon );
    trace( _T( "day   = %2d\n" ), ptm->tm_mday );
    trace( _T( "hour  = %2d\n" ), ptm->tm_hour );
    trace( _T( "min   = %2d\n" ), ptm->tm_min );
    trace( _T( "sec   = %2d\n" ), ptm->tm_sec );
    //trace( _T( "value = %d\n" ), value );
}


void DoLocaltimeTest()
{
    time_t now2 = 1553987249;
    time_t now1 = 1553123249;

    trace( _T( "time 1 data :\n" ) );
    TraceTime( now1 );

    trace( _T( "time 2 data :\n" ) );
    TraceTime( now2 );

    long long diff = now2 - now1;
    trace( _T( "difference in times is %lld seconds\n" ), diff );
}

int main()
{
  DoLocaltimeTest();
  return 0;
}

behaves correctly
time 1 data :
now is 1553123249
year  = 19
month =  2
day   = 21
hour  =  0
min   =  7
sec   = 29
time 2 data :
now is 1553987249
year  = 19
month =  2
day   = 31
hour  =  0
min   =  7
sec   = 29
difference in times is 864000 seconds
 
Share this answer
 
Comments
Rick York 30-Mar-19 20:01pm    
As it should! This was all in one thread on a windows box. I read a little more and found localtime_s which takes a pointer to a tm structure and it behaves correctly.

Thank you for checking!
CPallini 31-Mar-19 5:59am    
That is a solution, of course, but you didn't find the root of the problem. :-)
You are welcome.
Stefan_Lang 2-Apr-19 7:35am    
February 31? Are you sure it's working correctly? ;-p
CPallini 2-Apr-19 7:43am    
:thumbsup: Good one! :-D
Rick York 2-Apr-19 10:28am    
Yes, the time values were set semi-randomly.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900