【问题标题】:Time stamp in the C programming languageC 编程语言中的时间戳
【发布时间】:2010-11-29 11:43:11
【问题描述】:

如何在 C 中标记两次 t1 和 t2 并获得以毫秒为单位的差异?

【问题讨论】:

  • 你不能单独使用标准 C 来做到这一点。对于 Linux、Windows、手机、收银机、...、微波炉、...,您可能拥有的解决方案会有所不同。
  • @Christoph:time() 和 clock() 都可以返回 -1(转换为适当的类型)以表示该函数在该实现中不可用......和 ​​time(),如果可用, 分辨率为 1 秒或更差。我仔细阅读了标准,但没有发现 clock() 函数有任何硬性限制
  • 在 Linux 手册页中:“请注意,时间可以回绕。在 CLOCKS_PER_SEC 等于 1000000 的 32 位系统上,此函数将大约每 72 分钟返回相同的值。”获取 CPU 时间 getrusage() 更好,虽然时钟是 ANSI C 的一部分,但 getrusage/gettimeofday() 不是。

标签: c time timestamp


【解决方案1】:

这将为您提供以秒 + 微秒为单位的时间

#include <sys/time.h>
struct timeval tv;
gettimeofday(&tv,NULL);
tv.tv_sec // seconds
tv.tv_usec // microseconds

