portable way to get time

2019-07-09 03:09发布

问题:

Since Mac OS X doesn't support get time, I found this gist that made a portable way to use the clock_gettime fund here:

void current_utc_time(struct timespec *ts) {

#ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time
    clock_serv_t cclock;
    mach_timespec_t mts;
    host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
    clock_get_time(cclock, &mts);
    mach_port_deallocate(mach_task_self(), cclock);
    ts->tv_sec = mts.tv_sec;
    ts->tv_nsec = mts.tv_nsec;
#else
  clock_gettime(CLOCK_REALTIME, ts);
#endif
}

using it like this

struct timespec requestStart;
current_utc_time(&requestStart);
printf("start: s:  %lu\n", requestStart.tv_sec);
printf("start: ns: %lu\n", requestStart.tv_nsec);
start: s:  1435988139
start: ns: 202015000

I am trying to get the seconds and milliseconds value from this code, is this the correct way to get milliseconds from the nanoseconds value?

printf("total: ms:  %lu\n", (requestStart.tv_nsec - requestEnd.tv_nsec) / (unsigned long)1000000);

If so, how do I get the seconds value? If not how can I get the milliseconds and seconds value?

edit In response to the first comment, I am mainly looking for a way to have the code as portable as possible.

回答1:

If you want portability, just use gettimeofday. That should work everywhere. clock_gettime appears to be Linux-specific a relatively recent Posix introduction.

On converting: struct timeval (used by gettimeofday and other older functions) uses microseconds. The newer struct timespec uses nanoseconds. So to convert back and forth, you would multiply or divide by 1000.

When computing differences, you have to worry about carry/overflow, so your expression

(requestStart.tv_nsec - requestEnd.tv_nsec) / (unsigned long)1000000

is incorrect for two reasons: the difference might come out negative (that is, if the time went from 123.456 to 124.321), and you're scaling it by too much.

When I'm timing some operation, I usually do it something like this:

struct timeval before, after, elapsed;
gettimeofday(&before, NULL);
sleep(1);
gettimeofday(&after, NULL);
elapsed.tv_sec = after.tv_sec - before.tv_sec;
if(after.tv_usec >= before.tv_usec)
        elapsed.tv_usec = after.tv_usec - before.tv_usec;
else    {
        elapsed.tv_sec--;
        elapsed.tv_usec = 1000000 + after.tv_usec - before.tv_usec;
        }
printf("elapsed: %d.%06ld\n", (int)elapsed.tv_sec, (long)elapsed.tv_usec);

If I then wanted a struct timespec (using nanoseconds), I'd multiply by 1000:

struct timespec elapsed2;
elapsed2.tv_sec = elapsed.tv_sec;
elapsed2.tv_nsec = elapsed.tv_usec * 1000;
printf("elapsed: %d.%09ld\n", (int)elapsed2.tv_sec, (long)elapsed2.tv_nsec);

To convert from a struct timespec back to a struct timeval, I'd divide by 1000:

struct timeval elapsed3;
elapsed3.tv_sec = elapsed2.tv_sec;
elapsed3.tv_usec = elapsed2.tv_nsec / 1000;

Another useful thing is to pull out seconds and subseconds as floating point:

double e = (double)elapsed.tv_sec + elapsed.tv_usec / 1e6;
double e2 = (double)elapsed2.tv_sec + elapsed2.tv_nsec / 1e9;
printf("float: %f %f\n", e, e2);

(It turns out that there can be subtleties when writing this sort of code, depending on the actual types of tv_sec and tv_usec or tv_nsec, and on the "helpful" warnings your compiler might choose to give you. See this question.)



回答2:

#import <time.h>
#import <sys/timeb.h>

struct timeb timebCurrentTime;

ftime(&timebCurrentTime);
double y = (double)timebCurrentTime.time + (double)timebCurrentTime.millitm / 1000;//current time in sec since 1970-01-01 00:00:00 +0000 (UTC)


标签: c loops timer