使用 struct timespec 检索 Linux 时间

问题描述 投票:0回答:3

有人可以建议我如何使用

检索 Linux 时间吗?

结构 timespec ts

输入?它只是给了我自大纪元以来的时间。我可以使用此数据类型获取实际的 Linux 时间吗?

简要背景:我正在嵌入式设备上编写一个记录器实用程序,其时间戳分辨率以毫秒/微秒为单位。源添加由目标组件使用的时间戳。

struct stLogItem logitem; //stLogItem has a member, struct timespec ts    
clock_gettime(clk_id, &logitem.ts);

目标组件正在文件/控制台上打印此日志时间戳。但打印出来的日期是自 Epoch 以来的时间,而不是实际的 Linux 日期。

打印的数据为: 1970-01-01 23:30:07.586864475

然而,Linux 日期有所不同,如下所示:

root@imh:# 日期

2017 年 11 月 14 日星期二 11:34:12 世界标准时间

这不是格式问题。它是关于获取当前的 Linux 时间(以纳秒为单位)。

c linux posix timespec
3个回答
7
投票

调用

clock_gettime
后,类型为
ts.tv_sec
time_t
会填充自纪元以来的时间戳(以秒为单位)。您可以直接将其传递给
localtime
:

struct timespec ts;    
clock_gettime(clk_id, &ts);
struct tm *my_tm = localtime(&ts.tv_sec);

现在

my_tm
指向
struct tm
,其中时间细分为年/月/日/时/分/秒,而
ts.tv_nsec
具有纳秒部分。


3
投票

什么阻止你做:

#include <time.h>
#include <stdio.h>
#include <string.h>

int main(void)
{
  struct timespec ts;    
  clock_gettime(CLOCK_REALTIME, &ts);

  char * p = ctime(&ts.tv_sec); /* Note that ctime() isn't thread-safe. */
  p[strcspn(p, "\r\n")] = 0;

  printf("Date: %s %ldns\n", p, ts.tv_nsec);

  ...
}

来自相关文档

所有实现都支持系统范围的实时时钟,即 由 CLOCK_REALTIME 标识。它的时间代表秒和 自纪元以来的纳秒。

POSIX 文档在这里。)


2
投票

看到@dbush的答案正是我需要看到的,以了解如何将Linux时间戳转换为可用的本地时间!

我更进一步,以更多方式打印时间戳输出,包括以人类可读的字符串形式显示日、月、年等,如下所示:

Fri Apr 15 14:05:12 2022 -0700

这是完整的源代码,来自我的

eRCaGuy_hello_world 存储库:

timing_clock_gettime_full_demo.c

// This define is required to bring in some of the extra POSIX features defined // in `<time.h>`. Depending on your compiler settings, it may be required to // get access to `clock_gettime()`. Using `-std=gnu17`, however, brings it in // automatically since the compiler then uses the "gnu c" language instead of // the standard "c" language. // // #define _POSIX_C_SOURCE 200112L // Linux includes // NA // C includes #include <errno.h> // `errno` #include <inttypes.h> // `PRIu64` #include <stdbool.h> // For `true` (`1`) and `false` (`0`) macros in C #include <stdint.h> // For `uint8_t`, `int8_t`, etc. #include <stdio.h> // For `printf()` #include <string.h> // `strerror(errno)` #include <time.h> // Includes `clock_gettime()` on Linux #define NS_PER_SEC (1000000000L) /// Convert seconds to nanoseconds #define SEC_TO_NS(sec) ((sec)*NS_PER_SEC) // int main(int argc, char *argv[]) // alternative prototype int main() { printf("Obtain an NTP-adjusted Real-time Clock timestamp on Linux.\n\n"); // Obtain a timestamp struct timespec ts; int retcode = clock_gettime(CLOCK_REALTIME, &ts); if (retcode == -1) { printf("Failed to get a timestamp. errno = %i: %s\n", errno, strerror(errno)); } // Print seconds.nanoseconds printf("timestamp = %li.%09li sec.\n\n", ts.tv_sec, ts.tv_nsec); // Convert it to just `uint64_t` nanoseconds // See: eRCaGuy_hello_world/c/timinglib.c uint64_t ns = SEC_TO_NS((uint64_t)ts.tv_sec) + (uint64_t)ts.tv_nsec; printf("timestamp = %" PRIu64 " nanoseconds.\n\n", ns); // Convert it to a local time stored in `struct tm`. Use the re-entrant // (thread-safe) version of the function, called `localtime_r()`. See: // 1. https://man7.org/linux/man-pages/man3/localtime.3p.html // 1. https://stackoverflow.com/a/47532938/4561887 // 1. `struct tm`: https://man7.org/linux/man-pages/man3/ctime.3.html struct tm localtime_struct; // Note: retptr means "return pointer" struct tm * retptr = localtime_r(&ts.tv_sec, &localtime_struct); if (retptr == NULL) { printf("Failed to convert to localtime. errno = %i: %s\n", errno, strerror(errno)); } printf("localtime_struct contains:\n" " ns = %li\n" // Nanoseconds (0-999999999); NOT FROM THIS STRUCT " sec = %i\n" // Seconds (0-60) " min = %i\n" // Minutes (0-59) " hour = %i\n" // Hours (0-23) " mday = %i\n" // Day of the month (1-31) " mon = %i\n" // Month (0-11) " year = %i\n" // Year - 1900 " wday = %i\n" // Day of the week (0-6, Sunday = 0) " yday = %i\n" // Day in the year (0-365, 1 Jan = 0) " isdst = %i\n" // Daylight saving time "\n", ts.tv_nsec, localtime_struct.tm_sec, localtime_struct.tm_min, localtime_struct.tm_hour, localtime_struct.tm_mday, localtime_struct.tm_mon, localtime_struct.tm_year, localtime_struct.tm_wday, localtime_struct.tm_yday, localtime_struct.tm_isdst); // Convert the `struct tm` localtime struct to a human-readable string in // normal human time units of Day, Month, Year, etc. // - This is the format string required to output timestamps in the exact // same format as `git` uses when you `git commit`. const char * time_format_str = "%a %b %-d %H:%M:%S %Y %z"; char time_str[100]; size_t bytes_written = strftime(time_str, sizeof(time_str), time_format_str, &localtime_struct); if (bytes_written == 0) { printf("Failed to convert `struct tm` to a human-readable " "time string.\n"); } printf("Formatted local time string = %s\n\n", time_str); return 0; }
示例构建和运行命令,以及输出:

eRCaGuy_hello_world/c$ gcc -Wall -Wextra -Werror -O3 -std=gnu17 timing_clock_gettime_full_demo.c -o bin/a && bin/a Obtain an NTP-adjusted Real-time Clock timestamp on Linux. timestamp = 1650056712.080211270 sec. timestamp = 1650056712080211270 nanoseconds. localtime_struct contains: ns = 80211270 sec = 12 min = 5 hour = 14 mday = 15 mon = 3 year = 122 wday = 5 yday = 104 isdst = 0 Formatted local time string = Fri Apr 15 14:05:12 2022 -0700
上面的代码是我在这里更彻底的答案的一部分:

如何在 Linux 上读取 NTP 调整的 RTC(实时时钟)时间戳

© www.soinside.com 2019 - 2024. All rights reserved.