Подтвердить что ты не робот

Извлечь день года и юлианский день из строковой даты

У меня есть строка "2012.11.07" в Python. Мне нужно преобразовать его в объект даты, а затем получить целочисленное значение дня года, а также юлианского дня. Является ли это возможным?

4b9b3361

Ответ 1

Сначала вы можете преобразовать его в объект datetime.datetime следующим образом:

>>> import datetime
>>> fmt = '%Y.%m.%d'
>>> s = '2012.11.07'
>>> dt = datetime.datetime.strptime(s, fmt)
>>> dt
datetime.datetime(2012, 11, 7, 0, 0)

Затем вы можете использовать методы на datetime, чтобы получить то, что вы хотите... кроме того, что datetime не имеет функции, которую вы хотите напрямую, поэтому вам нужно преобразовать в время tuple

>>> tt = dt.timetuple()
>>> tt.tm_yday
312

Термин "юлианский день" имеет несколько разных значений. Если вы ищете 2012312, вы должны сделать это косвенно, например, одно из следующих.

>>> int('%d%03d' % (tt.tm_year, tt.tm_yday))
2012312
>>> tt.tm_year * 1000 + tt.tm_yday
2012312

Если вы ищете другое значение, вы должны понять это. Например, если вы хотите, чтобы "дни с 1 января 4713 г. до н. Э." Означали, и у вас есть формула, которая требует григорианский год и год в году, вы должны включить эти два значения выше. (Если у вас есть формула, принимает григорианский год, месяц и день, вам даже не нужен шаг timetuple.) Если вы не можете решить, куда идти оттуда, запросите дополнительную информацию.

Если у вас нет формулы, и, возможно, даже если вы уже это сделаете, лучше всего посмотреть вокруг PyPI и ActiveState для уже существующих модулей. Например, быстрый поиск показал что-то, называемое jdcal. Я никогда не видел его раньше, но быструю pip install jdcal и краткую смету readme, и я смог это сделать:

>>> sum(jdcal.gcal2jd(dt.year, dt.month, dt.day))
2456238.5

Тот же результат, что и USN Julian date converter, дал мне.

Если вам нужен интегральный юлианский день, вместо дробной юлианской даты, вы должны решить, в каком направлении вы хотите округлить - к 0, к отрицательной бесконечности, округлить полдень до следующего дня, округлить полдень к четным дням и т.д. (Обратите внимание, что дата Джулиана определяется как начало с полудня 1 января 4713 г. н.э., поэтому половина 7 ноября 2012 г. равна 2456238, другая половина - 2456239, и только вы знаете, какой из них вы хотите...) Например, чтобы округлить до 0

>>> int(sum(jdcal.gcal2jd(dt.year, dt.month, dt.day)))
2456238

Ответ 2

Чтобы упростить начальные шаги ответа abarnert:

from dateutil import parser
s = '2012.11.07'
dt = parser.parse(s)

затем примените оставшийся ответ abanert.

Ответ 3

Эта функция (преобразование строк даты в юлианскую дату/время) также присутствует в модуле astropy. Подробнее см. их документацию. Астропическая реализация особенно удобна для простого перехода к юлианскому времени, а не только к юлианской дате.

Пример решения для исходного вопроса:

>>> import astropy.time
>>> import dateutil.parser

>>> dt = dateutil.parser.parse('2012.11.07')
>>> time = astropy.time.Time(dt)
>>> time.jd
2456238.5
>>> int(time.jd)
2456238

Ответ 4

Для быстрых вычислений вы можете найти день года и номер юлианского дня, используя только модуль stdlib datetime:

#!/usr/bin/env python3
from datetime import datetime, timedelta

DAY = timedelta(1)
JULIAN_EPOCH = datetime(2000, 1, 1, 12) # noon (the epoch name is unrelated)
J2000_JD = timedelta(2451545) # julian epoch in julian dates

dt = datetime.strptime("2012.11.07", "%Y.%m.%d") # get datetime object
day_of_year = (dt - datetime(dt.year, 1, 1)) // DAY + 1 # Jan the 1st is day 1
julian_day = (dt.replace(hour=12) - JULIAN_EPOCH + J2000_JD) // DAY
print(day_of_year, julian_day)
# 312 2456239

Другой способ получить day_of_year:

