Retrieve Linux Time using struct timespec

15,235

Solution 1

After calling clock_gettime, ts.tv_sec, which has type time_t, is populated with the timestamp in seconds since the epoch. You can pass that directly to localtime:

struct timespec ts;    
clock_gettime(clk_id, &ts);
struct tm *my_tm = localtime(&ts.tv_sec);

Now my_tm points to a struct tm which has the time broken down into year / month / day / hour / minute / second, and ts.tv_nsec has the nanosecond portion.

Solution 2

What keeps you from doing:

#include <time.h>
#include <stdio.h>
#include <string.h>

int main(void)
{
  struct timespec ts;    
  clock_gettime(CLOCK_REALTIME, &ts);

  char * p = ctime(&ts.tv_sec); /* Note that ctime() isn't thread-safe. */
  p[strcspn(p, "\r\n")] = 0;

  printf("Date: %s %ldns\n", p, ts.tv_nsec);

  ...
}

From the relevant documentation:

All implementations support the system-wide real-time clock, which is identified by CLOCK_REALTIME. Its time represents seconds and nanoseconds since the Epoch.

(POSIX documentation is here.)

Share:
15,235

Related videos on Youtube

Irfan
Author by

Irfan

Updated on June 04, 2022

Comments

  • Irfan
    Irfan almost 2 years

    Can someone please suggest how can I retrieve linux time using

    struct timespec ts

    type? It just gives me time since Epoch. Can I get the actual Linux time using this datatype?

    Brief Background: I am writing a logger utility on embedded device with timestamp resolution in milli/micro seconds. The source adds timestamp which is consumed by destination component.

    struct stLogItem logitem; //stLogItem has a member, struct timespec ts    
    clock_gettime(clk_id, &logitem.ts);
    

    The destination component is printing this log timestamp on file/console. But the date which is printed out is time since Epoch, and not the actual Linux date.

    The printed data is: 1970-01-01 23:30:07.586864475

    Whereas, the Linux date is different as shown below:

    root@imh:# date

    Tue Nov 14 11:34:12 UTC 2017

    Its not a format issue. It is about getting the current Linux time (in nano seconds).

    • unwind
      unwind over 6 years
      What is "actual Linux time"? Time since the first announcement by Linus? :)
    • alk
      alk over 6 years
      You might like to have a look at localtime*().
    • Irfan
      Irfan over 6 years
      Tue Nov 14 10:06:34 UTC 2017 (after typing "date" on shell)
    • Ronny Brendel
      Ronny Brendel over 6 years
      Google how to get date and time in linux c. time(), localtime()
    • Irfan
      Irfan over 6 years
      I am using struct timespec for best resolution.
    • Irfan
      Irfan over 6 years
      does it suggest that I can not retrieve Linux time through "struct timespec"?
    • tripleee
      tripleee over 6 years
      Returning time as a simple scalar is a feature, not a bug. You have to convert it to a human-readable format separately if that's what you want.
    • tripleee
      tripleee over 6 years
    • danglingpointer
      danglingpointer over 6 years
      Do you want to get the elapsed real time using the clock_gettimecall?
    • Irfan
      Irfan over 6 years
      Its not a conversion problem. Its about getting current time. I am already printing human readable time on console. The output shows it: " 1970-01-01 22:17:01.776871940"
    • Irfan
      Irfan over 6 years
      using timespec, I want to retrieve the same date and time as returned by localtime(...) function.
    • alk
      alk over 6 years
      What is clk_id and how is it set?
    • dbush
      dbush over 6 years
      This update isn't enough. You need to show the actual code that produces the invalid output.
    • Irfan
      Irfan over 6 years
      @dbush, directly after retrieving the ts value by line, "clock_gettime(clk_id, &logitem.ts);", I have used the solution which you have provided and the solution alk has provided. Both of these solutions produce the output I mentioned.
    • Irfan
      Irfan over 6 years
      Please refer to my first comment on alk's post. Which shows output using his solution.
    • dbush
      dbush over 6 years
      When I run his code I get "Date: Tue Nov 28 09:41:03 2017 378233094ns" as output. If running "date" from the shell gives you the proper time, you're doing sometime different. Show your code.
    • Irfan
      Irfan over 6 years
      @alk, the clk_id is CLOCK_REALTIME. Infact, I pass it as it is. Means clk_id was just placeholder for actual value.
    • alk
      alk over 6 years
      Did you take my code as is and compiled it as is, no additions, no removals (despite the ...) to a single main?
  • Irfan
    Irfan over 6 years
    this just prints the output "Thu Jan 1 23:28:20 1970 690758173ns " where as the result of "date" command gives output "Tue Nov 14 10:59:57 UTC 2017". You can see two dates have different time values (just forget about format)
  • Irfan
    Irfan over 6 years
    And this is due to the fact that ts variable has that time. ctime just returns the input time as string
  • alk
    alk over 6 years
    @Irfan: If the above code really gives you "Thu Jan 1 23:28:20 1970 ..." it seems your system clock is messed up, running on the wrong time.
  • dbush
    dbush over 6 years
    @Irfan You should update your question with the actual code that produces that output. It's likely you're doing something else wrong.
  • Jonathan Leffler
    Jonathan Leffler over 6 years
    Note that the tm_year and tm_mon fields of the broken down time have oddball encodings, and strftime() can be used to format time strings (but nanoseconds have to be handled separately and carefully).
  • Gabriel Staples
    Gabriel Staples about 2 years
    Here is the documentation on localtime() and localtime_r(): man7.org/linux/man-pages/man3/localtime.3p.html. Note that localtime() is not thread-safe. If you need a threadsafe version, use the localtime_r() "re-entrant" (thread-safe) version.
  • Gabriel Staples
    Gabriel Staples about 2 years
    Thank you! I used your example to write my own. I needed the help to see how to use localtime(). I've expanded your answer a lot and added a bunch more output, such as formatting the output as Fri Apr 15 14:05:12 2022 -0700, in my own answer here.