Domanda

Il meglio che posso venire con per ora è questa mostruosità:

>>> datetime.utcnow() \
...   .replace(tzinfo=pytz.UTC) \
...   .astimezone(pytz.timezone("Australia/Melbourne")) \
...   .replace(hour=0,minute=0,second=0,microsecond=0) \
...   .astimezone(pytz.UTC) \
...   .replace(tzinfo=None)
datetime.datetime(2008, 12, 16, 13, 0)

vale a dire., In lingua inglese, ottenere il tempo corrente (in UTC), convertirlo in qualche altro fuso orario, impostare l'ora a mezzanotte, poi riconvertire UTC.

Non sto usando ora () o localtime () come sarebbe utilizzare fuso orario del server, non fuso orario dell'utente.

Non posso fare a meno che mi manca qualcosa, qualche idea?

È stato utile?

Soluzione

Credo che si può radersi un metodo paio di telefonate se lo si fa in questo modo:

>>> from datetime import datetime
>>> datetime.now(pytz.timezone("Australia/Melbourne")) \
            .replace(hour=0, minute=0, second=0, microsecond=0) \
            .astimezone(pytz.utc)

MA ... c'è un problema più grande di quanto l'estetica nel codice:. Darà il risultato sbagliato, il giorno del passaggio verso o da ora legale

La ragione di questo è che né i costruttori né datetime replace() prendono modifiche dell'ora legale in considerazione.

Ad esempio:

>>> now = datetime(2012, 4, 1, 5, 0, 0, 0, tzinfo=pytz.timezone("Australia/Melbourne"))
>>> print now
2012-04-01 05:00:00+10:00
>>> print now.replace(hour=0)
2012-04-01 00:00:00+10:00 # wrong! midnight was at 2012-04-01 00:00:00+11:00
>>> print datetime(2012, 3, 1, 0, 0, 0, 0, tzinfo=tz)
2012-03-01 00:00:00+10:00 # wrong again!

Tuttavia, la documentazione per gli stati tz.localize():

  

Questo metodo deve essere usato per costruire LocalTimes piuttosto   che passare un argomento tzinfo a un costruttore datetime.

In questo modo, il problema è risolto in questo modo:

>>> import pytz
>>> from datetime import datetime, date, time

>>> tz = pytz.timezone("Australia/Melbourne")
>>> the_date = date(2012, 4, 1) # use date.today() here

>>> midnight_without_tzinfo = datetime.combine(the_date, time())
>>> print midnight_without_tzinfo
2012-04-01 00:00:00

>>> midnight_with_tzinfo = tz.localize(midnight_without_tzinfo)
>>> print midnight_with_tzinfo
2012-04-01 00:00:00+11:00

>>> print midnight_with_tzinfo.astimezone(pytz.utc)
2012-03-31 13:00:00+00:00

Non ci sono garanzie per le date prima di 1582, però.

Altri suggerimenti

@ risposta di luppolo è sbagliato, al momento della transizione da ora legale (DST) per esempio, Apr 1, 2012 . Per risolvere il problema tz.localize() potrebbe essere utilizzato:

tz = pytz.timezone("Australia/Melbourne")
today = datetime.now(tz).date()
midnight = tz.localize(datetime.combine(today, time(0, 0)), is_dst=None)
utc_dt = midnight.astimezone(pytz.utc)        

Lo stesso con i commenti:

#!/usr/bin/env python
from datetime import datetime, time
import pytz # pip instal pytz

tz = pytz.timezone("Australia/Melbourne") # choose timezone

# 1. get correct date for the midnight using given timezone.
today = datetime.now(tz).date()

# 2. get midnight in the correct timezone (taking into account DST)
#NOTE: tzinfo=None and tz.localize()
# assert that there is no dst transition at midnight (`is_dst=None`)
midnight = tz.localize(datetime.combine(today, time(0, 0)), is_dst=None)

# 3. convert to UTC (no need to call `utc.normalize()` due to UTC has no 
#    DST transitions)
fmt = '%Y-%m-%d %H:%M:%S %Z%z'
print midnight.astimezone(pytz.utc).strftime(fmt)

Impostazione della variabile d'ambiente TZ modifica ciò che data e ora del fuso orario Python lavorare.

>>> time.gmtime()
(2008, 12, 17, 1, 16, 46, 2, 352, 0)
>>> time.localtime()
(2008, 12, 16, 20, 16, 47, 1, 351, 0)
>>> os.environ['TZ']='Australia/Melbourne'
>>> time.localtime()
(2008, 12, 17, 12, 16, 53, 2, 352, 1)

Ogni fuso orario ha un numero, ad esempio, US / Centrale = -6. Questo è definito come l'offset in ore da UTC. Dal 0000 è a mezzanotte, si può semplicemente utilizzare questo offset a trovare il tempo in qualsiasi fuso orario quando è mezzanotte UTC. Per accedere a questo, io credo che si possa utilizzare

 time.timezone

Il Python Docs , time.timezone dà in realtà il valore negativo di questo numero:

  
    

time.timezone

         
      

L'offset del fuso orario locale (non DST), in secondi ovest di UTC (negativo nella maggior parte dell'Europa occidentale, positivo negli Stati Uniti, pari a zero nel Regno Unito).

    
  

Quindi, si dovrebbe semplicemente usare questo numero per il tempo in ore, se è positivo (vale a dire, se è mezzanotte a Chicago (che ha un valore di sei fuso orario), allora è 6000 = 06:00 UTC).

Se il numero è negativo, sottrarre 24. Per esempio, Berlino darebbe -1, così 24 -. 1 => 2300 = 11:00

Questa è più semplice con dateutil.tz di pytz:

>>>import datetime
>>>import dateutil.tz
>>>midnight=(datetime.datetime
             .now(dateutil.tz.gettz('Australia/Melbourne'))
             .replace(hour=0, minute=0, second=0, microsecond=0)
             .astimezone(dateutil.tz.tzutc()))
>>>print(midnight)
2019-04-26 14:00:00+00:00

Il tzinfo documentazione raccomanda dateutil.tz dal Python 3.6. Gli oggetti tzinfo da dateutil.tz non hanno problemi con difetti come DST senza richiedere la funzionalità di localizzare pytz. Usando l'esempio di user3850:

>>> now = (datetime.datetime(2012, 4, 1, 5,  
...         tzinfo = dateutil.tz.gettz('Australia/Melbourne'))) 
>>> print(now.replace(hour = 0).astimezone(dateutil.tz.tzutc()))
2012-03-31 13:00:00+00:00
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top