Имам низ "2012.11.07"
в python. Трябва да го преобразувам в обект за дата и след това да получа цяло число на ден от годината, а също и юлиански ден. Възможно ли е?
Извличане на ден от годината и юлиански ден от низова дата
Отговори (8)
Първо, можете да го конвертирате в обект 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
. Никога не го бях виждал преди, но едно бързо pip install jdcal
и кратък преглед на readme и успях да направя това:
>>> sum(jdcal.gcal2jd(dt.year, dt.month, dt.day))
2456238.5
Това е същият резултат, който USN преобразувателят на юлиански дати ми даде.
Ако искате интегрален юлиански ден, вместо дробна юлианска дата, трябва да решите в коя посока искате да закръглите – към 0, към отрицателна безкрайност, закръгляне на обяд до следващия ден, закръгляне на обяд към четни дни и т.н. (Имайте предвид, че Юлианската дата се определя като започваща от обяд на 1 януари 4713 г. пр.н.е., така че половината от 7 ноември 2012 г. е 2456238, другата половина е 2456239 и само вие знаете кое от тях искате...) Например, за да закръглите към 0:
>>> int(sum(jdcal.gcal2jd(dt.year, dt.month, dt.day)))
2456238
jdcal
връща дробни юлиански дни (приема се обяд, ако е дадена само дата). Ако искате да спорите, че тези дни не трябва да се наричат Юлиански дни, а нещо друго, обсъдете го с автора на модула.
- person abarnert; 15.09.2014
int
. Но целта не е да му дадете OP кода, който той може да използва без да мисли, или да препоръчате конкретна библиотека; Използвах gdcal
като пример за видовете библиотеки, които можете да намерите с бързо търсене в Google, PyPI или ActiveState; все още зависи от OP да направи това търсене, да оцени библиотеките и да избере тази, която иска.
- person abarnert; 15.09.2014
PyPI julian
, щракнете върху първия ред, прегледайте бегло неговия readme, pip install jdcal
, стартирайте един от примерите от readme, проверете дали изглежда разумно. Що се отнася до закръгляването... Добре, ще го включа и в отговора.
- person abarnert; 15.09.2014
За да получите юлианския ден, използвайте метода datetime.date.toordinal
и добавете фиксирано отместване.
Юлианският ден е броят на дните от 1 януари 4713 г. пр. н. е. в 12:00 часа в пролептичния юлиански календар или 24 ноември 4714 г. пр. н. е. в 12:00 часа в пролептичен григориански календар. Имайте предвид, че всеки юлиански ден започва на обяд, а не в полунощ.
Функцията toordinal
връща броя на дните от 31 декември 1 г. пр. н. е. в 00:00 ч. в пролептичния григориански календар (с други думи, 1 януари 1 г. сл. н. е. в 00:00 ч. е началото на ден 1, а не ден 0). Обърнете внимание, че 1 пр. н. е. директно предшества 1 сл. н. е., не е имало година 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
За да опростите началните стъпки на отговора на abarnert:
from dateutil import parser
s = '2012.11.07'
dt = parser.parse(s)
след това приложете останалата част от отговора на abanert.
Тази функционалност (преобразуване на низове от дата в юлианска дата/час) присъства и в модула 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
За бързи изчисления можете да намерите ден от годината и номер на юлианския ден, като използвате само 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
time
документацията на модула използва термина "Julian day" em> различно:
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.
Според тази статия има създадена непубликувана едноредова формула от Fliegel и Van Flandern за изчисляване на григорианска дата към юлианска дата:
JD = 367 * year - 7 * (year + (month + 9)/12)/4 - 3 * ((year + (month - 9)/7)/100 + 1)/4 + 275 * month/9 + day + 1721029
Това беше уплътнено от P. M. Muller и R. N. Wimberly от Jet Propulsion Laboratory, Пасадена, Калифорния за дати след март 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
От горните примери, ето един ред (не-юлиански):
import datetime
doy = datetime.datetime.strptime('2014-01-01', '%Y-%m-%d').timetuple().tm_yday
Импортирам datetime lib и използвам strftime за извличане на „julian day“, година, месец, ден...
import datetime as dt
my_date = dt.datetime.strptime('2012.11.07', '%Y.%m.%d')
jld_str = my_date.strftime('%j') # '312'
jld_int = int(jld_str) # 312