Расчет юлианской даты в Python

Я пытаюсь создать юлианскую дату на питоне и испытываю серьезные трудности. Нет ничего проще:

jul = juliandate(year,month,day,hour,minute,second)

где jul будет что-то вроде 2457152.0 (десятичная дробь меняется со временем)?

Я пробовал jdcal, но не могу понять, как добавить компонент времени (jdcal.gcal2jd () принимает только год, месяц и день).


person edub    schedule 30.06.2015    source источник
comment
Не могли бы вы предоставить код, чтобы увидеть, что происходит, или вы используете библиотеку для juliandate?   -  person lmiguelvargasf    schedule 30.06.2015
comment
Я пробовал jdcal, но не могу понять, как добавить временной аспект (он должен изменить десятичную дробь). Я также безуспешно пробовал JDateTime, astropy.time и datetime. Приведенная выше строка кода является лишь гипотетической - я пытаюсь понять, есть ли что-нибудь подобное.   -  person edub    schedule 30.06.2015
comment
Думаю, вы можете узнать, что хотите, по этой ссылке   -  person lmiguelvargasf    schedule 30.06.2015
comment
Если у вас время UNIX, JD будет просто: jd = unixTime / 86400 + 2440587.5   -  person AstroFloyd    schedule 14.07.2019


Ответы (6)


Вот и все - решение на чистом Python с библиотекой datetime и математики.

Это основано на найденном здесь астрономическом уравнении ВМФ и проверено их собственным калькулятором: http://aa.usno.navy.mil/faq/docs/JD_Formula.php

import datetime
import math

def get_julian_datetime(date):
    """
    Convert a datetime object into julian float.
    Args:
        date: datetime-object of date in question

    Returns: float - Julian calculated datetime.
    Raises: 
        TypeError : Incorrect parameter type
        ValueError: Date out of range of equation
    """

    # Ensure correct format
    if not isinstance(date, datetime.datetime):
        raise TypeError('Invalid type for parameter "date" - expecting datetime')
    elif date.year < 1801 or date.year > 2099:
        raise ValueError('Datetime must be between year 1801 and 2099')

    # Perform the calculation
    julian_datetime = 367 * date.year - int((7 * (date.year + int((date.month + 9) / 12.0))) / 4.0) + int(
        (275 * date.month) / 9.0) + date.day + 1721013.5 + (
                          date.hour + date.minute / 60.0 + date.second / math.pow(60,
                                                                                  2)) / 24.0 - 0.5 * math.copysign(
        1, 100 * date.year + date.month - 190002.5) + 0.5

    return julian_datetime

Пример использования:

# Set the same example as the Naval site.
example_datetime = datetime.datetime(1877, 8, 11, 7, 30, 0)
print get_julian_datetime(example_datetime)
person SmittySmee    schedule 20.09.2018
comment
Обратите внимание, что эта функция производит новый вывод только каждую секунду, а не на уровне миллисекунды или ниже. Если у кого-то есть функция этого, которая также обеспечивает разрешение в миллисекундах и ниже от объекта datetime, что может быть полезно для некоторых (включая меня). - person Nils; 27.05.2021

Не чистое решение Python, но вы можете использовать SQLite в базе данных памяти, которая имеет функцию julianday():

import sqlite3
con = sqlite3.connect(":memory:")
list(con.execute("select julianday('2017-01-01')"))[0][0]

который возвращает: 2457754.5

person Janos Hajagos    schedule 21.04.2017

Ответьте на один из Дня выдержки год и юлианский день из строковой даты в Python. Библиотеки не требуются. Второй ответ - это библиотека из https://pypi.python.org/pypi/jdcal.

person Robert Jacobs    schedule 30.06.2015
comment
Вы не можете добавить компонент времени в jdcal.gcal2jd, хотя - person edub; 30.06.2015

Простой скрипт подделки чисел через вики тоже не знает. Обратите внимание, что это было написано с использованием Python 3.6, поэтому я не уверен, что он будет работать на Python 2.7, но это тоже старый вопрос.

