
我在 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 退出。
毫秒是向下舍入從微秒開始。
答案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路由器。