2013-03-11 18 views
24

Ho uno script python che utilizza questa chiamata per ottenere la data di ieri nel formato AAAA-MM-DD:Ottenere la data di ieri in Python, DST-safe

str(date.today() - timedelta(days=1))) 

Funziona maggior parte del tempo, ma quando il Lo script è stato pubblicato stamattina allo 2013-03-11 0:35 CDT restituito "2013-03-09" anziché "2013-03-10".

Presumibilmente l'ora legale (che è iniziata ieri) è la colpa. Immagino che il modo in cui è implementato lo timedelta(days=1) sia stato sottratto 24 ore e 24 ore prima che lo 2013-03-11 0:35 CDT sia stato 2013-03-09 23:35 CST, il che ha portato al risultato di "2013-03-09".

Allora, qual è un buon modo DST-safe per ottenere la data di ieri in python?

UPDATE: Dopo bukzor ha sottolineato che il mio codice dovrebbe aver funzionato correttamente, sono tornato allo script e stabilito che non è stato utilizzato. Imposta il valore predefinito, ma uno script della shell wrapper stava impostando la data in modo esplicito. Quindi il bug è nello script della shell, non nello script python.

+2

Un tale problema si verifica solo con un oggetto datetime timezeone, che "date.today()" non lo è. In che modo esattamente l'oggetto è istanziato? – bukzor

+0

@bukzor hai ragione. Si scopre che uno script di shell stava passando la data sbagliata, vedere il mio aggiornamento sopra. –

+0

Questa domanda dovrebbe essere chiusa; l'OP afferma che il suo bug è altrove. –

risposta

39
datetime.date.fromordinal(datetime.date.today().toordinal()-1) 
9

io non sono in grado di riprodurre il problema in python2.7 o python3.2:

>>> import datetime 
>>> today = datetime.date(2013, 3, 11) 
>>> print today 
2013-03-11 
>>> day = datetime.timedelta(days=1) 
>>> print today - day 
2013-03-10 

Mi sembra che questo è già il più semplice attuazione di un "luce del giorno-risparmio sicuro "Funzione yesterday().

+0

hai impostato il tempo di sistema per 2013-03-11 0:35 prima di provare questo? Il problema si verifica 1 ora dopo la mezzanotte quando viene applicata l'ora legale, il giorno ha solo 23 ore. – tdelaney

+0

@tdelaney: l'impostazione dell'ora del sistema è un modo indiretto per ottenere gli stessi risultati. in entrambi i casi si ottiene un oggetto datetime.date "ingenuo" con questo valore. – bukzor

+0

@tdelaney: il codice funziona così com'è perché usa gli oggetti * naive * 'date'. Stampa correttamente la data locale ma non ci dice nulla sul tempo effettivo relativo a UTC: [potrebbe essere tempo ambiguo o addirittura non esistente] (http://stackoverflow.com/a/29832960/4279) (ad es. è fuso orario in Brasile con transizioni DST a mezzanotte). In particolare, le compensazioni di utc potrebbero essere diverse a 'today' e' today - DAY'. È necessario il database tz per [trovare l'ora UTC corrispondente (ad esempio, espressa come oggetti datetime consapevoli)] (http://stackoverflow.com/a/15345272/4279). – jfs

7

Otterrete 2013-03-10 se si utilizza ingenuo datetime oggetto che non sa nulla di fusi orari (e DST in particolare):

from datetime import datetime, timedelta 

dt_naive = datetime(2013, 3, 11, 0, 35) 
print((dt_naive - timedelta(days=1)).date()) # ignores DST 
# -> 2013-03-10 

2013-03-09 è corretto, se siete interessati quale data è stato 24 ore fa.

import pytz # $ pip install pytz 

local_tz = pytz.timezone("America/Chicago") # specify your local timezone 
dt = local_tz.localize(dt_naive, is_dst=None) # raise if dt_naive is ambiguous 
yesterday = local_tz.normalize(dt - timedelta(days=1)).date() 
print(yesterday) 
# -> 2013-03-09 

Nota: .date() strisce informazioni fuso orario in modo otterrete 2013-03-10 ancora:

print(dt.date() - timedelta(days=1)) 
# -> 2013-03-10 

Per ottenere ieri in particolare fuso orario:

from datetime import datetime, time, timedelta 
import pytz # $ pip install pytz 

tz = pytz.timezone("America/Chicago") 
yesterday = datetime.now(tz).date() - timedelta(days=1) 

# to add timezone info back (to get yesterday's midnight) 
midnight = tz.localize(datetime.combine(yesterday, time(0, 0)), is_dst=None) 

Ottenere ieri mettendo a nudo informazioni fuso orario potrebbe non riuscire se il fuso orario ha giorni mancanti in quel periodo. Quindi questo metodo produrrebbe la data non esistente nel fuso orario specificato (tz.localize() genera un errore).

Problemi correlati