Дата по юлианскому календарю для DateTime, ВКЛЮЧАЯ ЧАСЫ И МИНУТЫ

Я пытаюсь преобразовать юлианскую дату, которая включает часы, минуты и секунды, в DateTime на С #.

Это номер: 2457285.7795969

Я могу вычислить DateTime без часов и минут с помощью этой функции.

public static DateTime FromJulian(long julianDate)
{
    long L = julianDate + 68569;
    long N = (long)((4 * L) / 146097);
    L = L - ((long)((146097 * N + 3) / 4));
    long I = (long)((4000 * (L + 1) / 1461001));
    L = L - (long)((1461 * I) / 4) + 31;
    long J = (long)((80 * L) / 2447);
    int Day = (int)(L - (long)((2447 * J) / 80));
    L = (long)(J / 11);
    int Month = (int)(J + 2 - 12 * L);
    int Year = (int)(100 * (N - 49) + I + L);

    return new DateTime(Year, Month, Day);
}

person Madthew    schedule 20.09.2015    source источник
comment
Поскольку вам нужно время до секунды, имейте в виду, что дополнительная секунда может сделать день длиной 86 001 секунду вместо обычных 86 000. Все согласны с тем, что целая часть JD должна зависеть только от даты UT (то есть даты по королевскому гринвичскому времени, если зимнее время сохранялось круглый год). Что делать с дробью в день с дополнительной секундой, не существует единого мнения. Одно из решений - разделить секунды с полуночи на 86 001. Какие самые ранние и самые поздние даты вам приходится иметь дело?   -  person Gerard Ashton    schedule 20.09.2015


Ответы (3)


Это то, что вы ищете: Преобразовать юлианскую дату со временем (ч / м / с) в дату и время в C #?
Применяя это ответьте, преобразование вашего значения 2457285,7795969 даст 19/9/2015 23:42:37.

person Ladi    schedule 20.09.2015
comment
Возможно, стоит скопировать код из этой ссылки, так как со временем он может исчезнуть. - person Rubens Farias; 20.09.2015
comment
Если ввести 2457285.7795969 в Многолетний компьютерный интерактивный альманах Военно-морской обсерватории США, получим 20 сентября 2015 г. 06: 42: 37.2 UT1 (что находится в пределах 0,9 секунды от UTC). Их веб-сайт (aa.usno.navy.mil/cgi -bin /) дает почти такие же результаты, но секунды равны 37,1. Если Ланди правильно реализовал код, с которым связался, это неправильно. - person Gerard Ashton; 20.09.2015
comment
Разница, вероятно, вызвана моим местным часовым поясом (Тихоокеанское время: UTC - 7). Я был неосторожен и не уточнил, что распечатал результат по местному времени - person Ladi; 20.09.2015
comment
Связанный ответ (вы должны скопировать его сюда, чтобы сделать свой пост самодостаточным) идет через время Unix (которое имеет происхождение 1 января 1970 г.) без уважительной причины. Время в .NET имеет происхождение 0001 1 января по пролептическому григорианскому календарю. Смотрите мой ответ. - person Jeppe Stig Nielsen; 20.09.2015
comment
У Stack Overflow есть другой ответ, который использует тот же внешний источник, что и ваш. - person Jeppe Stig Nielsen; 21.09.2015

Это должно быть так просто, как:

public static DateTime FromJulian(double julianDate)
{
  return new DateTime(
    (long)((julianDate - 1721425.5) * TimeSpan.TicksPerDay),
    DateTimeKind.Utc);
}

Как видите, 1721425.5 - это так называемая григорианская эпоха, то есть значение, которое юлианская дата имела в начале пролептического григорианского календаря, в 0001 1 января, 00:00: 00.0000000, откуда .NET DateTime имеет свое происхождение.

РЕДАКТИРОВАТЬ: если вы хотите, чтобы ваш метод генерировал исключение на «крайних» входах вместо того, чтобы возвращать недопустимое значение, сделайте следующее:

public static DateTime FromJulian(double julianDate)
{
  return new DateTime(
    checked((long)((julianDate - 1721425.5) * TimeSpan.TicksPerDay)),
    DateTimeKind.Utc);
}

Обратите внимание, что мы выполняем умножение с перегрузкой double operator *(double, double) (встроенной в C #). Это дает как можно меньше ошибок. Преобразование из double в long вызовет checked контекст, если double находится вне диапазона long. Если это преобразование прошло успешно, конструктор DateTime может выдать ошибку, если значение long выходит за пределы допустимого диапазона для .NET DateTime.


НОВОЕ РЕДАКТИРОВАНИЕ: вдохновленный другим потоком (Преобразование DateTime в юлианскую дату в C # (ToOADate Safe?)), вы также можете разработать очень простое решение с использованием DateTime.FromOADate. Тем не менее, см. Другую публикацию о переполнении стека, написанную мной, о недостатках точности метода FromOADate.

person Jeppe Stig Nielsen    schedule 20.09.2015

Прежде чем Лади ответил, что я искал ....

double L = DateTime.Now.ToOADate() + 2415018.5 + 68569;

double HMS = L-(int)L-0.5;  

int Hours = (int)(24*HMS);
HMS=HMS - (double)(Hours/24.0);
int Mins = (int)(24*60*HMS);
HMS=HMS - (double)(Mins/(24.0*60));

int Secs = (int)(24*60*60*HMS);

long N = (long)((4 * L) / 146097);
L = L - ((long)((146097 * N + 3) / 4));
long I = (long)((4000 * (L + 1) / 1461001));
L = L - (long)((1461 * I) / 4) + 31;
long J = (long)((80 * L) / 2447);
int Day = (int)(L - (long)((2447 * J) / 80));
L = (long)(J / 11);
int Month = (int)(J + 2 - 12 * L);
int Year = (int)(100 * (N - 49) + I + L);

DateTime test = new DateTime(Year, Month, Day);
Console.WriteLine("Hours-"+Hours);
Console.WriteLine("Mins-" + Mins);
Console.WriteLine("Secs-"+ Secs);

Console.WriteLine(test);
Console.WriteLine(DateTime.Now.ToString());
person Madthew    schedule 20.09.2015