【问题标题】:portable way to get time打发时间的便携方式
【发布时间】:2015-07-04 05:40:53
【问题描述】:

由于 Mac OS X 不支持获取时间,我在这里找到了一个使用 clock_gettime 基金的便携方式的要点:

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
}

这样使用

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

我正在尝试从此代码中获取秒和毫秒值,这是从纳秒值中获取毫秒的正确方法吗?

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

如果是这样,我如何获得秒值?如果不是,我怎样才能得到毫秒和秒值?

编辑 针对第一条评论,我主要是在寻找一种使代码尽可能可移植的方法。

【问题讨论】:

  • 这是 so 不是 ANSI C :-) 无论如何,真正的标准是 ISO,ANSI 只是当今的馈线机构之一。
  • MacOS 没有获取系统时间的简单界面?真是难以置信!
  • @wallyk 正如你从苹果官方文档中看到的那样,我使用了他们在上面的函数中提供的计时器。这是文档:developer.apple.com/library/ios/technotes/tn2169/_index.html 我更关心的是从上述函数将纳秒转换为秒和毫秒。
  • 您是否尝试与-lrt 链接? clock_gettime(3) 是一个符合 POSIX 的函数,但在几种架构中,您必须链接它或使用 #define _POSIX_SOURCE 宏来访问它。

标签: c loops timer


【解决方案1】:

如果您想要可移植性,只需使用gettimeofday。这应该在任何地方都有效。 clock_gettime 似乎是Linux 特有的一个相对较新的 Posix 介绍。

转换时:struct timeval(由gettimeofday 和其他旧函数使用)使用微秒。较新的struct timespec 使用纳秒。因此,要来回转换,您需要乘以或除以 1000。

计算差异时,您必须担心进位/溢出,因此您的表达式

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

不正确有两个原因:差异可能是负数(也就是说,如果时间从 123.456 变为 124.321),并且您将其缩放太多。

当我在计时某些操作时,我通常会这样做:

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);

如果我想要struct timespec(使用纳秒),我会乘以 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);

要从 struct timespec 转换回 struct timeval,我会除以 1000:

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

另一个有用的东西是把秒和亚秒作为浮点数:

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);

(事实证明,编写此类代码时可能存在细微差别,具体取决于tv_sectv_usectv_nsec 的实际类型,以及编译器可能选择给出的“有用”警告你。见this question。)

【讨论】:

  • 这是我见过的最详细的答案,对我帮助很大。因此,您可以从这些不同的时间结构进行转换。
  • 次要:printf("elapsed: %d.%09ld\n", (int)elapsed2.tv_sec, (long)elapsed2.tv_nsec); (long) 不需要转换,因为字段 tv_nsec 指定为 long。将time_t tv_sec 转换为int 的字段很容易缩小:考虑"%lld", (long long) elapsed2.tv_sec 以避免en.wikipedia.org/wiki/Year_2038_problem
【解决方案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)

【讨论】:

  • 1) 你能补充一点解释吗? 2)我认为你的意思是#include,而不是#import
猜你喜欢
  • 2015-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-28
  • 1970-01-01
  • 1970-01-01
  • 2014-09-12
相关资源
最近更新 更多