根据输入数据的数量,我有一个可以在几秒钟或几天内运行的程序。在程序结束时,我想打印经过的“时钟墙”时间:如果小于一分钟,则以秒为单位;如果小于一小时,则以分秒为单位;如果小于一小时,则以时分秒为单位。少于一天,否则以天时分秒为单位。这是我正在使用的代码:

#include <cstdio>
#include <ctime>
#include <unistd.h> // for sleep

int main (int argc, char ** argv)
{
  time_t startRawTime, endRawTime;

  time (&startRawTime);
  printf ("%s", ctime (&startRawTime));

  sleep (3); // any preprocessing of input data

  time (&endRawTime);
  printf ("%s", ctime (&endRawTime));

  printf ("%.0fs\n", difftime (endRawTime, startRawTime));

  time_t elapsed = static_cast<time_t>(difftime (endRawTime, startRawTime));
  struct tm * ptm = gmtime (&elapsed);
  printf ("%id %ih %im %is\n", ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);

  return 0;
}


这是打印的内容:

Mon Apr  9 14:43:16 2012
Mon Apr  9 14:43:19 2012
3s
1d 0h 0m 3s


当然,最后一行是错误的(应该为“ 0d”)。看来可以通过打印ptm->tm_mday - 1轻松解决。但是,当两个日期之间确实经过了一天时,ptm->tm_mday也将为“ 1”。因此,在那种情况下,我不想使其显示为“ 0d”。

那么有没有办法正确处理呢?还是我应该将difftime的结果作为双精度值(即秒数),然后计算自己的秒/分钟/小时/天数?

备注:我的代码仅在使用gcc -lstdc++编译的Linux上使用。

最佳答案

time_t值表示特定的时刻。 difftime的结果是两分钟之间的时间间隔(以秒为单位)。那是完全不同的事情。

在您的代码中,difftime()返回3.0,因为两个指定时间之间有3秒。将其转换为time_t会在纪元后3秒钟给您一点时间;在大多数系统上,这将是格林尼治标准时间1970年1月1日午夜3秒钟之后。tm_mday值为1,因为那是该月的第一天。

您可以通过从tm_mday值中减去1来实现此目的,因为tm_mday是基于1的,而不是基于0的。但是在更长的时间间隔内,您仍然会获得毫无意义的结果。例如,间隔31.5天将使您在2月1日中午,因为1月为31天;与您要获取的信息无关。

只需将difftime()的结果视为double(因为它就是这样),然后通过简单的算术计算天数,小时数,分钟数和秒数。

(由于失去了可移植性,您可以直接对time_t值进行求和,而不是使用difftime()。这会使某些算法更容易一些,但是在time_t值与其他值不同的系统上会破坏距某个纪元以来的整数秒数。difftime()存在是有原因的。)


  当然,最后一行是错误的(应该为“ 0d”)。看来可以
  通过打印“ ptm-> tm_mday-1”可以轻松解决。但是,ptm-> tm_mday
  如果两者之间确实有一天过去了,则也将为“ 1”
  日期。因此,在那种情况下,我不想使其显示为“ 0d”。


那是不对的。如果时间间隔刚好超过1天,则ptm->tm_mday将为2。您可以通过对代码进行少量修改来验证这一点:

time (&endRawTime);
endRawTime += 86400; // add this line
printf ("%s", ctime (&endRawTime));


进行更改时,将得到以下输出:

Mon Apr  9 13:56:49 2012
Tue Apr 10 13:56:52 2012
86403s
2d 0h 0m 3s


可以通过从ptm->tm_mday减去1来更正。但这又不是正确的方法。

10-04 21:15