Tags

, ,

Last week I found myself dealing with time again and again. I got embarrassed with attending a meeting one hour late as it turned out to be I was not clever enough to decipher my chrome calendar timezone. Then, I dealt with bugs related to recent timezone changes.

As I spare time from new features, I try to refactor oldskool code.  Modularity by abstraction is the sustainable way of implementing complex structures, and converting platform dependent code to common abstractions seems a good way of improvement.

However, sometime this turns to be harder done than said. As we will see, localtime() has tendency to not reflect timezone changes in Windows. We test use of time(), localtime(), GetLocalTime() using following sample code

#include <iostream>
#include <ctime>
#include <chrono>
#include <thread> // for sleep_for
#include <windows.h>
#include <stdio.h>

unsigned int k = 0;

int main()
{
    while (true)
    {
        std::cout << "-----------------------" << k++ << "--------------------" << std::endl;
 
        /***** Get loval time from time() & localtime() *****/
        std::time_t call_start_sec_tt;
        time(&call_start_sec_tt);
        tm* o_ct_ptr = localtime(&call_start_sec_tt);
        tm o_ct = *o_ct_ptr; 
 
        const int time_part_size = 24; //4+1+2+1+2+1+2+1+2+1+2+1+3+1
        char old_time_part[time_part_size];
 
        // another way to display may be use of ctime(&call_start_sec_tt); 
        snprintf(old_time_part, time_part_size, "%d %.2d %.2d %.2d %.2d %.2d", ((o_ct.tm_year)+1900), 
 ((o_ct.tm_mon) + 1), (o_ct.tm_mday), (o_ct.tm_hour), (o_ct.tm_min), (o_ct.tm_sec));
 
        std::cout << "Local time from \"time()\": " << old_time_part << std::endl;
 
        /***** Get loval time from std::chrono::system_clock::now() *****/
        std::chrono::system_clock::time_point today = std::chrono::system_clock::now();
        std::time_t tt;

        tt = std::chrono::system_clock::to_time_t ( today );
        tm* n_ct_ptr = localtime(&tt);
        tm n_ct = *n_ct_ptr; 
        char new_time_part[time_part_size];
 
        snprintf(new_time_part, time_part_size, "%d %.2d %.2d %.2d %.2d %.2d", ((n_ct.tm_year)+1900), 
 ((n_ct.tm_mon) + 1), (n_ct.tm_mday), (n_ct.tm_hour), (n_ct.tm_min), (n_ct.tm_sec));
 
         std::cout << "Local time from \"system_clock::now()\": " << new_time_part << std::endl;
 

         /***** Get loval time from Windows GetLocalTime() *****/
         SYSTEMTIME lt;
         GetLocalTime(&lt);
 
         char win_time_part[time_part_size];
         snprintf(win_time_part, time_part_size, "%d %.2d %.2d %.2d %.2d %.2d", 
  lt.wYear, lt.wMonth, lt.wDay, lt.wHour, lt.wMinute,lt.wSecond);
 
         std::cout << "Local time from \"GetLocalTime()\": " << win_time_part << std::endl;
 
         // modern but dangerous way to make thread sleep for 1 seconds in windows
         // std::this_thread::sleep_for (std::chrono::seconds(1));
 
         // oldskool but safe way to make thread sleep for 1 seconds
         Sleep(1000);
    }
}

 

When we modify time, changes are immediately available to process;

time-change-to-future

However, timezone changes seems to be ineffective to ongoing processes for localtime(). So when we start a new process we see the change but ongoing processes reflect the old version. The left console shows output of a pre started process and right console shows output of a post started process. Here windows specific GetLocalTime() seems to be solution.

time-change-timezone

And as a final surprise, beware of

std::this_thread::sleep_for (std::chrono::seconds(1))

As your intended sleep duration may change tremendously with changing system time, which seems undocumented and may take time to find the cause.

time-dangerous-way-to-make-thread-sleep

To sum up, now I see more clearly the importance of time and agree with Mr Tanpinar in necessity of establishing a Time Regulation Institute.

Advertisements