Categorie
Uncategorized

Timestamp

Tra le note IBM sul formato *DTS (menzionate in un precedente post) troviamo:

When converting an input date from a *DTS timestamp format to an output date of any format without time zone conversion, the supported date range is from August 23, 1928, 12:03:06.314752 (.315 for milliseconds) to May 10, 2071, 11:56:53.685240 (.685 for milliseconds).

e poco dopo:

When converting a character date and time value to *DTS and back to character format using microseconds precision, there is a rounding error of minus 1 to minus 7 microseconds.
If you specify a precision of microseconds, it is recommended that you use a microsecond value that is evenly divisible by 8.

Si potrebbe ipotizzare che X'0000000000000001‘ valga 8 microsecondi per spiegare questo errore di arrotondamento. Ma facendo qualche conto si verifica che non può essere.

Sia x il valore utilizzato per rappresentare 8 microsecondi. Conseguentemente:

  • Il valore 125.000 * x rappresenterebbe un milione di microsecondi, ossia 1 secondo.
  • Il valore 450.000.000 * x rappresenterebbe un ora (3600 secondi).
  • Il valore 10.800.000.000 * x rappresenterebbe un giorno (24 ore).

Tra il 23 Agosto 1928 e il 10 Maggio 2071 intercorrono 52.126 giorni.

Volendo cavillare ed avere un valore esatto dell’intervallo temporale dobbiamo sottrarre la differenza tra gli orari:
12:03:06.314752 – 11:56:53.685240 = 00:06:12.629512

Da cui:

(52126 * 10.800.000.000 - (125.000 * 372 + 78689) ) * x =
(562.960.800.000.000 - 46.578.689) * x =
 562.960.753.421.311 * x

Ora:

2^64 / 562.960.753.421.311 = 32.767,371

poiché 32767 = 0x7FFF il valore più plausibile per x è X'0000000000008000'

Ogni 8 microsecondi avremmo un incremento di X'8000'.

Quindi il sistema di conversione date da (e per) il formato *DTS utilizzerebbe a rigore solo 6 * 8 + 1 = 49 bit dei 64 a disposizione per trattare i timestamp (prima della versione V4R3 del sistema operativo i bit utilizzati erano 41).

Tuttavia i valori destinati ai timestamp nel savefile sembrano utilizzare tutti gli otto byte a disposizione.

La cosa più ovvia è ipotizzare che con i progressi dell’hardware si sia giunti (a livello di LIC) a gestire una granularità maggiore. Un’altra ipotesi è che la materializzazione del clock, essendo una operazione software oltre che hardware, sia strutturata proprio per garantire che due chiamate successive non possano restituire uno stesso valore (gestendo una rotazione dei valori associati ai bit meno significativi ossia quelli non determinabili dal clock vero e proprio).


Comunque sia, se venissero gestiti completamente i microsecondi sfrutteremmo a pieno altri 3 bit: 52 bit dei 64 a disposizione

X'000000000001000' = 1 microsecondo.

Curiosando nella documentazione IBM troviamo la risposta. A livello di sistema operativo IBM i 7.4 i bit utilizzati sono proprio 52.

Troviamo anche una spiegazione circa i bit apparentemente inutilizzati:

The uniqueness bits field may contain any combination of binary 1s and 0s. These bits do not provide additional granularity for a time value; they merely allow unique 64-bit values to be returned, such as when the value of the time-of-day (TOD) clock is materialized. When the uniqueness bits all contain binary 0s, then the 64-bit value returned is not unique. Unless explicitly stated otherwise, MI instructions which materialize the TOD clock return a unique 64-bit value.

Aggiungendo altri 10 bit potremmo gestire 1024 valori diversi per ogni microsecondo: con 62 bit avremo allora superato la granularità necessaria per gestire effettivamente i nanosecondi.

Numericamente avremmo comunque un dubbio su come siano gestiti i bit meno significativi.

Con un poco di impegno possiamo scrivere una routine in C che decodifichi i timestamp estratti dai savefile una volta che gli stessi siano stati trasferiti su altra piattaforma.

Quello effettivamente mostrato nel DSPSAVF (tasto funzione F16) è presente nella parte fissa dell’associated space:

000000000 02 49 c5 d4 d7 e3 e8 40 40 40 40 40 40 40 40 40
000000010 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40
000000020 04 01 a6 d7 9a 5b 0d 5a e0 01 00 00 00 01 00 00
000000030 00 00 01 40 40 ** ** ** ** ** ** ** 00 00 5c e2 
000000040 e8 e2 e5 c1 d3 40 40 40 00 00 00 00 d5 00 01 00 000000050 5c e2 e8 e2 c2 c1 e2 40 40 40 00 5c d5 d6 d5 c5 000000060 40 40 40 40 40 ** ** ** ** ** ** ** ** 00 00 00

Una ultima curiosità. Tra il valore X'0000000000000001' e il valore X'FFFFFFFFFFFFFFFF' esiste il valore X'8000000000000000'. A che data corrisponde?

In altri termini: quale è la data intermedia tra il 23 Agosto 1928 e il 10 Maggio 2071 nel formato *DTS?

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *