3

Having found many quite old questions about this subject, I wonder if getting the current time in Linux C with year, month, day, hours, minutes, seconds and milliseconds still is so cumbersome these days.

I searched a lot but there are either structs holding the wall time without milliseconds, or structs returning the current time in milliseconds that I have to convert into wall time separately, or functions that return seconds and milliseconds in extra fields which would be ok to use but isn't what I'd call elegant.

Does a time struct like this

struct TIME_WITH_ALL_FIELDS now;
get_now(&now);
print ("today is ...",
  now.year, now.month, now.day,
  now.hour, now.minute, now.second, now.millisecond);

really not exist yet?

Droidum
  • 440
  • 2
  • 9
  • I guess they don't see it as necessary since you can do much of the calculations on milliseconds. – Irelia Jun 16 '23 at 10:42
  • What makes you think milliseconds is at all relevant on an OS which doesn't even guarantee that kind of real-time performance? Might as well print decimals of pi. – Lundin Jun 16 '23 at 10:45
  • I need this to populate incoming data with a timestamp that resolves better than seconds. Milliseconds and even microseconds exist - but not in a way easy to handle, that's what makes me wonder. – Droidum Jun 16 '23 at 10:48
  • https://stackoverflow.com/a/47532809/6082851 – 12431234123412341234123 Jun 16 '23 at 11:11
  • 1
    Originally, Unix only provided `time(2)` which only gives seconds, and so all "time of day" calculations are based on seconds. Later APIs added microseconds, nanoseconds, etc, but left the seconds alone so that existing time-of-day functions could still be used. You could imagine replacement APIs in C, but they would just amount to rearranging arguments without providing any new functionality, so nobody has bothered. In C++ there is [`std::chrono`](https://en.cppreference.com/w/cpp/chrono) which is probably the "elegant" interface you are looking for. – Nate Eldredge Jun 17 '23 at 19:54

2 Answers2

4

This is the way you get the time on Linux:

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

int main(void)
{
  struct timespec ts;    
  if(clock_gettime(CLOCK_REALTIME, &ts)<0)
    { perror("Can not get time"); return 1; }

  struct tm l;
  if(!gmtime_r(&ts.tv_sec,&l))
    { perror("Can not convert time"); return 1; }

  printf
    (
      "Timestamp (UTC): %04i-%02i-%02iT%02i:%02i:%02i.%03li \n", 
      l.tm_year+1900, l.tm_mon+1, l.tm_mday, l.tm_hour, l.tm_min, l.tm_sec, ts.tv_nsec/1000000
    );
}

If you think this isn't good enough for you, then you shouldn't use C.

It should be obvious why the syscall does only return time in second and nanosecond, and don't tell you anything about the day, year and month. This is why you have to convert it after you get the time from the kernel.

  • "If you think this isn't good enough for you, then you shouldn't use C." well one always wants to learn more, in this case perhaps something better exists, so why shouldn't I ask ;-) – Droidum Jun 17 '23 at 07:23
0

You can get elapsed nano second from 1.1.1970 ( utc ) and so also milliseconds. Its possible to calculate date and time from the returned 64 bit value, but you have to handle time zone and daylight saving. ( calculate a offset )

include <time.h>

unsigned long long Getns()
{
  struct timespec ts;
  clock_gettime(CLOCK_REALTIME,&ts);
  //clock_gettime(CLOCK_MONOTONIC, &ts);
  return (ts.tv_sec * 1000000000) + ts.tv_nsec; 
}