9

Here's the sort of time formatting I'm after:

2009-10-08 04:31:33.918700000 -0500

I'm currently using this:

strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", ts);

Which gives:

2009-10-11 13:42:57 CDT

Which is close, but not exact. I can't seem to find anything on displaying -0500 at the end. Plus I'm getting the seconds as an int.

How can I resolve these two issues?

kiritsuku
  • 52,967
  • 18
  • 114
  • 136
Vlad the Impala
  • 15,572
  • 16
  • 81
  • 124

3 Answers3

24

I came up with this:

    char            fmt[64], buf[64];
    struct timeval  tv;
    struct tm       *tm;

    gettimeofday(&tv, NULL);
    if((tm = localtime(&tv.tv_sec)) != NULL)
    {
            strftime(fmt, sizeof fmt, "%Y-%m-%d %H:%M:%S.%%06u %z", tm);
            snprintf(buf, sizeof buf, fmt, tv.tv_usec);
            printf("'%s'\n", buf); 
    }

Fixes for the problems you had:

  • Use gettimeofday(), and struct timeval, which has a microseconds member for the higher precision.
  • Use a two-step approach, where we first build a string containing all the data except the microseconds.
  • Use lower-case 'z' for the timezone offset. This seems to be a GNU extension.

I tried re-creating the timezone offset manually, through the second struct timezone * argument of gettimeofday(), but on my machine it returns an offset of 0 which is not correct. The manual page for gettimefday() has quite a lot to say about the handling of timezones under Linux (which is the OS I tested on).

unwind
  • 391,730
  • 64
  • 469
  • 606
  • 1
    `%z` is still non-standard =) – gnud Oct 11 '09 at 20:18
  • Thanks, this is the closest I've gotten so far. The '%%06u' is just throwing garbage data back at me right now but the rest works well. P.S Yes, I know the %z is non-standard, but I'll take it :) – Vlad the Impala Oct 11 '09 at 20:40
  • @aditya: That's weird ... The code above should work. Make sure you provide the second snprintf() call with a proper unsigned microseconds value to use for the %06u format. You can try printing the result after the strftime() call, you should see your final output except for the %06u sequence after the period. – unwind Oct 11 '09 at 20:55
  • 4
    It seems everyone here have missed the fact that %z is completely standard C99. It's in (the freely available) draft n1256 (tc3 working paper) as well as the official standard document, and it is also specified in POSIX (http://pubs.opengroup.org/onlinepubs/9699919799/functions/strftime.html). – Quantumboredom Mar 21 '13 at 19:11
  • 1
    `tv.tv_usec` is type `suseconds_t`. Have not found a % modifier for it. Maybe a cast to (unsigned long) and use `%06lu`. (or cast to (uintmax_t) and use PRIuMAX. – chux - Reinstate Monica Aug 25 '13 at 00:47
  • I think the reason %%06u is throwing garbage is because the usec may be a long int, not an int. So you may need to use %%06lu instead. – Martin C. Martin Aug 27 '14 at 15:17
  • `%z` can be also printed using `timezone::tz_minutewest` or `tm::tm_gmtoff`. The last one seems to be non-standard, though. – newbie Jun 10 '15 at 11:37
1

%z (lower case z).

However, this does not appear in the Posix specification. Google took me in a circle back here.

Community
  • 1
  • 1
1

"%Y-%m-%d %T %z", but it seems %z is a GNU extension.

gnud
  • 77,584
  • 5
  • 64
  • 78