Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to smartly convert a number of seconds in a date-time value using C

In my embedded Linux application I have a "tick count" counter that increases 1 each 10 nanoseconds counting from 1st January 00:00:00 of 2014.

I want to be able to, picking the current value of the "tick count" counter, print it as the current date-time (year, month, day, hour, minute, second and millisecond) of my system already considering things such as leap year, February having 28/29 days, etc. and this using pure C methods (from time.h etc.).

But I don't know how to do it... For now I have the equivalent value in seconds, so I know how many seconds since the start date-time have passed, but not how to go from that to the current date-time value with everything adjusted, only in Qt which is not available (and the internet wasn't much of a help in this case till what could I understood of the explanations in cplusplus.com and etc.)

Any help appreciated.

like image 495
Momergil Avatar asked Oct 15 '14 20:10

Momergil


1 Answers

Use gmtime().

Simply divide the tick count to get the whole number of seconds and add an offset to change the epoch from Jan 1, 2014 to Jan 1, 1970.

void print_time(unsigned long long tick_count) {

  static const unsigned long ticks_per_sec = 100000000L;
  static const time_t epoch_delta = 16071L*24*60*60;
  time_t seconds = tick_count/ticks_per_sec + epoch_delta;

  unsigned long fraction = tick_count%ticks_per_sec;
  struct tm tm = *gmtime(&seconds);
  printf("%4d-%02d-%02d %02d:%02d:%02d.%03lu\n",
      tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
      tm.tm_hour, tm.tm_min, tm.tm_sec,
      fraction/10000);
}

[After Accept Edit]

OP comments "I tried to use the methods from time.h and I was unsuccessful as well as that it considers the count of time since 1970, which is not my situation"

Another approach is to use mktime(). This is less dependent on issues brought up by @DavidEisenstat. It relies on the tm_sec field being an int of sufficient width (like 32 bits) to cover years 2014 to 2082. mktime() takes out-of-range fields and adjusts them to the expected ranges. Should tm_sec be 16-bit, some simple adjustments could be had to tm_mday, tm_hour, tm_min, tm_sec instead.

void print_time2(unsigned long long tick_count) {

  static const unsigned long ticks_per_sec = 100000000L;
  unsigned long fraction = tick_count%ticks_per_sec;
  unsigned long long secondsFromJan12014 = tick_count/ticks_per_sec;
  struct tm tm = {0};
  tm.tm_year = 2014 - 1900;
  tm.tm_mday = 1;
  tm.tm_sec = secondsFromJan12014;

  if (mktime(&tm) == (time_t)(-1)) Handle_Failure();
  printf("%4d-%02d-%02d %02d:%02d:%02d.%03lu\n",
      tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
      tm.tm_hour, tm.tm_min, tm.tm_sec,
      fraction/10000);
}
like image 153
chux - Reinstate Monica Avatar answered Sep 30 '22 18:09

chux - Reinstate Monica