Я думаю, это отличный вопрос.(Я только что обнаружил это.)
Если вы не работаете с датами, близкими к 1900 году, DateTime
будет иметь большую точность, чем дата OA.Но по какой-то непонятной причине авторы DateTime
структуры просто любят обрезать до ближайшей целой миллисекунды, когда они преобразуют между DateTime
и чем-то еще.Само собой разумеется, что выполнение этого отбрасывает большую точность без веской причины.
Вот обходной путь:
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;
}
Теперь давайте рассмотрим (из вашего вопроса) DateTime
задается:
var ourDT = new DateTime(634202170964319073);
// .ToSting("O") gives 2010-09-16T06:58:16.4319073
Точность любого DateTime
равна 0,1 мкс.
Вблизи даты и времени, которые мы рассматриваем, точность даты OA составляет:
Math.Pow(2.0, -37.0)
дней, или около 0.6286
мкс
Мы пришли к выводу, что в этом регионе a DateTime
является более точным, чем дата OA на(чуть более) в шесть раз.
Давайте преобразуем ourDT
в double
, используя мой метод расширения, описанный выше
double ourOADate = ourDT.ToOADatePrecise();
// .ToString("G") gives 40437.2904679619
// .ToString("R") gives 40437.290467961888
Теперь, если вы преобразуете ourOADate
обратно в DateTime
используя статический метод FromOADatePrecise
, описанный выше, вы получите
2010-09-16T06:58:16.4319072
(записано в формате "O"
)
По сравнению с оригиналом, мы видим, чтопотеря точности составляет в этом случае 0,1 мкс.Мы ожидаем, что потеря точности будет в пределах ± 0,4 мкс, поскольку этот интервал имеет длину 0,8 мкс, что сравнимо с упомянутыми ранее 0,6286 мкс.
Если мы пойдем другим путем, начнем с double
, представляющегоДата ОА не слишком близка к 1900 году, и сначала используют FromOADatePrecise
и затем ToOADatePrecise
, затем мы возвращаемся к double
, и поскольку точностьпромежуточное значение DateTime
превосходит значение даты OA, в этом случае мы ожидаем идеального двустороннего приема.Если, с другой стороны, вы используете методы BCL FromOADate
и ToOADate
в одном и том же порядке, крайне маловероятно получить хорошее двустороннее сообщение (если только double
, с которого мы начинали, не имеет совершенно особой формы).