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

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

Во-первых, вы можете преобразовать его в объект 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 не имеет функции, которую вы хотите напрямую, поэтому вам нужно преобразовать во временный кортеж

 >>> 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 что-то под названием jdcal . Я никогда раньше этого не видел, но быстро pip install jdcal и кратко pip install jdcal readme, и я смог это сделать:

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

Это тот же результат, который дал мне конвертер даты в USN Julian .

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

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

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

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

затем примените оставшуюся часть ответа abanert.

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

 #!/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 BC, юлианский пролепический календарь -4712 " .

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

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

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

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

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

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

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

toordinal функция возвращает количество дней с 31 декабря 1 года до н.э. в 00:00 в пролептическом григорианском календаре (другими словами, 1 января 1 года в 00:00 – начало первого дня, а не день 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 

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

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

 >>> 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 

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

 import datetime doy = datetime.datetime.strptime('2014-01-01', '%Y-%m-%d').timetuple().tm_yday 
 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