Extraiga el día del año y el día juliano a partir de una fecha de cadena en python
date datetime (8)
Tengo una cadena "2012.11.07" en python. Necesito convertirlo en objeto de fecha y luego obtener un valor entero de día del año y también día juliano . ¿Es posible?
De acuerdo con este artículo hay una fórmula inédita de una línea creada por Fliegel y Van Flandern para calcular una fecha gregoriana a una fecha juliana:
JD = 367 * year - 7 * (year + (month + 9)/12)/4 - 3 * ((year + (month - 9)/7)/100 + 1)/4 + 275 * month/9 + day + 1721029
Esto fue compactado por PM Muller y RN Wimberly del Jet Propulsion Laboratory, Pasadena, California para fechas posteriores a marzo de 1900 a:
JD = 367 * year - 7 * (year + (month + 9)/12)/4 + 275 * month/9 + day + 1721014
Estas fórmulas están desactivadas en 0.5, así que restar 0.5 de las fórmulas.
Usa alguna manupulación de cadenas para extraer realmente los datos y estarás bien
>>> 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
De los ejemplos anteriores, aquí está el trazador de líneas uno (no Julian):
import datetime
doy = datetime.datetime.strptime(''2014-01-01'', ''%Y-%m-%d'').timetuple().tm_yday
Esta funcionalidad (conversión de cadenas de fecha a fecha / hora juliana) también está presente en el módulo de astropy . Por favor, consulte su documentación para detalles completos. La implementación de Astropy es especialmente útil para facilitar las conversiones a la hora juliana, en lugar de solo la fecha juliana.
Ejemplo de solución para la pregunta original:
>>> 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
Para cálculos rápidos, puede encontrar el día del año y el número del día juliano usando solo el módulo 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
Otra forma de obtener day_of_year
:
import time
day_of_year = time.strptime("2012.11.07", "%Y.%m.%d").tm_yday
julian_day
en el código anterior es "el número del día juliano asociado con el día solar - el número asignado a un día en un recuento continuo de días que comienzan con el día juliano número 0 asignado al día que comienza en Greenwich mediodía el 1 de enero de 4713 BC, calendario proleptico juliano -4712 " .
La documentación del módulo de time
usa el término "día juliano" de manera diferente:
Jn
El día juliano n (1 <= n <= 365). Los días bisiestos no se cuentan, por lo que en todos los años el 28 de febrero es el día 59 y el 1 de marzo es el día 60.
n
El día juliano basado en cero (0 <= n <= 365). Los días bisiestos se cuentan, y es posible referirse al 29 de febrero.
es decir, el día juliano basado en cero es day_of_year - 1
aquí. Y el primero ( Jn
) es day_of_year - (calendar.isleap(dt.year) and day_of_year > 60)
- los días que comienzan con el 1 de marzo se cambian para excluir el día bisiesto.
También hay un término relacionado: fecha juliana . El número del día juliano es un número entero. La fecha juliana es intrínsecamente fraccional: "La fecha juliana (JD) de cualquier instante es el número del día juliano para el mediodía anterior más la fracción del día desde ese instante".
En general, para evitar el manejo de casos extremos, use una biblioteca para calcular el día juliano según lo sugerido por @abarnert .
Para obtener el día juliano, use el método datetime.date.toordinal
y agregue un desplazamiento fijo.
El día juliano es el número de días desde el 1 de enero de 4713 aC a las 12:00 en el calendario juliano proléptico, o el 24 de noviembre de 4714 aC a las 12:00 en el calendario gregoriano proléptico . Tenga en cuenta que cada día juliano comienza al mediodía, no a la medianoche.
La función toordinal
devuelve el número de días desde el 31 de diciembre de 1 aC a las 00:00 en el calendario gregoriano proléptico (en otras palabras, el 1 de enero de 1 AD a las 00:00 es el comienzo del día 1, no el día 0). Tenga en cuenta que 1 aC precede directamente al año 1 dC, no hubo año 0 ya que el número cero no se inventó hasta muchos siglos después.
import datetime
datetime.date(1,1,1).toordinal()
# 1
Simplemente agregue 1721424.5 al resultado de toordinal
para obtener el día juliano.
Otra respuesta ya explica cómo analizar la cadena con la que comenzó y convertirla en un objeto datetime.date
. Entonces puedes encontrar el día juliano de la siguiente manera:
import datetime
my_date = datetime.date(2012,11,7) # time = 00:00:00
my_date.toordinal() + 1721424.5
# 2456238.5
Para simplificar los pasos iniciales de la respuesta de abarnert:
from dateutil import parser
s = ''2012.11.07''
dt = parser.parse(s)
luego aplica el resto de la respuesta de abanert.
Primero, puede convertirlo en un objeto datetime.datetime
como este:
>>> import datetime
>>> fmt = ''%Y.%m.%d''
>>> s = ''2012.11.07''
>>> dt = datetime.datetime.strptime(s, fmt)
>>> dt
datetime.datetime(2012, 11, 7, 0, 0)
Luego puede usar los métodos en datetime
para obtener lo que desea ... excepto que datetime
no tiene la función que desea directamente, por lo que necesita convertir a una tupla de tiempo
>>> tt = dt.timetuple()
>>> tt.tm_yday
312
El término "día juliano" tiene algunos significados diferentes. Si está buscando 2012312
, tiene que hacerlo indirectamente, por ejemplo, uno de los siguientes.
>>> int(''%d%03d'' % (tt.tm_year, tt.tm_yday))
2012312
>>> tt.tm_year * 1000 + tt.tm_yday
2012312
Si buscas un significado diferente, deberías ser capaz de resolverlo desde aquí. Por ejemplo, si quiere el significado de "días desde el 1 de enero de 4713 aC", y tiene una fórmula que requiere el año y el año gregoriano, tiene que conectar los dos valores anteriores (si tiene una fórmula que toma el año, mes y día gregorianos, ni siquiera necesita el paso de timetuple
). Si no puede averiguar a dónde ir desde allí, solicite más detalles.
Si no tiene una fórmula, y tal vez incluso si ya lo hace, su mejor opción es probablemente buscar en PyPI y ActiveState los módulos preexistentes. Por ejemplo, una búsqueda rápida jdcal
algo llamado jdcal
. Nunca lo había visto antes, pero un pip install jdcal
rápido de pip install jdcal
y una breve pip install jdcal
léame, y pude hacer esto:
>>> sum(jdcal.gcal2jd(dt.year, dt.month, dt.day))
2456238.5
Ese es el mismo resultado que el convertidor de fecha USN Julian me dio.
Si desea el día juliano integral, en lugar de la fecha juliana fraccionaria, debe decidir qué dirección desea redondear: hacia 0, hacia el infinito negativo, redondeando el mediodía hasta el día siguiente, redondeando al mediodía hacia el día par, etc. (Tenga en cuenta La fecha juliana se define como comenzando desde el mediodía del 1 de enero de 4713BC, entonces la mitad del 7 de noviembre de 2012 es 2456238, la otra mitad es 2456239, y solo usted sabe cuál de ellas quiere ...) Por ejemplo, para redondear hacia 0:
>>> int(sum(jdcal.gcal2jd(dt.year, dt.month, dt.day)))
2456238
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