sistema - ¿Hay alguna forma de usar una función similar a strftime para las fechas anteriores a 1900 en Python?
obtener el dia de la semana en python (5)
No me di cuenta de esto, pero al parecer la función strftime
de Python no admite fechas anteriores a 1900:
>>> from datetime import datetime
>>> d = datetime(1899, 1, 1)
>>> d.strftime(''%Y-%m-%d'')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: year=1899 is before 1900; the datetime strftime() methods require year >= 1900
Estoy seguro de que podría hacer algo por mí mismo para hacer esto, pero creo que la función strftime
está ahí por una razón (y también hay una razón por la que no puede admitir fechas anteriores a 1900). Necesito poder admitir fechas antes de 1900. Yo solo uso str
, pero hay mucha variación. En otras palabras, puede o no tener microsegundos o puede tener o no una zona horaria. Hay alguna solución para esto?
Si hace una diferencia, lo hago para poder escribir los datos en un archivo de texto y cargarlos en una base de datos utilizando Oracle SQL * Loader.
Básicamente terminé haciendo la respuesta de Alex Martelli. Aquí hay una implementación más completa:
>>> from datetime import datetime
>>> d = datetime.now()
>>> d = d.replace(microsecond=0, tzinfo=None)
>>> str(d)
''2009-10-29 11:27:27''
La única diferencia es que str(d)
es equivalente a d.isoformat('' '')
.
Esta es la "característica" de la biblioteca ctime (UTF). También puede tener problemas por encima de 2038.
Esto es de la fuente matplotlib . Podría proporcionar un buen punto de partida para rodar el tuyo.
def strftime(self, dt, fmt):
fmt = self.illegal_s.sub(r"/1", fmt)
fmt = fmt.replace("%s", "s")
if dt.year > 1900:
return cbook.unicode_safe(dt.strftime(fmt))
year = dt.year
# For every non-leap year century, advance by
# 6 years to get into the 28-year repeat cycle
delta = 2000 - year
off = 6*(delta // 100 + delta // 400)
year = year + off
# Move to around the year 2000
year = year + ((2000 - year)//28)*28
timetuple = dt.timetuple()
s1 = time.strftime(fmt, (year,) + timetuple[1:])
sites1 = self._findall(s1, str(year))
s2 = time.strftime(fmt, (year+28,) + timetuple[1:])
sites2 = self._findall(s2, str(year+28))
sites = []
for site in sites1:
if site in sites2:
sites.append(site)
s = s1
syear = "%4d" % (dt.year,)
for site in sites:
s = s[:site] + syear + s[site+4:]
return cbook.unicode_safe(s)
La documentación parece bastante clara sobre esto:
El rango exacto de años para los que funciona
strftime()
también varía según las plataformas. Independientemente de la plataforma, años antes de 1900 no se puede utilizar.
Así que no habrá una solución que use strftime()
. Afortunadamente, es bastante sencillo hacer esto "a mano":
>>> "%02d-%02d-%02d %02d:%02d" % (d.year,d.month,d.day,d.hour,d.minute)
''1899-01-01 00:00''
isoformat funciona en instancias de datetime
sin limitación de rango:
>>> import datetime
>>> x=datetime.datetime(1865, 7, 2, 9, 30, 21)
>>> x.isoformat()
''1865-07-02T09:30:21''
Si necesita una cadena de formato diferente, no es demasiado difícil cortar, cortar y remezclar piezas de la cadena que obtiene de isoformat
, que es muy consistente ( YYYY-MM-DDTHH:MM:SS.mmmmmm
, con el punto y los siguientes microsegundos omitido si los microsegundos son cero).
mxDateTime
puede manejar fechas arbitrarias. Los módulos de time
y datetime
/ datetime
Python utilizan marcas de tiempo de UNIX internamente, por eso tienen un rango limitado.
In [5]: mx.DateTime.DateTime(1899)
Out[5]: <mx.DateTime.DateTime object for ''1899-01-01 00:00:00.00'' at 154a960>
In [6]: DateTime.DateTime(1899).Format(''%Y-%m-%d'')
Out[6]: 1899-01-01