
Estoy usando OpenWRT en Arduino YUN y estoy tratando de obtener la fecha exacta en milisegundos (DD/MM/AAAA h:min:sec:ms) obteniendo la hora mediante un servidor de tiempo.
Desafortunadamente date +%N
solo regresa %N
, pero no los nanosegundos. He oído +%N
que no está incluido en la fecha de OpenWRT.
Entonces, ¿hay alguna forma de obtener la fecha (incluidos los milisegundos) como la quiero?
Respuesta1
En OpenWRT, date
es busybox
, que tiene limitaciones, pero esta no es estrictamente una de ellas. El problema subyacente es que la libc (uClibc)no es compatible con esta extensión GNU strftime. (Aunque tampoco lo hace glibc, hablaremos más sobre eso a continuación).
Deberías tenerlo lua
por defecto, pero esono ayudarásin algunos otros módulos no predeterminados.
hwclock
requiere gettimeofday()
comparar/configurar el RTC (reloj de hardware), pero no generará una resolución inferior a un segundo (el acceso a los RTC puede ser lo suficientemente lento como para que no sea útil de todos modos). Aparte de eso, OpenWRT solo proporciona el antiguo rdate
, que solo tiene una resolución de un segundo completo.
Parece que no hay una forma sencilla de obtener una marca de tiempo precisa directamente desde /proc
, la marca de tiempo más útil está en /proc/timer_list
(tercera línea), que es el tiempo de actividad en nanosegundos (la resolución dependerá de la plataforma).
Si su Busybox se creó con CONFIG_BUSYBOX_CONFIG_ADJTIMEX
set, entonces debería poder usarlo adjtimex
para leer el reloj del kernel (aunque tenga en cuenta que la versión de Busybox tieneambosArgumentos diferentes y resultados diferentes al adjtimex estándar.
Versión normal, adjtimex -p
última línea de salida:
raw time: 1416419719s 146628us = 1416419719.146628
Versión Busybox, adjtimex
(¡sin -p
!), últimas 3 líneas:
[...]
time.tv_sec: 1416420386
time.tv_usec: 732653
return value: 0 (clock synchronized)
Goldilocks es una buena solución, suponiendo que tenga su configuración de compilación cruzada OpenWRT (¡muy recomendable!). Sufecha-coreutilsLa solución funciona porque, si bien Coreutils reconoce glibc, no lo es exclusivamente. Viene con su propia implementación independiente de strftime
(derivada de glibc) y la usa para resumir (a través de strftime_case()
) el subyacente strftime
para admitir varias extensiones (y, de lo contrario, recurre a la versión uClibc).
Incluso glibc (hasta la versión 2.23 actual) no es compatible %N
, las coreutils strftime()
derivadas de la versión canónica de glibc agregan %N
y %:z
algunos otros cambios. Abundan las variaciones y versiones parcheadas strftime()
(incluidas las versiones en bash y gawk).
Respuesta2
Si tiene un compilador de C y no puede encontrar nada más, esto informará, por ejemplo
> 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;
}
Con gcc, simplemente compílelo gcc whatever.c -o millitime
. Si hay un error (lo cual sería muy extraño), informa a stderr y sale con un estado de 1. De lo contrario, informa a stdout y sale 0.
Los milisegundos sonredondeado hacia abajodesde microsegundos.
Respuesta3
En realidad también hay un paquete llamado coreutils-date
! ¡No lo sabía! ¡Allí se incluyen todas las funciones estándar!
Respuesta4
#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;
}
Esto en lenguaje C y funciona como coreutils-date date +%s%3N
. Está compilado en el enrutador OpenWrt con OpenWrt-SDK.