8

I want to convert milliseconds into timespec structure used by GNU Linux. I have tried following code for the same.

  timespec GetTimeSpecValue(unsigned long milisec)
  {
    struct timespec req;
    //long sec = (milisecondtime /1000);
    time_t sec = (time_t)(milisec/1000);
    req->tv_sec = sec;
    req->tv_nsec = 0;
    return req;
  }

Running this code gives me the following error.

expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘GetTimeSpecValue’

I have also include time.h file in the code.

jww
  • 97,681
  • 90
  • 411
  • 885
jparthj
  • 1,606
  • 3
  • 20
  • 44
  • Hm, either time.h was not included properly or there is missing semicolon somewhere above. – KBart Feb 22 '13 at 12:51
  • well, that is not the case. I have already gone through entire code and no such mistakes i found. :-( – jparthj Feb 22 '13 at 12:52
  • 4
    There are multiple errors in your code. There is no `tv` declared which you try to return (I guess you want to return `req` instead). `req` is not a pointer but you try to access it via `->`. And you have to return `struct timespec` instead of `timespec`. – scai Feb 22 '13 at 13:01

3 Answers3

12

The timespec structure represents time in two portions — seconds and nanoseconds. Thus, the algorithm for conversion from milliseconds is pretty darn simple. One seconds has thousand milliseconds, one milliseconds has a thousand microseconds and one microsecond has a thousand nanoseconds, for which we are grateful to SI. Therefore, we first need to divide milliseconds by a thousand to get a number of seconds. Say, for example, 1500 milliseconds / 1000 = 1.5 seconds. Given integer arithmetics (not a floating point), the remainder is dropped (i.e. 1500 / 1000 is equal to just 1, not 1.5). Then we need to take a remainder that denotes a number of milliseconds that is definitely less than one second, and multiply it by a million to convert it to nanoseconds. To get a remainder of dividing by 1000, we use a module operator (%) (i.e. 1500 % 1000 is equal to 500). For example, let's convert 4321 milliseconds to seconds and nanoseconds:

  1. 4321 (milliseconds) / 1000 = 4 (seconds)
  2. 4321 (milliseconds) % 1000 = 321 (milliseconds)
  3. 321 (milliseconds) * 1000000 = 321000000 (nanoseconds)

Knowing the above, the only thing that is left is to write a little bit of C code. There are few things that you didn't get right:

  1. In C, you have to prefix structure data types with struct. For example, instead of saying timespec you say struct timespec. In C++, however, you don't have to do it (unfortunately, in my opinion).
  2. You cannot return structures from the function in C. Therefore, you need to pass a structure by pointer into a function that does something with that structure.

Edit: This contradicts (Return a `struct` from a function in C).

OK, enough talking. Below is a simple C code example:

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

static void ms2ts(struct timespec *ts, unsigned long ms)
{
    ts->tv_sec = ms / 1000;
    ts->tv_nsec = (ms % 1000) * 1000000;
}

static void print_ts(unsigned long ms)
{
    struct timespec ts;
    ms2ts(&ts, ms);
    printf("%lu milliseconds is %ld seconds and %ld nanoseconds.\n",
           ms, ts.tv_sec, ts.tv_nsec);
}

int main()
{
    print_ts(1000);
    print_ts(2500);
    print_ts(4321);
    return EXIT_SUCCESS;
}

Hope it helps. Good Luck!

Community
  • 1
  • 1
  • 1
    Wouldn't this be better/faster to use `ts->tv_nsec = (ms - (ts->tv_sec * 1000)) * 1000000`, mod is a slow operation, especially on processors that do not have a hardware FPU – Geoffrey Jul 24 '13 at 08:58
  • It should be noted that some functions, such as pthread_mutex_cond_timedwait use a timestamp in tv_sec... this one had me scratching my head for a while. – Geoffrey Jul 24 '13 at 11:52
  • I liked your explanation !. – jfk Feb 28 '17 at 16:08
1

try this:

struct timespec GetTimeSpecValue(unsigned long millisec) {
    struct timespec req;
    req.tv_sec=  (time_t)(millisec/1000);
    req.tv_nsec = (millisec % 1000) * 1000000;
    return req;
}

I don't think struct timespec is typedef'ed,hence you need to prepend timespec with struct. And work out the nano second part if you want to be precise. Note that req is not a pointer. Thus members cannot be accessed with '->'

Cœur
  • 37,241
  • 25
  • 195
  • 267
hetepeperfan
  • 4,292
  • 1
  • 29
  • 47
  • 1
    If he just gets milliseconds as input he cannot calculate any nanoseconds :). – scai Feb 22 '13 at 13:24
  • True:) but he can update tv_nsec to as precise as possible given input is milli seconds. I'll fix it in my post – hetepeperfan Feb 22 '13 at 13:28
  • I had no use for nano second..and i corrected my mistake and your help did the trick..many thanks – jparthj Feb 22 '13 at 14:26
  • 1
    @jparthj: If you have no use of nanoseconds, then you'll lose everything that is less than a second. It does sound very bad because a second is like "forever" for a computer, and saying that `1999` milliseconds is just one second may play a bad joke with your program. So be careful! –  Feb 22 '13 at 14:29
0

Incorporating a few tweaks to the answer including Geoffrey's comment, the code below avoids divides for small delay and modulo for long delay:

void msec_to_timespec(unsigned long msec, struct timespec *ts)
{
    if (msec < 1000){
        ts->tv_sec = 0;
        ts->tv_nsec = msec * 1000000;
    }
    else {
        ts->tv_sec = msec / 1000;
        ts->tv_nsec = (msec - ts->tv_sec * 1000) * 1000000;
    }
}
trench_digger
  • 285
  • 2
  • 8