Python Language
Fecha y hora
Buscar..
Observaciones
Python proporciona métodos integrados y bibliotecas externas para crear, modificar, analizar y manipular fechas y horas.
Análisis de una cadena en un objeto de fecha y hora compatible con la zona horaria
Python 3.2+ admite el formato %z
al analizar una cadena en un objeto de datetime
y datetime
.
+HHMM
UTC en la forma+HHMM
o-HHMM
(cadena vacía si el objeto es ingenuo).
import datetime
dt = datetime.datetime.strptime("2016-04-15T08:27:18-0500", "%Y-%m-%dT%H:%M:%S%z")
Para otras versiones de Python, puede usar una biblioteca externa como dateutil
, que hace que el análisis de una cadena con zona horaria en un objeto de datetime
y datetime
sea rápido.
import dateutil.parser
dt = dateutil.parser.parse("2016-04-15T08:27:18-0500")
La variable dt
ahora es un objeto de datetime
y datetime
con el siguiente valor:
datetime.datetime(2016, 4, 15, 8, 27, 18, tzinfo=tzoffset(None, -18000))
Aritmética de fecha simple
Las fechas no existen de forma aislada. Es común que necesite encontrar la cantidad de tiempo entre las fechas o determinar cuál será la fecha de mañana. Esto se puede lograr usando objetos timedelta
import datetime
today = datetime.date.today()
print('Today:', today)
yesterday = today - datetime.timedelta(days=1)
print('Yesterday:', yesterday)
tomorrow = today + datetime.timedelta(days=1)
print('Tomorrow:', tomorrow)
print('Time between tomorrow and yesterday:', tomorrow - yesterday)
Esto producirá resultados similares a:
Today: 2016-04-15
Yesterday: 2016-04-14
Tomorrow: 2016-04-16
Difference between tomorrow and yesterday: 2 days, 0:00:00
Uso básico de objetos datetime
El módulo datetime contiene tres tipos principales de objetos: fecha, hora y fecha y hora.
import datetime
# Date object
today = datetime.date.today()
new_year = datetime.date(2017, 01, 01) #datetime.date(2017, 1, 1)
# Time object
noon = datetime.time(12, 0, 0) #datetime.time(12, 0)
# Current datetime
now = datetime.datetime.now()
# Datetime object
millenium_turn = datetime.datetime(2000, 1, 1, 0, 0, 0) #datetime.datetime(2000, 1, 1, 0, 0)
Las operaciones aritméticas para estos objetos solo se admiten dentro del mismo tipo de datos y realizar una aritmética simple con instancias de diferentes tipos resultará en un error de tipo.
# subtraction of noon from today
noon-today
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for -: 'datetime.time' and 'datetime.date'
However, it is straightforward to convert between types.
# Do this instead
print('Time since the millenium at midnight: ',
datetime.datetime(today.year, today.month, today.day) - millenium_turn)
# Or this
print('Time since the millenium at noon: ',
datetime.datetime.combine(today, noon) - millenium_turn)
Iterar sobre fechas
A veces desea iterar en un rango de fechas desde una fecha de inicio hasta una fecha de finalización. Puedes hacerlo usando la biblioteca datetime
y el objeto timedelta
:
import datetime
# The size of each step in days
day_delta = datetime.timedelta(days=1)
start_date = datetime.date.today()
end_date = start_date + 7*day_delta
for i in range((end_date - start_date).days):
print(start_date + i*day_delta)
Lo que produce:
2016-07-21
2016-07-22
2016-07-23
2016-07-24
2016-07-25
2016-07-26
2016-07-27
Analizar una cadena con un nombre de zona horaria corto en un objeto de fecha y hora con fecha horaria
Al usar la biblioteca dateutil
como en el ejemplo anterior en el análisis de las marcas de tiempo dateutil
en la zona horaria , también es posible analizar las marcas de tiempo con un nombre de zona horaria "corto" especificado.
Para fechas formateadas con nombres de zonas horarias cortas o abreviaturas, que generalmente son ambiguas (p. Ej., CST, que podrían ser la Hora estándar central, la Hora estándar de China, la Hora estándar de Cuba, etc.) o puede encontrar más información aquí o no necesariamente están disponibles en una base de datos estándar , es necesario especificar una asignación entre la abreviatura de zona horaria y el objeto tzinfo
.
from dateutil import tz
from dateutil.parser import parse
ET = tz.gettz('US/Eastern')
CT = tz.gettz('US/Central')
MT = tz.gettz('US/Mountain')
PT = tz.gettz('US/Pacific')
us_tzinfos = {'CST': CT, 'CDT': CT,
'EST': ET, 'EDT': ET,
'MST': MT, 'MDT': MT,
'PST': PT, 'PDT': PT}
dt_est = parse('2014-01-02 04:00:00 EST', tzinfos=us_tzinfos)
dt_pst = parse('2016-03-11 16:00:00 PST', tzinfos=us_tzinfos)
Después de ejecutar esto:
dt_est
# datetime.datetime(2014, 1, 2, 4, 0, tzinfo=tzfile('/usr/share/zoneinfo/US/Eastern'))
dt_pst
# datetime.datetime(2016, 3, 11, 16, 0, tzinfo=tzfile('/usr/share/zoneinfo/US/Pacific'))
Vale la pena señalar que si utiliza una zona horaria de pytz
con este método, no se localizará correctamente:
from dateutil.parser import parse
import pytz
EST = pytz.timezone('America/New_York')
dt = parse('2014-02-03 09:17:00 EST', tzinfos={'EST': EST})
Esto simplemente adjunta la zona horaria de pytz
a la fecha y hora:
dt.tzinfo # Will be in Local Mean Time!
# <DstTzInfo 'America/New_York' LMT-1 day, 19:04:00 STD>
Si utiliza este método, probablemente debería volver a localize
la parte ingenua de la fecha y hora después del análisis:
dt_fixed = dt.tzinfo.localize(dt.replace(tzinfo=None))
dt_fixed.tzinfo # Now it's EST.
# <DstTzInfo 'America/New_York' EST-1 day, 19:00:00 STD>)
Construyendo tiempos de datos conscientes de la zona horaria
Por defecto, todos los objetos de datetime
y datetime
son ingenuos. Para que sean conscientes de la zona horaria, debe adjuntar un objeto tzinfo
, que proporciona el desplazamiento UTC y la abreviatura de la zona horaria en función de la fecha y la hora.
Zonas horarias de compensación
Para las zonas horarias que son un desplazamiento fijo de UTC, en Python 3.2+, el módulo datetime
proporciona la clase de timezone
, una implementación concreta de tzinfo
, que toma un timedelta
y un parámetro de nombre (opcional):
from datetime import datetime, timedelta, timezone
JST = timezone(timedelta(hours=+9))
dt = datetime(2015, 1, 1, 12, 0, 0, tzinfo=JST)
print(dt)
# 2015-01-01 12:00:00+09:00
print(dt.tzname())
# UTC+09:00
dt = datetime(2015, 1, 1, 12, 0, 0, tzinfo=timezone(timedelta(hours=9), 'JST'))
print(dt.tzname)
# 'JST'
Para versiones de Python anteriores a 3.2, es necesario usar una biblioteca de terceros, como dateutil
. dateutil
proporciona una clase equivalente, tzoffset
, que (a partir de la versión 2.5.3) toma argumentos de la forma dateutil.tz.tzoffset(tzname, offset)
, donde el offset
se especifica en segundos:
from datetime import datetime, timedelta
from dateutil import tz
JST = tz.tzoffset('JST', 9 * 3600) # 3600 seconds per hour
dt = datetime(2015, 1, 1, 12, 0, tzinfo=JST)
print(dt)
# 2015-01-01 12:00:00+09:00
print(dt.tzname)
# 'JST'
Zonas con horario de verano.
Para las zonas con horario de verano, las bibliotecas estándar de Python no proporcionan una clase estándar, por lo que es necesario utilizar una biblioteca de terceros. pytz
y dateutil
son bibliotecas populares que proporcionan clases de zona horaria.
Además de las zonas horarias estáticas, dateutil
proporciona clases de zonas dateutil
que utilizan el horario de verano (consulte la documentación del módulo tz
). Puede usar el método tz.gettz()
para obtener un objeto de zona horaria, que luego se puede pasar directamente al constructor de datetime
:
from datetime import datetime
from dateutil import tz
local = tz.gettz() # Local time
PT = tz.gettz('US/Pacific') # Pacific time
dt_l = datetime(2015, 1, 1, 12, tzinfo=local) # I am in EST
dt_pst = datetime(2015, 1, 1, 12, tzinfo=PT)
dt_pdt = datetime(2015, 7, 1, 12, tzinfo=PT) # DST is handled automatically
print(dt_l)
# 2015-01-01 12:00:00-05:00
print(dt_pst)
# 2015-01-01 12:00:00-08:00
print(dt_pdt)
# 2015-07-01 12:00:00-07:00
PRECAUCIÓN : A partir de la versión 2.5.3, dateutil
no maneja dateutil
ambiguos correctamente, y siempre se establecerá de forma predeterminada en la fecha posterior . No hay forma de construir un objeto con una dateutil
represente la zona horaria, por ejemplo, 2015-11-01 1:30 EDT-4
, ya que esto es durante una transición de horario de verano.
Todos los casos de borde se manejan correctamente cuando se usa pytz
, pero las zonas horarias de pytz
no se deben pytz
directamente a las zonas horarias a través del constructor. En su lugar, se debe adjuntar una zona horaria de pytz
usando el método de localize
la zona horaria:
from datetime import datetime, timedelta
import pytz
PT = pytz.timezone('US/Pacific')
dt_pst = PT.localize(datetime(2015, 1, 1, 12))
dt_pdt = PT.localize(datetime(2015, 11, 1, 0, 30))
print(dt_pst)
# 2015-01-01 12:00:00-08:00
print(dt_pdt)
# 2015-11-01 00:30:00-07:00
Tenga en cuenta que si realiza aritmética de fecha y hora en una pytz
horaria de pytz
-aware, debe realizar los cálculos en UTC (si desea un tiempo transcurrido absoluto), o debe llamar a normalize()
en el resultado:
dt_new = dt_pdt + timedelta(hours=3) # This should be 2:30 AM PST
print(dt_new)
# 2015-11-01 03:30:00-07:00
dt_corrected = PT.normalize(dt_new)
print(dt_corrected)
# 2015-11-01 02:30:00-08:00
Análisis de fecha y hora difuso (extracción de fecha y hora de un texto)
Es posible extraer una fecha de un texto usando el analizador de dateutil
en un modo "borroso", donde los componentes de la cadena que no se reconocen como parte de una fecha se ignoran.
from dateutil.parser import parse
dt = parse("Today is January 1, 2047 at 8:21:00AM", fuzzy=True)
print(dt)
dt
ahora es un objeto datetime
y vería datetime.datetime(2047, 1, 1, 8, 21)
impreso.
Cambio entre zonas horarias
Para cambiar entre zonas horarias, necesita objetos de fecha y hora que tengan en cuenta la zona horaria.
from datetime import datetime
from dateutil import tz
utc = tz.tzutc()
local = tz.tzlocal()
utc_now = datetime.utcnow()
utc_now # Not timezone-aware.
utc_now = utc_now.replace(tzinfo=utc)
utc_now # Timezone-aware.
local_now = utc_now.astimezone(local)
local_now # Converted to local time.
Análisis de una marca de tiempo ISO 8601 arbitraria con bibliotecas mínimas
Python solo tiene soporte limitado para analizar las marcas de tiempo ISO 8601. Para strptime
necesita saber exactamente en qué formato se encuentra. Como complicación, la clasificación de una datetime
y datetime
es una marca de tiempo ISO 8601, con espacio como separador y fracción de 6 dígitos:
str(datetime.datetime(2016, 7, 22, 9, 25, 59, 555555))
# '2016-07-22 09:25:59.555555'
pero si la fracción es 0, no se genera ninguna parte fraccionaria
str(datetime.datetime(2016, 7, 22, 9, 25, 59, 0))
# '2016-07-22 09:25:59'
Pero estas 2 formas necesitan un formato diferente para strptime
. Además, strptime' does not support at all parsing minute timezones that have a
: in it, thus
can be parsed, but the standard format
2016-07-22 09: 25: 59 + 0300 can be parsed, but the standard format
2016-07-22 09:25:59 +03: 00` no puedo.
Hay una biblioteca de un solo archivo llamada iso8601
que analiza correctamente las marcas de tiempo ISO 8601 y solo ellas.
Admite fracciones y zonas horarias, y el separador en T
todo con una sola función:
import iso8601
iso8601.parse_date('2016-07-22 09:25:59')
# datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=<iso8601.Utc>)
iso8601.parse_date('2016-07-22 09:25:59+03:00')
# datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=<FixedOffset '+03:00' ...>)
iso8601.parse_date('2016-07-22 09:25:59Z')
# datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=<iso8601.Utc>)
iso8601.parse_date('2016-07-22T09:25:59.000111+03:00')
# datetime.datetime(2016, 7, 22, 9, 25, 59, 111, tzinfo=<FixedOffset '+03:00' ...>)
Si no se establece una zona horaria, iso8601.parse_date
se establece de iso8601.parse_date
predeterminada en UTC. La zona predeterminada se puede cambiar con el argumento de palabra clave default_zone
. En particular, si esto es None
lugar del predeterminado, entonces las marcas de tiempo que no tienen una zona horaria explícita se devuelven como tiempos de referencia ingenuos:
iso8601.parse_date('2016-07-22T09:25:59', default_timezone=None)
# datetime.datetime(2016, 7, 22, 9, 25, 59)
iso8601.parse_date('2016-07-22T09:25:59Z', default_timezone=None)
# datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=<iso8601.Utc>)
Convertir la marca de tiempo a datetime
El módulo datetime
puede convertir una timestamp
de timestamp
POSIX en un objeto datetime
ITC.
La época es el 1 de enero de 1970 a medianoche.
import time
from datetime import datetime
seconds_since_epoch=time.time() #1469182681.709
utc_date=datetime.utcfromtimestamp(seconds_since_epoch) #datetime.datetime(2016, 7, 22, 10, 18, 1, 709000)
Restar meses de una fecha con precisión
Usando el módulo de calendar
import calendar
from datetime import date
def monthdelta(date, delta):
m, y = (date.month+delta) % 12, date.year + ((date.month)+delta-1) // 12
if not m: m = 12
d = min(date.day, calendar.monthrange(y, m)[1])
return date.replace(day=d,month=m, year=y)
next_month = monthdelta(date.today(), 1) #datetime.date(2016, 10, 23)
Usando el módulo dateutils
import datetime
import dateutil.relativedelta
d = datetime.datetime.strptime("2013-03-31", "%Y-%m-%d")
d2 = d - dateutil.relativedelta.relativedelta(months=1) #datetime.datetime(2013, 2, 28, 0, 0)
Calcular las diferencias de tiempo
timedelta
módulo timedelta
es útil para calcular las diferencias entre los tiempos:
from datetime import datetime, timedelta
now = datetime.now()
then = datetime(2016, 5, 23) # datetime.datetime(2016, 05, 23, 0, 0, 0)
Especificar el tiempo es opcional al crear un nuevo objeto de datetime
delta = now-then
delta
es de tipo timedelta
print(delta.days)
# 60
print(delta.seconds)
# 40826
Para obtener n día después y n día antes de la fecha podríamos usar:
día después de la fecha:
def get_n_days_after_date(date_format="%d %B %Y", add_days=120):
date_n_days_after = datetime.datetime.now() + timedelta(days=add_days)
return date_n_days_after.strftime(date_format)
n día anterior a la fecha:
def get_n_days_before_date(self, date_format="%d %B %Y", days_before=120):
date_n_days_ago = datetime.datetime.now() - timedelta(days=days_before)
return date_n_days_ago.strftime(date_format)
Obtener una marca de tiempo ISO 8601
Sin zona horaria, con microsegundos.
from datetime import datetime
datetime.now().isoformat()
# Out: '2016-07-31T23:08:20.886783'
Con zona horaria, con microsegundos.
from datetime import datetime
from dateutil.tz import tzlocal
datetime.now(tzlocal()).isoformat()
# Out: '2016-07-31T23:09:43.535074-07:00'
Con zona horaria, sin microsegundos.
from datetime import datetime
from dateutil.tz import tzlocal
datetime.now(tzlocal()).replace(microsecond=0).isoformat()
# Out: '2016-07-31T23:10:30-07:00'
Consulte ISO 8601 para obtener más información sobre el formato ISO 8601.