Esiste un modo per utilizzare una funzione simile a strftime per le date precedenti al 1900 in Python?

StackOverflow https://stackoverflow.com/questions/1643967

Domanda

Non me ne sono reso conto, ma a quanto pare la funzione strftime di Python non supporta le date precedenti al 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

Sono sicuro di poter hackerare insieme qualcosa per farlo, ma immagino che la funzione strftime sia lì per un motivo (e c'è anche un motivo per cui non può supportare pre 1900 date). Devo essere in grado di supportare date precedenti al 1900. Utilizzerei solo str , ma ci sono troppe variazioni. In altre parole, può avere o meno microsecondi oppure può avere o meno un fuso orario. C'è una soluzione a questo?

Se fa la differenza, lo sto facendo in modo da poter scrivere i dati in un file di testo e caricarli in un database usando Oracle SQL * Loader.

Ho essenzialmente finito per rispondere ad Alex Martelli. Ecco un'implementazione più completa:

>>> from datetime import datetime
>>> d = datetime.now()
>>> d = d.replace(microsecond=0, tzinfo=None)
>>> str(d)
'2009-10-29 11:27:27'

L'unica differenza è che str (d) è equivalente a d.isoformat ('') .

È stato utile?

Soluzione

isoformat funziona su datetime istanze senza limitazione dell'intervallo:

>>> import datetime
>>> x=datetime.datetime(1865, 7, 2, 9, 30, 21)
>>> x.isoformat()
'1865-07-02T09:30:21'

Se hai bisogno di una stringa di diverso formato non è troppo difficile tagliare, tagliare e remixare i pezzi della stringa che ottieni da isoformat , che è molto coerente ( YYYY-MM-DDTHH : MM: SS.mmmmmm , con il punto e i seguenti microsecondi omessi se i microsecondi sono zero).

Altri suggerimenti

La sembra abbastanza chiara al riguardo:

  

L'intervallo esatto di anni per cui strftime () varia anche tra le piattaforme. Indipendentemente dalla piattaforma, anni prima del 1900 non possono essere utilizzati.

Quindi non ci sarà una soluzione che utilizza strftime () . Fortunatamente, è abbastanza semplice fare questo "a mano":

>>> "%02d-%02d-%02d %02d:%02d" % (d.year,d.month,d.day,d.hour,d.minute)
'1899-01-01 00:00'

mxDateTime può gestire date arbitrarie . I moduli time e datetime di Python usano i timestamp UNIX internamente, ecco perché hanno un raggio limitato.

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

Questo è dal fonte matplotlib . Potrebbe fornire un buon punto di partenza per il tuo.

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)

Questa è la funzione " " della libreria ctime (UTF). Inoltre potresti avere problemi al di sopra del 2038.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top