Как конвертировать UTC в Julian Date в c # [дубликат]

Если у вас много полей в инструкции select, и вы хотите получить последнее значение для всех этих полей с помощью оптимизированного кода:

select * from
(select * from table_name
order by id,rev desc) temp
group by id 
26
задан cweston 9 March 2011 в 20:07
поделиться

5 ответов

OADate похож на Julian Dates, но использует другую отправную точку (30 декабря 1899 г. против 1 января 4713 г. до н.э.) и другую точку «нового дня». Джулиан Датс считает, что полдень станет началом нового дня, OADates используют современное определение, полночь.

Юлиан. Дата полуночи, 30 декабря 1899 года, 2415018.5. Этот метод должен дать вам правильные значения:

public static double ToJulianDate(this DateTime date)
{
    return date.ToOADate() + 2415018.5;
}

Что касается алгоритма:

  • if (Month < 3) ...: Чтобы магические числа работали правильно, они поставив февраль на «конец» года.
  • (153 * Month - 457) / 5: Вау, это некоторые серьезные магические числа. Обычно количество дней в каждом месяце составляет 31 28 31 30 31 30 31 31 30 31 30 31, но после этой корректировки в выражении if она становится равной 31 30 31 30 31 31 30 31 30 31 31 28. Или, вычтите 30, и вы получите 1 0 1 0 1 1 0 1 0 1 1 -2. Они создают этот шаблон 1s и 0s, делая это деление в целочисленном пространстве. Переписанная с плавающей запятой, это будет (int)(30.6 * Month - 91.4). 30.6 - среднее число дней в месяц, за исключением февраля (точнее, повторение 30.63). 91,4 - это почти количество дней в 3 средних не-февральских месяцах. (30,6 * 3 - 91,8). Итак, давайте удалим 30, и просто сосредоточимся на этом 0,6 дня. Если мы умножим его на количество месяцев, а затем обрезаем до целого числа, получим шаблон 0s и 1s. 0,6 * 0 = 0,0 -> 0,6 * 1 = 0,6 -> 0 (разность 0) 0,6 * 2 = 1,2 -> 1 (разность 1) 0,6 * 3 = 1,8 -> 1 (разность 0) 0,6 * 4 = 2,4 -> 2 (разность 1) 0,6 * 5 = 3,0 -> 3 (разность 1) 0,6 * 6 = 3,6 -> 3 (разность 0) 0,6 * 7 = 4,2 -> 4 (разность 1) 0,6 * 8 = 4.8 -> 4 (разность 0) См. Схему различий в праве? Это та же самая картина в списке выше, количество дней в каждом месяце минус 30. Вычитание 91.8 компенсирует количество дней в первые три месяца, которые были перенесены в «конец» года, и корректировка он на 0,4 перемещает последовательные разности 1 (0,6 * 4 и 0,6 * 5 в приведенной выше таблице), чтобы выровнять их со смежными месяцами, составляющими 31 день. С февраля наступает конец года, нам не нужно иметь дело с его длиной. Это может быть 45 дней (46 в високосный год), и единственное, что нужно было бы изменить, это постоянное количество дней в году, 365. Обратите внимание, что это зависит от порядка 30 и 31 месяца , Если бы у нас было два месяца подряд, которые составляли 30 дней, это было бы невозможно.
  • 365 * Year: Дни в год
  • (Year / 4) - (Year / 100) + (Year / 400): плюс один височный день каждые 4 года, минус один раз каждые 100, плюс один каждый 400.
  • + 1721119: Это юлианская дата 2 марта 1 года до н.э. Поскольку мы перенесли «начало» календаря с января по март, мы используем это как наше смещение, а не 1 января. Поскольку нет нулевого года, 1 BC получает целочисленное значение 0. Что касается того, почему 2 марта, а не 1 марта, я предполагаю, что это потому, что в этом месяце все еще было немного в конце. Если исходный писатель использовал - 462 вместо - 457 (- 92.4 вместо - 91.4 в математике с плавающей запятой), то смещение было бы до 1 марта.
79
ответ дан David Yaw 5 September 2018 в 11:42
поделиться

Хотя метод

public static double ToJulianDate(this DateTime date) { return date.ToOADate() + 2415018.5; }

работает на современные даты, он имеет значительные недостатки.

Юлианская дата определена для отрицательных дат - например, до нашей эры (до обычной эры) и является общей для астрономических расчетов. Вы не можете построить объект DateTime с годом, меньшим 0, и поэтому Julian Date не может быть вычислен для дат BCE с использованием вышеуказанного метода.

Реформа календарного рекорда григорианской эпохи 1582 года помещает 11-дневное отверстие в календаре между 4 и 15 октября. Эти даты не определены ни в юлианском календаре, ни в григорианском календаре, но DateTime принимает их как аргументы. Кроме того, использование вышеуказанного метода не возвращает правильное значение для любой юлианской даты. Эксперименты с использованием System.Globalization.JulianCalendar.ToDateTime () или передача эпохи JulianCalendar в конструкторе DateTime по-прежнему приводят к неправильным результатам для всех дат до 5 октября 1582.