【讨论】:

    【解决方案2】:

    使用gettimeofday() 或更好的clock_gettime()

    【讨论】:

      【解决方案3】:

      你可以尝试c时间库中的例程(time.h)。另外看看同一个库中的clock()。它给出了自 prog 开始以来的时钟滴答声。但是你可以在你想集中精力的操作之前保存它的值,然后在那个操作之后再次捕获 cliock 滴答声并找到 then 之间的差异以获得时间差。

      【讨论】:

        【解决方案4】:

        使用@Arkaitz Jimenez 的代码获得两个时间值:

        #include <sys/time.h>
        //...
        struct timeval tv1, tv2, diff;
        
        // get the first time:
        gettimeofday(&tv1, NULL);
        
        // do whatever it is you want to time
        // ...
        
        // get the second time:
        gettimeofday(&tv2, NULL);
        
        // get the difference:
        
        int result = timeval_subtract(&diff, &tv1, &tv2);
        
        // the difference is storid in diff now.
        

        timeval_subtract 的示例代码可以在this web site找到:

         /* Subtract the `struct timeval' values X and Y,
            storing the result in RESULT.
            Return 1 if the difference is negative, otherwise 0.  */
        
         int
         timeval_subtract (result, x, y)
              struct timeval *result, *x, *y;
         {
           /* Perform the carry for the later subtraction by updating y. */
           if (x->tv_usec < y->tv_usec) {
             int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
             y->tv_usec -= 1000000 * nsec;
             y->tv_sec += nsec;
           }
           if (x->tv_usec - y->tv_usec > 1000000) {
             int nsec = (x->tv_usec - y->tv_usec) / 1000000;
             y->tv_usec += 1000000 * nsec;
             y->tv_sec -= nsec;
           }
        
           /* Compute the time remaining to wait.
              tv_usec is certainly positive. */
           result->tv_sec = x->tv_sec - y->tv_sec;
           result->tv_usec = x->tv_usec - y->tv_usec;
        
           /* Return 1 if result is negative. */
           return x->tv_sec < y->tv_sec;
         }
        

        【讨论】:

        • timeval_subtract 中的代码是邪恶的,因为它修改了输入值 y。如果输入是两个 struct timeval 值,而不是指针,那也不错。但是在计算“x - y”时,您通常不会期望计算会改变存储在“y”中的值。
        • @Jonathan,是的。虽然简单地将其更改为通过复制实现就可以解决这个问题
        • 我同意。我会修复它,但我现在无法仔细检查我的更改是否可以编译,所以我想我会保持原样。
        【解决方案5】:

        如果您想查找经过的时间,只要您在开始和结束之间不重新启动计算机,此方法就可以工作。

        在 Windows 中,使用 GetTickCount()。方法如下:

        DWORD dwStart = GetTickCount();
        ...
        ... process you want to measure elapsed time for
        ...
        DWORD dwElapsed = GetTickCount() - dwStart;
        

        dwElapsed 现在是经过的毫秒数。

        在 Linux 中,使用 clock()CLOCKS_PER_SEC 来做同样的事情。

        如果您需要持续重启或跨 PC 的时间戳(这确实需要非常好的同步),那么请使用其他方法 (gettimeofday())。

        此外,至少在 Windows 中,您可以获得比标准时间分辨率更好的结果。通常,如果您在一个紧密的循环中调用 GetTickCount(),您会看到它每次更改时跳跃 10-50。这是因为 Windows 线程调度程序使用的时间片。这或多或少是它给每个线程在切换到其他东西之前运行的时间。如果你这样做:

        timeBeginPeriod(1);
        

        在您的程序或进程的开头和:

        timeEndPeriod(1);
        

        最后,时间片将变为 1 毫秒,您将在 GetTickCount() 调用中获得更好的时间分辨率。但是,这确实会对整个计算机运行进程的方式产生微妙的变化,因此请记住这一点。不过,Windows Media Player 和许多其他的东西无论如何都会这样做,所以我不太担心。

        我确信在 Linux 中可能有一些方法可以做同样的事情(可能有更好的控制,或者可能使用亚毫秒量子),但我还不需要在 Linux 中这样做。

        【讨论】:

          【解决方案6】:

          标准 C99:

          #include <time.h>
          
          time_t t0 = time(0);
          // ...
          time_t t1 = time(0);
          double datetime_diff_ms = difftime(t1, t0) * 1000.;
          
          clock_t c0 = clock();
          // ...
          clock_t c1 = clock();
          double runtime_diff_ms = (c1 - c0) * 1000. / CLOCKS_PER_SEC;
          

          类型的精度是实现定义的,即日期时间差可能只返回整秒。

          【讨论】:

          • 日期时间差最多返回整秒。如果我正确解释标准,time(),当它不返回 (time_t)-1 时,不能保证每秒返回新值:例如,它可以有 5 秒或 1 分钟的分辨率。
          • @pmg:精度由实现定义,例如在我的系统上time() 具有1s 分辨率; clock() 的精度通常尽可能高,但它测量的是运行时间而不是日期时间
          【解决方案7】:

          还要注意clock() 和usleep() 之间的交互。 usleep() 暂停程序,clock() 只测量程序运行的时间。

          如果使用 here 中提到的 gettimeofday() 可能会更好

          【讨论】:

            【解决方案8】:
            /*
             Returns the current time.
            */
            
            char *time_stamp(){
            
            char *timestamp = (char *)malloc(sizeof(char) * 16);
            time_t ltime;
            ltime=time(NULL);
            struct tm *tm;
            tm=localtime(&ltime);
            
            sprintf(timestamp,"%04d%02d%02d%02d%02d%02d", tm->tm_year+1900, tm->tm_mon, 
                tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
            return timestamp;
            }
            
            
            int main(){
            
            printf(" Timestamp: %s\n",time_stamp());
            return 0;
            
            }
            

            输出:时间戳:20110912130940 // 2011 年 9 月 12 日 13:09:40

            【讨论】:

            • 您可以使用 asctime(tm) 返回字符串,而不是格式化数据。
            【解决方案9】:

            这个解决方案怎么样?我在搜索中没有看到类似的东西。我试图避免分裂并使解决方案更简单。

               struct timeval cur_time1, cur_time2, tdiff;
            
               gettimeofday(&cur_time1,NULL);
               sleep(1);
               gettimeofday(&cur_time2,NULL);
            
               tdiff.tv_sec = cur_time2.tv_sec - cur_time1.tv_sec;
               tdiff.tv_usec = cur_time2.tv_usec + (1000000 - cur_time1.tv_usec);
            
               while(tdiff.tv_usec > 1000000)
               {
                  tdiff.tv_sec++;
                  tdiff.tv_usec -= 1000000;
                  printf("updated tdiff tv_sec:%ld tv_usec:%ld\n",tdiff.tv_sec, tdiff.tv_usec);
               }
            
               printf("end tdiff tv_sec:%ld tv_usec:%ld\n",tdiff.tv_sec, tdiff.tv_usec);
            

            【讨论】:

              【解决方案10】:
              #include <sys/time.h>
              
              time_t tm = time(NULL);
              char stime[4096];
              ctime_r(&tm, stime);
              stime[strlen(stime) - 1] = '\0';
              printf("%s",stime);
              

              【讨论】:

                【解决方案11】:

                这个程序清楚地展示了如何做到这一点。需要时间 1 暂停 1 秒,然后需要时间 2,两次之间的差异应该是 1000 毫秒。所以你的答案是正确的

                #include <stdio.h>
                #include <time.h>
                #include <unistd.h>
                
                // Name: miliseconds.c
                // gcc /tmp/miliseconds.c -o miliseconds
                
                struct timespec ts1, ts2; // time1 and time2
                
                int main (void) {
                
                    // get time1
                    clock_gettime(CLOCK_REALTIME, &ts1);
                    sleep(1); // 1 second pause
                    // get time2
                    clock_gettime(CLOCK_REALTIME, &ts2);
                    // nanoseconds difference in mili
                    long miliseconds1= (ts2.tv_nsec - ts1.tv_nsec) / 10000000 ;
                    // seconds difference in mili
                    long miliseconds2 = (ts2.tv_sec -  ts1.tv_sec)*1000;
                    long miliseconds = miliseconds1 + miliseconds2;
                    printf("%ld\n", miliseconds); 
                
                    return 0;
                }
                

                【讨论】:

                • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
                • 你是对的,我的回答更多是为了改进 AKM Mahmudul Hoque 的回答,而不是回答原始问题。我很困惑,因为他们给了 6 分。即使您的回答显然没有直接回答问题。
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2022-06-14
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2013-08-16
                相关资源
                最近更新 更多