def julian_day(now):
    """
    1. Get current values for year, month, and day
    2. Same for time and make it a day fraction
    3. Calculate the julian day number via   https://en.wikipedia.org/wiki/Julian_day
    4. Add the day fraction to the julian day number

    """
    year = now.year
    month = now.month
    day = now.day
    day_fraction = now.hour + now.minute / 60.0 + now.second / 3600.0 / 24.0

    # The value 'march_on' will be 1 for January and February, and 0 for other months.
    march_on = math.floor((14 - month) / 12)
    year = year + 4800 - march_on
    # And 'month' will be 0 for March and 11 for February. 0 - 11 months
    month = month + 12 * march_on - 3

    y_quarter = math.floor(year / 4)
    jdn = day + math.floor((month * 153 + 2) / 5) + 365 * year + y_quarter

    julian = year < 1582 or year == (1582 and month < 10) or (month == 10 and day < 15)
    if julian:
        reform = 32083 # might need adjusting so needs a test
    else:
        reform = math.floor(year / 100) + math.floor(year / 400) + 32030.1875 # fudged this

    return jdn - reform + day_fraction

Обычно это было просто для того, чтобы попробовать на себе, так как самый распространенный алгоритм доставлял мне проблемы. Это работает, и если вы поищете его и напишете свой сценарий, используя его, поскольку он доступен на многих языках. Но у этого есть шаги в документации, чтобы попытаться сделать его простым. Важнейшее решение - как часто вы будете искать даты до григорианской реформы. Вот почему я еще не тестировал это, но продолжаю играть с этим, так как это требует большого массажа. :-D По крайней мере, я думаю, что это соответствует PEP8, даже если это не соответствует лучшим практикам. Идите и пилинт.

Вы можете просто использовать пакеты с исходным кодом, такие как PyEphem или что-то еще, но вы все равно хотели бы знать, что с ним происходит, чтобы вы могли писать свои собственные тесты. Я свяжу для вас этот PyEphem, но есть много готовых пакетов с расчетами по юлианскому дню.

Лучше всего, если вы много работаете с этими типами чисел, - получить список постоянных, таких как J2000.

datetime.datetime(2000, 1, 1, 12, 0, 0, tzinfo=datetime.timezone.utc)

datetime.datetime.toordinal() + 1721425 - 0.5 # not tested

# or even
datetime.datetime(1970, 1, 1, tzinfo=datetime.timezone.utc)

Разобраться в этом несложно, если вы познакомитесь с тем, что делает библиотека datetime. Ради интереса вы обратили внимание на логотип PyEphem? Я подозреваю, что это происходит от чего-то вроде этого

Один пост, который я видел, похоже, работает, но не имеет тестов: jiffyclub

Теперь это более распространенный способ вычисления двух значений с использованием объекта datetime.

def jdn(dto):
"""
Given datetime object returns Julian Day Number
"""
year = dto.year
month = dto.month
day = dto.day

not_march = month < 3
if not_march:
    year -= 1
    month += 12

fr_y = math.floor(year / 100)
reform = 2 - fr_y + math.floor(fr_y / 4)
jjs = day + (
    math.floor(365.25 * (year + 4716)) + math.floor(30.6001 * (month + 1)) + reform - 1524)
if jjs < ITALY:
    jjs -= reform

return jjs
# end jdn

def ajd(dto):
"""
Given datetime object returns Astronomical Julian Day.
Day is from midnight 00:00:00+00:00 with day fractional
value added.
"""
jdd = jdn(dto)
day_fraction = dto.hour / 24.0 + dto.minute / 1440.0 + dto.second / 86400.0
return jdd + day_fraction - 0.5
# end ajd

Возможно, это не лучшая практика в Python, но вы спросили, как это вычислить, а не просто получить или извлечь, хотя, если это то, что вы хотите, на эти вопросы в последнее время были даны ответы.

person Douglas G. Allen    schedule 20.01.2017

Самый простой: df ['Julian_Dates'] = df.index.to_julian_date (). вам нужно установить столбец даты и времени для индексации (используйте Pandas).

Есть способ использовать Astropy. Сначала измените свое время на список (t). Во-вторых, измените этот список на время астропии (Время). Наконец, вычислите свой JD или MJD (t.jd t.mjd).
https://docs.astropy.org/en/stable/time/

Для df: t = Time (DF.JulianDates, format = 'jd', scale = 'utc')

person Jose Robles    schedule 12.03.2020