Datums- und Uhrzeittyp zur Verwendung mit Protobuf

74

Ich denke darüber nach, Protokollpuffer für den Datenaustausch zwischen einem Linux- und einem Windows-basierten System zu verwenden.

Was ist das empfohlene Format zum Senden von Datums- / Uhrzeitwerten (Zeitstempel)? Das Feld sollte bei der Serialisierung klein sein.

Asgaut
quelle

Antworten:

47

Obwohl Sie nicht sagen, welche Sprachen Sie verwenden oder welche Genauigkeit Sie benötigen, würde ich vorschlagen, Unix-Zeit zu verwenden , die in a codiert ist int64. Es ist in den meisten Sprachen und Plattformen ziemlich einfach zu handhaben (siehe hier für ein Windows-Beispiel), und Protobufs verwendet eine Varint-Codierung , die die Größe klein hält, ohne den darstellbaren Bereich zu stark einzuschränken.

JesperE
quelle
17
verwendet nur 4 Bytes bis 2038 ... kann das nicht übertreffen
JoelFan
4
Die Unix-Zeit verbraucht nur 4 Bytes, was eine recht effiziente Codierung darstellt. Für Daten nach 2038 sind jedoch mehr als 4 Bytes erforderlich
JoelFan
3
Die Unix-Zeit wird nicht in Bezug auf die Anzahl der benötigten Bytes angegeben, sondern als die Anzahl der Sekunden seit der Epoche. Traditionell wurde es als 32-Bit-Ganzzahl dargestellt, aber die meisten Betriebssysteme verwenden heute 64-Bit-Ganzzahlen.
JesperE
10
Mein Punkt ist: Wenn Sie Unix Time in Protobuf verwenden, werden Sie nur 4 Bytes verwenden ... was bedeutet, dass Unix Time gut ist ... das ist alles, was ich sage!
Nebenbei füge
6
Ist es nicht 5? Varint-Codierung.
Hounshell
126

TimestampSeit protobuf 3.0 gibt es einen Nachrichtentyp. So erstellen Sie ihn im Modell:

syntax = "proto3";

import "google/protobuf/timestamp.proto";

message MyMessage {
    google.protobuf.Timestamp my_field = 1;
}

timestamp.proto Die Datei enthält Beispiele für die Verwendung von Timestamp, einschließlich Linux- und Windows-Programmen.

Beispiel 1: Zeitstempel von POSIX berechnen time().

Timestamp timestamp;
timestamp.set_seconds(time(NULL));
timestamp.set_nanos(0);

Beispiel 2: Zeitstempel von POSIX berechnen gettimeofday().

struct timeval tv;
gettimeofday(&tv, NULL);

Timestamp timestamp;
timestamp.set_seconds(tv.tv_sec);
timestamp.set_nanos(tv.tv_usec * 1000);

Beispiel 3: Zeitstempel aus Win32 berechnen GetSystemTimeAsFileTime().

FILETIME ft;
GetSystemTimeAsFileTime(&ft);
UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;

// A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
// is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
Timestamp timestamp;
timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
Evgeny Veretennikov
quelle
Was ist mit JavaScript?
Neurotransmitter
4
Ich bin mir nicht sicher, ob dies eine vollständige Antwort wert ist, aber die Frage fragt nach Zeitstempeln und Datumsangaben. Betrachten Sie also google.type.Date, wenn Sie keine höhere Genauigkeit benötigen.
Micseydel
1
@micseydel: OP hat nach einem "kleinen" Datentyp gefragt. google.type.Date ist 3 Zoll und hat eine geringere Genauigkeit als das einfache Senden eines int64 mit einem Unix-Zeitstempel. Es gibt nur sehr wenige Fälle, in denen google.type.Date wünschenswert ist, mit Ausnahme der einfachen menschlichen Lesbarkeit. Natürlich kombiniert das Binärformat von Protobuf die 3 Ints so gut es geht, aber im Allgemeinen scheint es nicht ideal zu sein, wenn es auf die Größe ankommt.
DoomGoober
8

In der neuesten Protobuf-Version (3.0) - Für C # ist Timestamp ein WellKnownType verfügbar. Überprüfen Sie dies

Hari Hara Chandan
quelle