Следующие подпрограммы, адаптированные из Jean Meeus «Астрономические алгоритмы» возвращает правильные результаты для всех дат, начинающихся с полудня 1 января -4712, нулевого времени в юлианском календаре. Они также выдают исключение ArgumentOutOfRangeException, если недействительная дата передается.

 public class JulianDate
{
    public static bool isJulianDate(int year, int month, int day)
    {
        // All dates prior to 1582 are in the Julian calendar
        if (year < 1582)
            return true;
        // All dates after 1582 are in the Gregorian calendar
        else if (year > 1582)
            return false;
        else
        {
            // If 1582, check before October 4 (Julian) or after October 15 (Gregorian)
            if (month < 10)
                return true;
            else if (month > 10)
                return false;
            else
            {
                if (day < 5)
                    return true;
                else if (day > 14)
                    return false;
                else
                    // Any date in the range 10/5/1582 to 10/14/1582 is invalid 
                    throw new ArgumentOutOfRangeException(
                        "This date is not valid as it does not exist in either the Julian or the Gregorian calendars.");
            }
        }
    }

    static private double DateToJD(int year, int month, int day, int hour, int minute, int second, int millisecond)
    {
        // Determine correct calendar based on date
        bool JulianCalendar = isJulianDate(year, month, day);

        int M = month > 2 ? month : month + 12;
        int Y = month > 2 ? year : year - 1;
        double D = day + hour/24.0 + minute/1440.0 + (second + millisecond / 1000.0)/86400.0;
        int B = JulianCalendar ? 0 : 2 - Y/100 + Y/100/4;

        return (int) (365.25*(Y + 4716)) + (int) (30.6001*(M + 1)) + D + B - 1524.5;
    }

    static public double JD(int year, int month, int day, int hour, int minute, int second, int millisecond)
    {
        return DateToJD(year, month, day, hour, minute, second, millisecond);
    }


    static public double JD(DateTime date) 
    {
        return DateToJD(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, date.Millisecond);
    }
}
7
ответ дан JBartlau 5 September 2018 в 11:42
поделиться

Объяснение Дэвида Яу объясняется, но расчет кумулятивного числа дней года за месяцы до данного месяца является антиинтуитивным. Если вы предпочитаете массив целых чисел, чтобы сделать алгоритм более понятным, тогда это будет делать:

    /*
     * convert magic numbers created by:
     *    (153*month - 457)/5) 
     * into an explicit array of integers
     */
    int[] CumulativeDays = new int[]
    {
        -92   // Month = 0  (Should not be accessed by algorithm)
      , -61   // Month = 1  (Should not be accessed by algorithm)
      , -31   // Month = 2  (Should not be accessed by algorithm)
      ,   0   // Month = 3  (March)
      ,  31   // Month = 4  (April)
      ,  61   // Month = 5  (May)
      ,  92   // Month = 6  (June)
      , 122   // Month = 7  (July)
      , 153   // Month = 8  (August)
      , 184   // Month = 9  (September)
      , 214   // Month = 10 (October)
      , 245   // Month = 11 (November)
      , 275   // Month = 12 (December)
      , 306   // Month = 13 (January, next year)
      , 337   // Month = 14 (February, next year)
    };

и первые три строки вычисления затем станут:

  int julianDay = day
                  + CumulativeDays[month]
                  + 365*year
                  + (year/4)

выражение

(153*month - 457)/5)

, хотя и производит точно такую ​​же последовательность, что и те же самые целые числа, что и приведенный выше массив для значений в диапазоне: от 3 до 14; включительно и делает это без каких-либо требований к хранению. Недостаток требований к хранению является только достоинством при расчете кумулятивного числа дней таким и запутанным способом.

4
ответ дан John Washburn 5 September 2018 в 11:42
поделиться

Если кому-то нужно конвертировать из даты Julian в DateTime, см. ниже:

public static DateTime FromJulianDate(double julianDate)
{
    return DateTime.FromOADate(julianDate - 2415018.5);
}
2
ответ дан Malick 5 September 2018 в 11:42
поделиться

Мой код для модифицированного Julian Date использует тот же алгоритм, но имеет другое магическое число в конце, так что итоговое значение соответствует Модифицированной Юлианской Дате, показанной в Wikipedia . Я использовал этот же алгоритм не менее 10 лет как ключ для ежедневных временных рядов (изначально на Java).

public static int IntegerDate(DateTime date)
    {
        int Month = date.Month;
        int Day = date.Day;
        int Year = date.Year;

        if (Month < 3)
        {
            Month = Month + 12;
            Year = Year - 1;
        }
        //modified Julian Date
        return Day + (153 * Month - 457) / 5 + 365 * Year + (Year / 4) - (Year / 100) + (Year / 400) - 678882;
    }

Обратный расчет имеет больше магических чисел для вашего развлечения:

public static DateTime FromDateInteger(int mjd)
    {
        long a = mjd + 2468570;
        long b = (long)((4 * a) / 146097);
        a = a - ((long)((146097 * b + 3) / 4));
        long c = (long)((4000 * (a + 1) / 1461001));
        a = a - (long)((1461 * c) / 4) + 31;
        long d = (long)((80 * a) / 2447);
        int Day = (int)(a - (long)((2447 * d) / 80));
        a = (long)(d / 11);
        int Month = (int)(d + 2 - 12 * a);
        int Year = (int)(100 * (b - 49) + c + a);
        return new DateTime(Year, Month, Day);
    }
0
ответ дан user3902302 5 September 2018 в 11:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: