我正在编写一个函数,除其他外,必须打印出已用时间计数器。它通过引用接收开始时间_start
,并将其与current
进行比较,两者都输入为time_t
。我想使用strftime()
以ISO 8601格式打印出观察到的时间差。这是我试图做的事情:
// Negative start time implies program has not begun
if (*_start > 0) {
time_t elapsed = current - *_start;
strftime(time_str, sizeof(time_str) - 1, "%T", localtime(&elapsed));
printf("%s\n", time_str);
}
这是我在运行程序后立即获得的输出
01:00:00
01:00:00
01:00:01
01:00:01
01:00:01
秒工作正常,如果我让它运行得更长,它们会按预期增加,所以分钟,但小时从01开始而不是00.为什么会发生这种情况?我怎样才能让时间开始归零,比如分钟?
答案 0 :(得分:3)
time_t
通常(参见编辑)存储绝对时间戳(自UTC,1970年1月1日午夜起的秒数)。通过计算current - *_start
,您将获得经过的时间(以秒为单位)(根据需要),但是然后将其传递给localtime
和strftime
,您告诉计算机要花费时间自程序启动以来,将其视为自UTC时间1-1-1970午夜起的时间。
我猜你的系统当地时区恰好是01:00:00。
我不知道打印已用时间的C99功能,但是自己写一个并不难。
void format_elapsed_time(char *time_str, int total_seconds_elapsed) {
int hours_elapsed = total_seconds_elapsed / 3600;
int minutes_elapsed = (total_seconds_elapsed % 3600) / 60;
int seconds_elapsed = total_seconds_elapsed % 60;
sprintf(time_str, "%02i:%02i:%02i", hours_elapsed, minutes_elapsed, seconds_elapsed);
}
编辑:正如@chux指出的那样,time_t
不必将时间戳存储为自1-1-1970以来的秒数。有关详细信息,请参阅this answer。
答案 1 :(得分:1)
为了便于查找2 time_t
之间经过的秒数,请使用difftime()
作为减去2 time_t
值,但未在C中指定为秒的差异。
double difftime(time_t time1, time_t time0);
C11dr§7.26.2.2
difftime
函数返回以秒为单位的差值double
。
double elapsed_seconds = difftime(current, *_start);
printf("elapsed_seconds: %f\n", elapsed_seconds);
答案 2 :(得分:1)
如果您想使用此方法,您应该知道time()
返回UTC。如果您从 local 时间(由localtime()
返回)减去该时间,则时区将对结果产生影响(可能您的特定时区已从UTC移除一小时)。
考虑以下完整程序,类似于您的代码段:
#include <stdio.h>
#include <time.h>
#include <unistd.h>
int main(void) {
time_t start = time(0);
char time_str[100];
for (int i = 5; i > 0; i--) {
sleep (1);
time_t elapsed = time(0) - start;
strftime(time_str, sizeof(time_str) - 1, "%T", localtime(&elapsed));
printf("%s\n", time_str);
}
return 0;
}
还要考虑我的特定时区已从UTC中移除八小时:
pax> date ; date -u
Thursday 30 March 10:25:57 AWST 2017
Thursday 30 March 02:25:57 UTC 2017
当我运行它时,我看到:
08:00:01
08:00:02
08:00:03
08:00:04
08:00:05
您可以看到与UTC的8小时时差影响该值。 修复实际上非常简单:根本不使用本地时间。如果您使用localtime()
替换gmtime()
来电,则会获得您期望的输出:
00:00:01
00:00:02
00:00:03
00:00:04
00:00:05
答案 3 :(得分:0)
我意识到这个问题已经有了答案,但我想我可能会把焦点转移一点,然后扩展接受的答案。由于OP指定它们正在处理经过时间,因此可以避免使用clock()函数完全处理绝对时间戳。
clock_t start = clock();
.
.
clock_t end = clock();
double elapsed = (end - start) / (double)CLOCKS_PER_SEC;
然后你可以调用名义上修改过的format_elapsed_time()函数,如下所示:
void format_elapsed_time(char *time_str, double elapsed) {
int h, m, s, ms;
h = m = s = ms = 0;
ms = elapsed * 1000; // promote the fractional part to milliseconds
h = ms / 3600000;
ms -= (h * 3600000);
m = ms / 60000;
ms -= (m * 60000);
s = ms / 1000;
ms -= (s * 1000);
sprintf(time_str, "%02i:%02i:%02i.%03i", h, m, s, ms);
}