Unix-Zeitstempel in eingebetteten Systemen, APIs und Datenbanken
Sensorzeitstempel mit RTC, NTP, monotonen Uhren, JSON und SQL entwerfen, einschließlich ESP32-Synchronisierungsbeispiel.
Ein belastbarer Sensordatensatz braucht Messwert, Zeitbezug und Unsicherheit. Unix-Zeit ermöglicht Interoperabilität, garantiert aber weder Genauigkeit noch Ereignisreihenfolge. Nutzen Sie Unix-Timestamp / Epoch-Konverter und die Grundlagen in Unix-Zeitstempel und Epoch-Zeit verstehen.
RTC und Systemuhr
Eine Hardware-RTC hält Kalender oder Zähler während CPU-Schlafphasen, oft mit einer Pufferbatterie. Sie ist nicht automatisch auf UTC eingestellt oder synchronisiert. Die Systemuhr ordnet einer Hardwarezeitbasis eine Epoche zu. Nach Versorgungsausfall muss die Gültigkeit der RTC geprüft werden; ihr Standarddatum ist keine Messung.
STM32, ESP32 und eingebettetes Linux
STM32-RTC, Sicherungsdomäne und Subsekundenfunktionen unterscheiden sich je Familie: Referenzhandbuch und ST AN4759 sind maßgeblich. Ein universelles Unix-Register existiert nicht. ESP-IDF kombiniert RTC- und hochauflösende Zeitgeber gemäß Konfiguration. Linux stellt CLOCK_REALTIME und monotone Uhren bereit. Prüfen Sie libc und ABI unabhängig von der CPU-Breite.
NTP und SNTP
NTP schätzt Zeitversatz und Netzlaufzeit; SNTP vereinfacht den Client. Asymmetrische Laufzeiten bleiben eine Fehlerquelle. NTP-Epoche und Ärenfelder entsprechen nicht Unix-Sekunden; die Protokollbibliothek übernimmt die Umrechnung. Speichern Sie Synchronisierungszustand, Alter und Unsicherheit. Ein Zeitsprung wirkt sofort, während eine schrittweise Korrektur vorübergehend die Taktrate ändert.
Echtzeituhr und monotone Uhr unterscheiden
Die zivile Systemzeit beantwortet die UTC-Datumsfrage und kann korrigiert werden. Ein monotoner Zähler misst Laufzeit seit einem beliebigen Ursprung und ist keine UTC-Angabe. Er kann beim Neustart zurückgesetzt werden; Schlafphasen werden je nach Uhr unterschiedlich behandelt. Verwenden Sie monotone Fristen für Zeitüberschreitungen und einen separaten UTC-Bezug für geräteübergreifende Vergleiche.
Sensorerfassung richtig zeitstempeln
Erfassen Sie die Zeit nahe am relevanten ADC-Abtastwert oder Interrupt. Sende- und Serverempfangszeiten enthalten Warteschlangen und Wiederholungen und gehören in eigene Felder. Für Messblöcke sind Blockursprung, Abtastperiode und Sequenznummer sinnvoll; berücksichtigen Sie Drift. Der Abtastleitfaden erläutert die Signalperspektive.
Ereignisprotokolle und Telemetrie
Gerätekennung, Startkennung und Sequenznummer verhindern, dass wiederholte UTC-Werte nach einer Rückwärtskorrektur Datensätze überschreiben. Unterscheiden Sie gemessene und rekonstruierte Zeiten. Eine reine UTC-Sortierung garantiert keine kausale Reihenfolge zwischen Geräten mit überlappenden Unsicherheiten.
Einheit und Fehlerbudget
| Zeitstempeleinheit | 1 s | 1700000000 s |
|---|---|---|
| Sekunden (s) | 1 | 1700000000 |
| Millisekunden (ms) | 1000 | 1700000000000 |
| Mikrosekunden (µs) | 1000000 | 1700000000000000 |
| Nanosekunden (ns) | 1000000000 | 1700000000000000000 |
Sekunden eignen sich für grobe Termine, Millisekunden häufig für Web-Telemetrie, Mikrosekunden für geeignete Erfassung und Nanosekunden für entsprechende Hardware. Auflösung, Wiederholbarkeit und Genauigkeit sind verschieden. Ein freier Fehler von 20 ppm summiert sich in nominalen 24 Stunden auf etwa 1,728 s. Temperatur und Alterung verändern diesen Wert.
REST und JSON
{
"timestamp_ns": "1700000000123456789",
"captured_at": "2023-11-14T22:13:20.123456789Z",
"time_quality": "synced",
"uncertainty_ms": 20,
"boot_id": "device-session-42",
"sequence": 17
}
Beschreiben Sie Epoche, Einheit, Vorzeichen und Bereich im Schema. Große Zeitwerte sollten für Binary64-Clients als Dezimalzeichenfolgen übertragen werden. BigInt lässt sich nicht direkt mit JSON.stringify serialisieren. timestamp_ns benennt die Einheit ausdrücklich. Unbekannte UTC-Zeit wird null mit Qualitätsangabe, keine scheinbar gültige Zeit um 1970.
ISO 8601 und RFC 3339
Verwenden Sie einen dokumentierten RFC-3339-Vertrag mit Z oder numerischem Offset und festgelegter Nachkommagenauigkeit. 2023-11-14T22:13:20Z und 2023-11-14T23:13:20+01:00 sind identisch. Eine bloße Ortszeit bestimmt kein UTC. Ein Offset enthält nicht die zukünftigen Regeln von Europe/Paris.
SQL-Datenbanken
CREATE TABLE sensor_measurement (
device_id text NOT NULL,
boot_id text NOT NULL,
sequence bigint NOT NULL,
captured_at timestamptz,
monotonic_us bigint NOT NULL,
time_quality text NOT NULL,
temperature_c double precision NOT NULL,
PRIMARY KEY (device_id, boot_id, sequence)
);
INSERT INTO sensor_measurement VALUES ('sensor-1', 'boot-42', 17,
TIMESTAMPTZ '2023-11-14T22:13:20.123456Z', 9812370, 'synced', 23.625);
Das Beispiel ist PostgreSQL-spezifisch. timestamptz speichert einen Zeitpunkt und stellt ihn in der Sitzungszone dar; die ursprüngliche IANA-Kennung bleibt nicht erhalten. Speichern Sie diese bei Bedarf separat. Die Zeitstempelauflösung beträgt Mikrosekunden; exakte Nanosekunden brauchen ein zusätzliches Ganzzahl- oder Dezimalfeld. Andere SQL-Systeme besitzen andere Bereiche und Regeln. Zeitindex und Datensatzidentität haben unterschiedliche Aufgaben.
UTC und örtliche Zeitpläne
Speichern Sie Ereigniszeitpunkte in UTC. Eine tägliche Regel um 08:00 in Paris benötigt hingegen Ortszeit und IANA-Zone. Definieren Sie das Verhalten bei übersprungenen oder wiederholten Zeiten. 86400 addierte Unix-Sekunden garantieren nicht dieselbe örtliche Uhrzeit am nächsten Kalendertag.
time_t und langlebige Produkte
Leiten Sie time_t nicht aus sizeof(void*) ab. Ein 32-Bit-Sekundenfeld erreicht 2038 auch in einem teilweise 64-bittigen System. ESP-IDF verwendet seit v5.0 vorzeichenbehaftetes 64-Bit-time_t; ältere Firmware und Übertragungsfelder können enger bleiben. Prüfen Sie printf-Formate, Datenbankspalten, Bootloader, RTC-Treiber und OTA-Migrationen.
ESP32-Beispiel mit NTP und Sensorwert
Der ESP-IDF-5.x/6.x-Code wird einmal nach initialisiertem esp-netif und bestehender WLAN- oder Ethernet-Verbindung aufgerufen. Der Kartentreiber übergibt log_sensor eine endliche Temperatur. Die erste Synchronisierung wartet höchstens 15 Sekunden; jede Erfassung erzeugt JSON.
#include <stdbool.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>
#include <sys/time.h>
#include "freertos/FreeRTOS.h"
#include "esp_netif_sntp.h"
#include "esp_timer.h"
#include "esp_random.h"
static bool clock_synced;
static int64_t last_sync_us;
static uint32_t boot_id;
static uint64_t sequence;
void ntp_after_network_ready(void) {
boot_id = esp_random();
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("pool.ntp.org");
esp_netif_sntp_init(&config);
clock_synced = esp_netif_sntp_sync_wait(pdMS_TO_TICKS(15000)) == ESP_OK;
if (clock_synced) last_sync_us = esp_timer_get_time();
}
void log_sensor(double temperature_c) {
int64_t monotonic_us = esp_timer_get_time();
struct timeval tv;
bool valid = clock_synced && monotonic_us - last_sync_us < INT64_C(3600000000)
&& gettimeofday(&tv, NULL) == 0;
printf("{\"boot_id\":\"%08" PRIx32 "\",\"sequence\":%" PRIu64
",\"monotonic_us\":\"%" PRId64 "\",\"timestamp_us\":",
boot_id, sequence++, monotonic_us);
if (valid) {
int64_t utc_us = (int64_t)tv.tv_sec * INT64_C(1000000) + tv.tv_usec;
printf("\"%" PRId64 "\"", utc_us);
} else printf("null");
printf(",\"time_quality\":\"%s\",\"temperature_c\":%.3f}\n",
valid ? "synced" : "unsynced", temperature_c);
}
timestamp_us und monotonic_us sind Dezimalzeichenfolgen. Bei fehlender Synchronisierung bleibt UTC null und die Reihenfolge verfügbar. Die einstündige Gültigkeitsgrenze ist eine Beispielrichtlinie, keine Genauigkeitsgarantie. Automatische spätere Synchronisierungen erneuern in diesem Beispiel nicht das Vertrauen: Produktionscode sollte last_sync_us über eine Benachrichtigung aktualisieren, gemeinsame Zustände schützen und Netzwerkfehler behandeln. Die zufällige 32-Bit-Startkennung ist illustrativ; kritische Identitäten brauchen einen persistenten Zähler oder eine ausreichend starke Kennung.
Neustart, Drift und Synchronisationsverlust
Ein Neustart eröffnet eine neue monotone Zeitlinie. Verbinden Sie diese nicht ungeprüft mit dem vorherigen Start. Erhöhen Sie bei Netzausfall die Unsicherheit anhand des Oszillatorbudgets und des letzten zuverlässigen Bezugs. Eine gepufferte RTC kann helfen, benötigt aber eine Qualitätskennzeichnung. Große Korrekturen sollten beobachtbar bleiben, ohne historische Daten still zu verändern.
Entwurfsregeln und Tests
- Epoche, Einheit und Vorzeichen an allen Grenzen ausdrücklich definieren.
- UTC für Ereignisse, monotone Uhren für Fristen verwenden.
- Sequenz, Startkennung und Synchronisationsqualität erhalten.
- Kaltstart ohne Netz, leere RTC-Batterie, Rückwärtskorrektur, Zeitumstellung und Zahlenbereichsgrenzen testen.
- Zeitzonendaten für zukünftige örtliche Termine aktuell halten.
Technische FAQ
Garantiert NTP Mikrosekundengenauigkeit?
Nein. Laufzeitasymmetrie, Betriebssystemplanung und Erfassungslatenz bleiben bestehen. Messen Sie den gesamten Signalweg.
Reicht ein monotoner Zähler für UTC?
Nein. Er braucht eine Zuordnung zu einer UTC-Referenz mit Driftmodell, Alter und Unsicherheit; ein Neustart begrenzt diese Zuordnung.
Soll die lokale Zeit gespeichert werden?
UTC für Ereignisse, eine zusätzliche Zone für zivile Regeln oder den ursprünglichen Kontext. Die Anzeige kann anschließend lokal erfolgen.
Werkzeuge und Primärquellen
Unix-Timestamp / Epoch-Konverter · Unix-Zeitstempel und Epoch-Zeit verstehen · Oszillatortoleranz.
- IETF · RFC 3339
- IETF · RFC 5905 (NTP)
- IETF · RFC 8259 (JSON)
- Python · PEP 418
- Espressif · ESP-IDF
- STMicroelectronics · AN4759
- PostgreSQL · SQL
Verwandte Werkzeuge und Leitfäden
Quarz-Lastkondensator-Rechner · Vollständigen Entwurfsleitfaden lesen