2

I need to convert some string times in the format "2011061411322100" into GMT - my first attempt is below. However, the problem is that the times are coming from another PC and is a historical time. So I am not getting the times in real time so I cannot simply get the GMT from the local time on the box that my code is running.

The problem is that if my code is running during a time change, the time change will have occurred on my box but not on the remote box where I am getting the times. I can however, query the box to get the current time at any time.

So, to give more detail:

  1. I start the job on a remote box
  2. The job completes
  3. I get some times related to the job running
  4. I convert the time to GMT

If a time change (daylight savings) occurs between 1. and 2. I am screwed. My GMT conversion will break. I guess after 2) I need to get the current Remote Box time and see if there is a difference of >58 mins and then apply that to the conversion. But I cannot figure out a reliable method of doing this.


string GMTConverter::strToGMT(const string& timeToConvert)
{
    // Set time zone from TZ environment variable. 
    _tzset();

    struct tm tmTime;


    //2011 06 14 11 32 21 00
     // (strToInt is just a wrapper for atoi) 
    int year = strToint(timeToConvert.substr(0, 4) );
    int month = strToint(timeToConvert.substr(4, 2) );
    int day = strToint(timeToConvert.substr(6, 2) );
    int hour = strToint(timeToConvert.substr(8, 2) );
    int min = strToint(timeToConvert.substr(10, 2) );
    int sec = strToint(timeToConvert.substr(12, 2) );

    cout<<"Time after parsing: "<<year<<"/"<<month<<"/"<<day<<" "<<hour<<":"<<min<<":"<<sec<<endl;

    // add to tm struct and return
    tmTime.tm_hour = hour; 
    tmTime.tm_min = min; 
    tmTime.tm_sec = sec; 
    tmTime.tm_mday = day; 
    tmTime.tm_mon = (month-1); 
    tmTime.tm_year = (year - 1900); 

    cout <<"Time in TM: "<<tmTime.tm_year<<"/"<<tmTime.tm_mon<<"/"<<tmTime.tm_mday<<" "<<tmTime.tm_hour<<":"<<tmTime.tm_min<<":"<<tmTime.tm_sec<<endl;

    char currDateTime[64];

     // For logging
    strftime(currDateTime, 63, "%c", &tmTime);
    cout <<"Actual time:"<<currDateTime<<endl;

    time_t remotePCTime = mktime( &tmTime );

    struct tm *gmt = gmtime( &remotePCTime );
    cout << "gmt = " << asctime( gmt ) << endl;

    char datebuf_2[12];
    char timebuf_2[13];
    strftime( datebuf_2, 13, "%Y-%m-%d\0", gmt );
    strftime( timebuf_2, 13, "%H:%M:%S\0", gmt );

    return string(datebuf_2) + "T" + string(timebuf_2) + "." + string("000");
}
Paligulus
  • 493
  • 1
  • 4
  • 14

3 Answers3

2

The obvious reliable solution would be to use UTC (which has no daylight savings) for the time stamp you're sending over. Using any time system that has inherent ambiguity (there is one hour of overlap each year where you can get the same time stamps on a different time) will make it impossible to have a fool-proof method, since information is lost.

If you have no control over the time format that the remote machine is sending, you can only try to extrapolate from the information that you do have, for instance, if the end time is lower than the start time, add one hour. This again introduces ambiguity if the job took longer than one hour, but at least time won't move backwards.

Aaldert
  • 46
  • 1
  • 1
    Unfortunately I have to send as GMT – Paligulus Jun 27 '11 at 12:22
  • Having said that, the result of gmtime is meant to be UTC? – Paligulus Jun 27 '11 at 12:25
  • 2
    Glancing over the docs (msdn: http://msdn.microsoft.com/en-us/library/0z9czt0w(v=vs.80).aspx) it appears both the in and output of gmtime are supposed to be UTC. Which is basically GMT without daylight savings (tm_isdst is always zero). – Aaldert Jun 27 '11 at 12:45
  • 3
    There is no such thing as GMT. Not any more at least, not since 1974. Some terms tend to stick around long after they are deprecated, and GMT is one of them. The easiest solution is to assume GMT means UTC, just as Aaldert suggested. – David Hammen Jun 27 '11 at 12:58
  • 1
    Thanks for clarifying. This still leaves the problem of handling the remote machine time. – Paligulus Jun 27 '11 at 13:31
  • 2
    Since you can get the remote machine's current time, if you do this before dispatching the job and after it finishes, and compare it with the time elapsed on the local machine (which for good measure, should be ignoring local DST changes for this particular purpose), you can at least deduce whether a daylight savings event has kicked in on the remote machine during the job. If they're different by about an hour (58 minutes should work, but 45 should be just as good) in either direction you can deal with it accordingly. – Aaldert Jun 27 '11 at 22:23
  • 1
    What happens if it occurs during the job? – Robben_Ford_Fan_boy Jun 28 '11 at 00:08
  • 1
    Don't use GMT (Or UTC) to compute delta time. UTC itself has problems with leap seconds. The solution is to use time since some epoch time since as 12 noon UTC January 1 2000 (J2000), or if you are a computer geek who does pay any attention to international standards, some date in 1969. GMT or UTC are nice for human output. Don't use them for computing time differences. – David Hammen Jun 28 '11 at 01:11
1

Time change appears twice a year - why should you bother? Anyway, can't you change the time format to include the time change event? Or check if job is done during time change by comparing to some fixed time and date at which time change appears?

Xirdus
  • 2,997
  • 6
  • 28
  • 36
1

Get the local time in UTC at the start and end of the remote job. Get the remote job time and covert to UTC at the start and end of the job. Convert the collection "historic" times to GMT/UTC as stated in your original post. Keep this data together in a struct or class and give additional start end times a clear name like LocalDLSValidation etc We must now checkfor following scenarios:

  1. Start and end time delta between Local and Remote is within allowed threshold(50mins?)

This the gold case. No modification is required to our collection of historical times

 2. Local start/end time and remote time delta is outside threshold. 

This is the second simplest case. It means that we can + or - hour to our entire collection of times.

 3.Local start time and remote time delta is within threshold.  But end is outside. 

This is our worst case scenario as it means change has occurred in the middle of our job. If the job lasts less than hour then it will be easy to see which times in our collection need to be + or - one hour.

If it is greater than 1 hour....mmmmm. This is where we run into problems.

   4.  Start time between local and remote is different but end time is different

According to use case in OP this should not occur.

Robben_Ford_Fan_boy
  • 8,494
  • 11
  • 64
  • 85