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

Python 3.x 3.2
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):

Python 3.x 3.2
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:

Python 3.x 3.2
Python 2.x 2.7
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.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow