Penso che questa sia una domanda eccellente. (Ho appena scoperto.)
A meno che non si opera con date molto vicine l'anno 1900, un DateTime
avrà un più alto precisione rispetto una data di OA. Ma per qualche motivo oscuro, gli autori della struttura DateTime
solo amano per troncare al più vicino intero millisecondo quando convertono tra DateTime
e qualcos'altro. Inutile dire che facendo questo si butta via molta precisione senza una buona ragione.
Ecco un work-around:
static readonly DateTime oaEpoch = new DateTime(1899, 12, 30);
public static DateTime FromOADatePrecise(double d)
{
if (!(d >= 0))
throw new ArgumentOutOfRangeException(); // NaN or negative d not supported
return oaEpoch + TimeSpan.FromTicks(Convert.ToInt64(d * TimeSpan.TicksPerDay)):
}
public static double ToOADatePrecise(this DateTime dt)
{
if (dt < oaEpoch)
throw new ArgumentOutOfRangeException();
return Convert.ToDouble((dt - oaEpoch).Ticks)/TimeSpan.TicksPerDay;
}
Ora, prendiamo in considerazione (dalla tua domanda) il DateTime
data da:
var ourDT = new DateTime(634202170964319073);
// .ToSting("O") gives 2010-09-16T06:58:16.4319073
La precisione di qualsiasi DateTime
è di 0,1 ms.
Vicino la data e l'ora stiamo considerando, la precisione di una data di OA è:
Math.Pow(2.0, -37.0)
giorni, o circa 0.6286
, microsiemens
Concludiamo che in questa regione un DateTime
è più preciso di una data OA di (poco più di) un fattore sei.
Diamo convertire ourDT
-double
usando il mio metodo di estensione sopra
double ourOADate = ourDT.ToOADatePrecise();
// .ToString("G") gives 40437.2904679619
// .ToString("R") gives 40437.290467961888
Ora, se si converte ourOADate
di nuovo ad un DateTime
utilizzando il metodo statico FromOADatePrecise
sopra, si ottiene
2010-09-16T06:58:16.4319072
(scritto con Formato "O"
)
Confrontando con l'originale, vediamo che la perdita di precisione è in questo caso 0,1 μs. Ci aspettiamo che la perdita di precisione sia compresa tra ± 0,4 μs poiché questo intervallo ha una lunghezza di 0,8 μs che è paragonabile a 0,6286 μs menzionati in precedenza.
Se andiamo nella direzione opposta, a partire da un double
che rappresenta una data di OA non troppo vicino al 1900, e prima uso FromOADatePrecise
, e poiToOADatePrecise
, poi torniamo a un double
, e perché la precisione dell'intermedio DateTime
è superiore a quella di una data OA, ci aspettiamo un round trip perfetto in questo caso. Se, d'altra parte, utilizzi i metodi BCL FromOADate
e ToOADate
nello stesso ordine, è estremamente improbabile ottenere un buon viaggio di andata e ritorno (a meno che lo double
con cui abbiamo iniziato abbia un modulo molto speciale).
Non esattamente le specifiche, ma vale la pena leggere: http://blogs.msdn.com/b/ericlippert/archive/2003/09/16/eric-s-complete-guide-to-vt-date.aspx –
Grazie, sembra esserci molta storia dietro questo formato data ... –