我在 Arduino YUN 上使用 OpenWRT,并尝试通过时间服务器获取时间来获取以毫秒为单位的准确日期 (DD/MM/YYYY h:min:sec:ms)。
不幸的date +%N
是只返回%N
,而不是纳秒。我听说+%N
OpenWRT日期中没有包含。
那么有什么办法可以得到我想要的日期(包括毫秒)呢?
答案1
在 OpenWRT 上,date
是busybox
,它有局限性,但这并不是严格意义上的局限性之一。根本问题是 libc (uClibc)不支持此 GNU strftime 扩展。 (尽管 glibc 也没有,下面会详细介绍。)
默认情况下你应该有lua
,但是没有帮助没有一些其他非默认模块。
hwclock
要求gettimeofday()
比较/设置 RTC(硬件时钟),但它不会输出亚秒分辨率(访问 RTC 可能会很慢,以至于可能没有用处)。除此之外,OpenWRT 仅提供古老的rdate
,只有整秒的分辨率。
似乎没有直接的方法可以直接从 获取准确的时间戳/proc
,最有用的时间戳位于/proc/timer_list
(第 3 行),它是以纳秒为单位的正常运行时间(分辨率将取决于平台)。
如果你的 busybox 是用 set 构建的CONFIG_BUSYBOX_CONFIG_ADJTIMEX
,那么你应该能够使用它adjtimex
来读取内核时钟(尽管请注意,busybox 版本有两个都标准 adjtimex 的不同参数和不同输出。
普通版本,adjtimex -p
最后一行输出:
raw time: 1416419719s 146628us = 1416419719.146628
Busybox 版本,adjtimex
(没有-p
!),最后 3 行:
[...]
time.tv_sec: 1416420386
time.tv_usec: 732653
return value: 0 (clock synchronized)
Goldilocks 是一个很好的解决方案,假设您有 OpenWRT 交叉构建设置(强烈推荐!)。你的coreutils-日期解决方案之所以有效,是因为虽然 coreutils 能够识别 glibc,但它并不完全是 glibc。它带有自己的独立实现strftime
(源自 glibc),并使用它来包装(通过strftime_case()
)底层strftime
,以支持各种扩展(否则会回退到 uClibc 版本)。
即使 glibc(直到当前的 2.23)也不支持,源自规范 glibc 版本的%N
coreutils添加了和以及其他一些更改。其变体和修补版本比比皆是(包括 bash 和 gawk 中的版本)。strftime()
%N
%:z
strftime()
答案2
如果你有一个 C 编译器并且找不到其他任何东西,这将报告,例如
> millitime && sleep 1 && millitime
14/11/2014 9:39:49:364
14/11/2014 9:39:50:368
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
int main (void) {
struct timeval now;
struct tm *parsed;
if (gettimeofday(&now, NULL) == -1) {
fprintf (
stderr,
"gettimeofday() failed: %s\n",
strerror(errno)
);
return 1;
}
parsed = localtime((const time_t*)&now.tv_sec);
if (!parsed) {
fprintf (
stderr,
"localtime() failed: %s\n",
strerror(errno)
);
return 1;
}
printf (
"%d/%d/%d %d:%02d:%02d:%03d\n",
parsed->tm_mday,
parsed->tm_mon + 1,
parsed->tm_year + 1900,
parsed->tm_hour,
parsed->tm_min,
parsed->tm_sec,
now.tv_usec / 1000
);
return 0;
}
用gcc,编译就可以了gcc whatever.c -o millitime
。如果出现错误(这会很奇怪),它会向 stderr 报告并以状态 1 退出。否则,它会向 stdout 报告并退出 0。
毫秒是向下舍入从微秒开始。
答案3
其实还有一个包叫coreutils-date
!不知道!包含所有标准功能!
答案4
#include <stdio.h>
#include <time.h>
void main (void){
long ms;
time_t s;
struct timespec spec;
clock_gettime(CLOCK_REALTIME, &spec);
s = spec.tv_sec;
ms = (spec.tv_nsec / 1.0e6);
printf("%d%03d\n", s, ms);
return 0;
}
这在 C 语言中,工作方式类似于 coreutils-date date +%s%3N
。使用OpenWrt-SDK编译为OpenWrt路由器。