4

I am trying to convert time string into time format in C on windows. As i just have hour, minutes and seconds in my string, so tried to parse the string using sscanf into time format and then use mktime. But somehow its not converting it into time format. To check, i tried to print the converted time into string back. The code looks like:

struct tm tm;
char time_buffer[100];
int hh, mm;
float ms;
time_t time_value;
char *timestamp = {"16:11:56.484"};
sscanf(timestamp, "%d:%d:%f", &hh, &mm,&ms);
tm.tm_hour =hh;
tm.tm_min = mm;
tm.tm_sec = ms*1000;
tm.tm_isdst = -1;
time_value = malloc(100*sizeof(char));
time_value = mktime(&tm);
if (time_value==-1)
    printf ("unable to make time");
strftime(time_buffer, sizeof(time_buffer), "%c", &tm);
printf(time_buffer);
maskacovnik
  • 3,080
  • 5
  • 20
  • 26
learningpal
  • 309
  • 1
  • 8
  • 17

2 Answers2

4
  1. you don't initialize your struct tm but only set tm_hour, tm_min, tm_sec and tm_isdst. All other fields are not initialized and therefore have unknown/undefined values.
  2. If you'd initialize your struct tm with a memset(&tm, 0, sizeof(tm)), you'd probably still receive an error because the fields held by the struct don't all allow 0 as valid value (tm_mday). See the docs for reference.
  3. The value you put into tm_sec is likely to be invalid. You actually want it to be ms/1000, not ms*1000.
eckes
  • 64,417
  • 29
  • 168
  • 201
  • It is only **defined** in time.h. You declare the variable, so you have to initialize it. If you're still learning: it's a good habit to initialize **every** variable you declare with a defined value. – eckes Jul 13 '15 at 09:57
  • @ eckes: Thanks much for your comments. I initialized it as: tm.tm_hour = 16; tm.tm_min = 11; tm.tm_sec = 56.484*1000; But still its showing "unable to make time" – learningpal Jul 13 '15 at 11:01
  • @learningpal: read carefully: *you have to initialize **every field** provided by `tm`*. Not only those that you fill with actual values like `tm_hour`... – eckes Jul 13 '15 at 12:15
  • I am usine these three variables in my code, hour, minute and seconds and I initialized them. By every field do you mean the days and months name? Or Can you explain by an example what you actually mean? And 'tm_sec', I require (ms*1000), because I need to get the time in milliseconds – learningpal Jul 13 '15 at 12:28
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/83121/discussion-between-learningpal-and-eckes). – learningpal Jul 13 '15 at 12:28
  • @ eckes: Thanks a lot for your time and suggestions.. :) – learningpal Jul 13 '15 at 16:20
4

Before calling mktime(), code needs to initialize 7+ fields of tm_struct(): year, month,day, hour min, sec, isdst and potentially others.

2 exceptions: .tm_yday, .tm_wday do not need assignment before calling mktime().

The year, month, day should be set to something reasonable: let us use 2000 Jan 1. Alternatively code could use time_t() to get today.

Code uses ms hinting that the value is in milliseconds. It is not. It is still in seconds.

Use local time_t variable rather than allocating one. malloc() not needed.

struct tm tm = {0};
tm.tm_year = 2000 - 1900;  // Years from 1900
tm.tm_mon = 1 - 1; // Months from January
tm.tm_mday = 1;
char time_buffer[100];
int hh, mm;
float ss;
time_t time_value;
char *timestamp = "16:11:56.484";

if (sscanf(timestamp, "%d:%d:%f", &hh, &mm,&ss) != 3) Handle_BadData();
tm.tm_hour = hh;
tm.tm_min = mm;
tm.tm_sec = roundf(ss);  // or simply = ss;
tm.tm_isdst = 0;  // Keep in standard time
// time_value = malloc(100*sizeof(char));
time_value = mktime(&tm);
if (time_value == -1) {
    printf ("unable to make time");
}
else {
  strftime(time_buffer, sizeof(time_buffer), "%c", &tm);
  printf(time_buffer);
}

// Sat Jan  1 16:11:56 2000
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • @ chux: Thanks much. I was not initializing all the variables of struct tm. But the time value I need in milliseconds, can you explain how to get that time in milliseconds too. – learningpal Jul 13 '15 at 14:33
  • 1
    Code _cannot_ portably save the time value in milliseconds using `time_t` - `time_t` being the type result of `mktime()`. C does not specify how `time_t` values are encoded other than that it is a number. Most (not all) have `time_t` as an integer count of seconds since Jan 1, 1970 - see [unix time](https://en.wikipedia.org/wiki/Unix_time). Code could use its own structure, maybe one including a field for `time_t` and another for fraction of seconds. Many OS have used `typedef struct timeval { long tv_sec; long tv_usec; } timeval;` or something like that - so no need to re-invent the wheel. – chux - Reinstate Monica Jul 13 '15 at 14:57
  • 1
    @learningpal _getting_ the milliseconds value is easy `float ms = modff(ss, NULL) * 1000.0f;` So now that code has the milliseconds value, what do you want to do with it? – chux - Reinstate Monica Jul 13 '15 at 15:01
  • @ chux: Thanks a lot.. :) I am implementing your code but when I initialize the tm_year, tm_mon and tm_mday as your did, I get error : "expected '=', ',', ';', 'asm' or '__attribute__' before '.' token|" – learningpal Jul 13 '15 at 15:36
  • Perhaps code is missing a preceding `#include `? – chux - Reinstate Monica Jul 13 '15 at 15:43
  • You may be using an old school compiler. Put all the variable declarations before the assignments: `struct tm tm; char time_buffer[100]; ...char *timestamp = "16:11:56.484"; tm.tm_year = 2000 - 1900;... tm.tm_mday = 1;`. – chux - Reinstate Monica Jul 13 '15 at 15:53
  • 1
    @ chux: ya you are right. It works now.. Thanks a lot.. :) I was working on it from last 1 week but didnt get these errors of initialization. – learningpal Jul 13 '15 at 16:20
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/83186/discussion-between-learningpal-and-chux). – learningpal Jul 14 '15 at 10:16