2009-05-07 20 views
7

Ho bisogno di serializzare un valore di DateTime .NET in un messaggio di buffer di protocollo.Buffer del protocollo: Devo usare int64 o fixed64 per rappresentare un valore di DateTime .NET?

Il mio piano è utilizzare DateTime.ToBinary() e quindi passare il valore restituito a 64 bit nel messaggio. Ma non sono sicuro di cosa scegliere come protocollo tipo di dati del buffer per rappresentarlo.

Immagino di essere confuso su quando devono essere utilizzati i tipi di dati fixed64 (o sfixed64).

Presumo che in questo scenario utilizzerei i tipi firmati poiché i valori restituiti da DateTime.ToBinary() possono essere negativi e positivi.

+0

Personalmente dubito della saggezza di ToBinary in primo luogo - vedi risposta per ulteriori informazioni. –

risposta

9

Bene, si desidera che sia int64 o sfixed64 per far fronte al valore firmato.

Avendo appena eseguito un test rapido, DateTime.Now.ToBinary() è codificato in 10 byte utilizzando int64 mentre sfixed64 utilizza sempre 8 byte. Fondamentalmente, la codifica a lunghezza variabile è ottima per i numeri piccoli, ma diventa più grande della codifica fissa per i grandi numeri. (È lo stesso tipo di compromesso rispetto all'uso di UTF-8 invece di UTF-16: i caratteri ASCII possono essere codificati in UTF-8 in un singolo byte, ma in seguito i punti di codice finiscono per essere codificati come 2 e quindi 3 byte, mentre UTF -16 utilizza sempre 2 byte per i caratteri del BMP.)

la mia ipotesi è che DateTime.ToBinary() valori sono probabile di essere abbastanza grande (senza conoscere i dettagli di esattamente ciò che fa), in modo sfixed64 è più appropriato.

Ha senso?

+1

Quindi in questo caso lo sfixed64 è più adatto perché utilizza codifica a lunghezza fissa rispetto a sint64 che è di lunghezza variabile e quindi adatto per valori più piccoli. Ho ragione? –

+1

Sì, è esattamente giusto. –

+1

'ToBinary()' di solito codifica come 10 byte perché i 2 bit superiori del valore 'int64' sono' Kind'. Ma il valore 'Ticks' _can_ prende 62 bit. Se non hai bisogno di granularità a 100 nanosecondi, allora 'now.Ticks/TimeSpan.TickPerSecond' (o qualunque granularità di cui hai bisogno) passa a proto come un' int64' sarebbe il byte più corto [], ma a meno che tu non faccia come @ MarcGravell suggerisce che entrambe le parti devono conoscere il divisore. –

0

È necessario utilizzare un numero a 64 bit con segno, non perché DateTime può essere negativo, ma poiché il metodo ToBinary restituisce un , che è un numero a 64 bit con segno.

+1

Grazie per la risposta Guffa, ma questo non risponde alla mia domanda. Mi interessa sapere se i tipi di dati "fixed64" debbano o meno essere utilizzati in questo caso. Con una spiegazione del perché, se possibile! –

4

In protobuf-net, io uso un approccio scala graduata (e in effetti, gestisce tutto questo per voi, se è sufficiente utilizzare DateTime) - il Proto equivalente è qualcosa di simile:

message DateTime { 
    optional sint64 value = 1; // the offset (in units of the selected scale) 
          // from 1970/01/01 
    optional TimeSpanScale scale = 2 [default = DAYS]; // the scale of the 
                // timespan 
    enum TimeSpanScale { 
    DAYS = 0; 
    HOURS = 1; 
    MINUTES = 2; 
    SECONDS = 3; 
    MILLISECONDS = 4; 

    MINMAX = 15; // dubious 
    } 
} 

cioè se il DateTime può essere espresso in giorni interi, inviamo solo il numero di giorni dal 1970, ecc. più un piccolo segno alla scala. Ciò significa che le date possono essere inviate un po 'più efficientemente, ma in realtà non costa molto di più per altre scale.

Personalmente, non vorrei usare ToBinary() - Vorrei usare esplicitamente un offset di una scala nota da un'epoca conosciuta (come l'epoca unix). Questo lo rende più portabile tra le piattaforme. Ma se si sta inviando (per esempio) solo l'offset millisecondo, allora una scala fissa di solito sarebbe più efficiente di una scala di lunghezza variante. Se hai bisogno di una firma o di una firma dipende dal fatto che tu abbia bisogno di date prima della tua epoca ;-p

+0

Marc, grazie per l'intuizione. In effetti, mi ero già spostato su un approccio molto simile al tuo (usando l'epoca di Linux), ma ero ancora curioso riguardo l'uso corretto dei tipi di buffer di protocollo fixed64/sfixed64. Immagino che tu possa dire che la mia domanda era un po 'accademica perché ero davvero interessato all'applicabilità dei vari tipi disponibili per codificare i dati con i Protocol Buffers. –