import time

day_of_year = time.strptime("2012.11.07", "%Y.%m.%d").tm_yday

julian_day в приведенном выше коде "юлианский день, связанный с солнечным днем ​​- число, назначенное на день в непрерывном количестве дни, начинающиеся с юлианского дня № 0, назначенного на день, начинающийся в Гринвич, означают полдень 1 января 4713 г. до н.э., юлианский пролепический календарь -4712" .

Документация модуля time использует термин "Джулианский день" по-разному:

Jn Юлианский день n (1 <= n <= 365). Ленточные дни не учитываются, поэтому в все годы 28 февраля - день 59, а 1 марта - день 60.
nнулевой юлианский день (0 <= n <= 365). Рассчитываются дни прыжка, и это можно сослаться на 29 февраля.

т.е. здесь находится юлианский день с нулевым значением day_of_year - 1. И первый (Jn) - day_of_year - (calendar.isleap(dt.year) and day_of_year > 60) - дни, начинающиеся с 1 марта, смещаются, чтобы исключить високосный день.

Существует также связанный термин: юлианская дата. Юлийский день - это целое число. Джулианская дата по своей сути является дробной: "Юлианская дата (JD) любого момента - это номер юлианского дня для предыдущего полудня плюс доля дня с этого момента."

В общем, чтобы избежать обработки крайних случаев самостоятельно, используйте библиотеку, чтобы вычислить юлианский день как предложенный @abarnert.

Ответ 5

Чтобы получить юлианский день, используйте метод datetime.date.toordinal и добавьте фиксированное смещение.

Юлианский день - это число дней с 1 января 4713 г. до н.э. в 12:00 в пролептическом юлианском календаре, или 24 ноября 4714 г. до н.э. в 12:00 в прорептический григорианский календарь. Обратите внимание, что каждый юлианский день начинается в полдень, а не в полночь.

Функция toordinal возвращает число дней с 31 декабря 1 года до н.э. в 00:00 в пролептическом григорианском календаре (другими словами, 1 января 1 года в 00:00 - начало 1-го дня, а не день 0). Обратите внимание, что 1 BC непосредственно предшествует 1 AD, не было года 0, так как число ноль не было изобретено до тех пор, пока много веков спустя.

import datetime

datetime.date(1,1,1).toordinal()
# 1

Просто добавьте 1721424.5 к результату toordinal, чтобы получить юлианский день.

Еще один ответ уже объяснил, как разобрать строку, с которой вы начали, и превратить ее в объект datetime.date. Таким образом, вы можете найти юлианский день следующим образом:

import datetime

my_date = datetime.date(2012,11,7)   # time = 00:00:00
my_date.toordinal() + 1721424.5
# 2456238.5

Ответ 6

Из приведенных выше примеров, вот один лайнер (не-Джулиан):

import datetime

doy = datetime.datetime.strptime('2014-01-01', '%Y-%m-%d').timetuple().tm_yday

Ответ 7

def JulianDate_to_date(y, jd):
    month = 1
    while jd - calendar.monthrange(y,month)[1] > 0 and month <= 12:
        jd = jd - calendar.monthrange(y,month)[1]
        month += 1
    date = datetime.date(y,month,jd).strftime("%m/%d/%Y")
    return date

Ответ 8

Согласно этой статье существует неопубликованная однострочная формула, созданная Флигелем и Ван Фландерном для вычисления григорианской даты по юлианской дате:

JD = 367 * year - 7 * (year + (month + 9)/12)/4 - 3 * ((year + (month - 9)/7)/100 + 1)/4 + 275 * month/9 + day + 1721029

Это было сжато П. М. Мюллером и Р. Н. Уимберли из Лаборатории реактивного движения, Пасадена, Калифорния, для дат после марта 1900 года, чтобы:

JD = 367 * year - 7 * (year + (month + 9)/12)/4 + 275 * month/9 + day + 1721014

Эти формулы отключены на 0,5, поэтому просто вычтите 0,5 из формул.

Используйте некоторую строковую манипуляцию для фактического извлечения данных, и вы будете в порядке

>>> year, month, day = map(int,"2018.11.02".split("."))
>>> 367 * year - 7 * (year + (month + 9)/12)/4 + 275 * month/9 + day + 1721014 - 0.5
2458424.5