1

The request is accept a specific time and calculate how many time elapsed since 1970/01/01 00:00:00 Need taking millisecond into account!

For example, input a date time: 2009/08/06 14:35:19.42 The result show: 124958371942

As I know, time_t is only take care how many seconds elapsed since 1970/01/01 and struct tm has no millisecond attribute to set

I try to use mktime and get the wrong result: 1249540519ll

struct tm t;
t.tm_year = 2009 - 1900;
t.tm_mon = 7;
t.tm_mday = 6;
t.tm_hour = 14;
t.tm_min = 35;
t.tm_sec = 19;

wprintf(L"%ull\n", mktime(&t));

What API should use for this case? Thanks!

YS Wang
  • 177
  • 13
  • Can't you add milliseconds to mktime's result? – Basilevs Nov 21 '14 at 02:02
  • Sorry, I didn't get your point... – YS Wang Nov 21 '14 at 02:05
  • mktime_seconds*1000 + milliseconds – Basilevs Nov 21 '14 at 02:12
  • 1249540519ll * 1000 + 42 = 1249540519ll042 != 124958371942 :( – YS Wang Nov 21 '14 at 02:14
  • 1
    Why do you think mktime returns incorrect result? [Have you set a correct timezone?](http://stackoverflow.com/questions/530519/stdmktime-and-timezone-info) – Basilevs Nov 21 '14 at 02:16
  • You could also use [gettimeofday(2)](http://linux.die.net/man/2/gettimeofday). – chrk Nov 21 '14 at 02:29
  • possible duplicate of [What should I use to replace gettimeofday() on Windows?](http://stackoverflow.com/questions/1676036/what-should-i-use-to-replace-gettimeofday-on-windows) – Basilevs Nov 21 '14 at 02:50
  • 1
    There is a confusion between timezones. `2009/08/06 14:35:19.42` is local time as it gets 124958371942 and `mktime()` is referencing difference between local and `1970/01/01 00:00:00` Universal time UTC. Need to account for the apparent 4 hours difference. So @Basilevs, maybe more to it than `mktime_seconds*1000 + milliseconds` Ronald, what timezone are your 2 timestamps? – chux - Reinstate Monica Nov 21 '14 at 03:04
  • Got it, it's timezone different issue. Thanks! – YS Wang Nov 21 '14 at 03:16

1 Answers1

0

It appears with 124958371942, OP is counting centiseconds and not milliseconds. There also is a timezone issue. It appears the 1970 timestamp is UTC and the 2009 date may be local.

Various approaches to cope with timezone differences.

A comon approach is to assume both the 2009/08/06 14:35:19.42 and 1970/01/01 00:00:00 are universal time. Another is that they are both local time. The following assumes both local time.

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

void tt(void) {

  struct tm t = { 0 }; // important to set _all_ fields

  t.tm_year = 2009 - 1900;
  t.tm_mon = 8 - 1;
  t.tm_mday = 6;
  t.tm_hour = 14;
  t.tm_min = 35;
  t.tm_sec = 19;
  t.tm_isdst = -1;  // Unless known let code determine if it is DST or not.
  time_t t1 = mktime(&t);
  printf("%10lld\n", (long long) t1);

  t.tm_year = 1970 - 1900;
  t.tm_mon = 1 - 1;
  t.tm_mday = 1;
  t.tm_hour = 0;
  t.tm_min = 0;
  t.tm_sec = 0;
  t.tm_isdst = -1;
  time_t t0 = mktime(&t);
  printf("%10lld\n", (long long) t0);

  printf("%lf\n", difftime(t1, t0) * 1000.0);
}

// Of course these are per my timezone value
1249587319
     21600
1249565719000.000000

Some details:

struct tm() may have a sub-seconds field. That is why it is important to zero the entire structure. Only 9 fields are specified, others may exist. Two fields, tm_wdayand tm_yday do not need to be initialize before calling mktime(), but at least 7 of them should be set including tm_isdst.

difftime() is the portable way to subtract timestamps.

When printing time_t, the value is typically the integer count of seconds since 1970 without leap seconds. Converting to long long is a reasonable, but not absolute portable method of printing.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256