
Я использую OpenWRT на Arduino YUN и пытаюсь получить точную дату в миллисекундах (ДД/ММ/ГГГГ ч:мин:сек:мс), получая время от сервера времени.
К сожалению, 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 был собран с помощью CONFIG_BUSYBOX_CONFIG_ADJTIMEX
set, то вы должны иметь возможность использовать его 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's — это прекрасное решение, если у вас есть настройка кросс-сборки OpenWRT (настоятельно рекомендуется!).coreutils-датарешение работает, потому что, хотя coreutils и поддерживает glibc, он не является исключительно glibc. Он поставляется со своей собственной автономной реализацией strftime
(выведенной из glibc) и использует ее для обертывания (через strftime_case()
) базового strftime
, чтобы поддерживать различные расширения (и в противном случае возвращается к версии uClibc).
Даже glibc (до текущей версии 2.23) не поддерживает %N
, coreutils, strftime()
полученные из канонической версии glibc, добавляют %N
и %:z
и несколько других изменений. Вариации и пропатченные версии strftime()
изобилуют (включая версии в bash и gawk).
решение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 с OpenWrt-SDK.