C中的格式化经过时间
Formatted elapsed time in C
我正在编写一个函数,除其他外,它必须打印出经过的时间计数器。它通过引用接收开始时间 _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。为什么会这样?我怎样才能让开始的时间像分钟一样归零?
time_t
通常(请参阅编辑)存储绝对时间戳(自 1970 年 1 月 1 日午夜 UTC 以来的秒数)。通过计算 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。
要方便地查找 2 time_t
之间经过的秒数,请使用 difftime()
因为 C 中未指定减去 2 time_t
值作为秒数差。
double difftime(time_t time1, time_t time0);
C11dr §7.26.2.2
The difftime
function returns the difference expressed in seconds as a double
.
double elapsed_seconds = difftime(current, *_start);
printf("elapsed_seconds: %f\n", elapsed_seconds);
如果你想使用这个方法,你应该知道time()
returns 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 的八小时时差会影响该值。 fix 实际上很简单:根本不使用本地时间。如果将 localtime()
调用替换为 gmtime()
,您将获得预期的输出:
00:00:01
00:00:02
00:00:03
00:00:04
00:00:05
我意识到这个问题已经有了答案,但我想我可能会稍微转移一下注意力并扩展已接受的答案。由于 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);
}
我正在编写一个函数,除其他外,它必须打印出经过的时间计数器。它通过引用接收开始时间 _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。为什么会这样?我怎样才能让开始的时间像分钟一样归零?
time_t
通常(请参阅编辑)存储绝对时间戳(自 1970 年 1 月 1 日午夜 UTC 以来的秒数)。通过计算 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。
要方便地查找 2 time_t
之间经过的秒数,请使用 difftime()
因为 C 中未指定减去 2 time_t
值作为秒数差。
double difftime(time_t time1, time_t time0);
C11dr §7.26.2.2
Thedifftime
function returns the difference expressed in seconds as adouble
.
double elapsed_seconds = difftime(current, *_start);
printf("elapsed_seconds: %f\n", elapsed_seconds);
如果你想使用这个方法,你应该知道time()
returns 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 的八小时时差会影响该值。 fix 实际上很简单:根本不使用本地时间。如果将 localtime()
调用替换为 gmtime()
,您将获得预期的输出:
00:00:01
00:00:02
00:00:03
00:00:04
00:00:05
我意识到这个问题已经有了答案,但我想我可能会稍微转移一下注意力并扩展已接受的答案。由于 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);
}