Obține fusul orar utilizat de datetime.datetime.fromtimestamp() (Programare, Python, Fus Orar)

Feuermurmel a intrebat.

Este posibil, și dacă da, cum, să obținem fusul orar (adică decalajul UTC sau un datetime.timezone instanță cu acest decalaj) care este utilizat de datetime.datetime.fromtimestamp() pentru a converti un timestamp POSIX (secundele de la epoca) în datetime obiect?

datetime.datetime.fromtimestamp() convertește un timestamp POSIX într-un obiect naiv datetime naiv (adică fără un obiect tzinfo), dar o face utilizând localele sistemului pentru a-l ajusta la fusul orar local și la decalajul UTC în vigoare la momentul respectiv.

De exemplu, folosind data 2008-12-27 miezul nopții UTC (40 * 356 * 86400 secunde de la începutul epocii):

>>> datetime.datetime.fromtimestamp(40 * 356 * 86400)
datetime.datetime(2008, 12, 27, 1, 0)

Această marcă temporală este convertită într-un datetime obiect la ora 1 dimineața (ceea ce era la acel moment, aici, într-un fus orar CET/CEST). 100 de zile mai târziu, acesta este rezultatul:

>>> datetime.datetime.fromtimestamp((40 * 356 + 100) * 86400)
datetime.datetime(2009, 4, 6, 2, 0)

Care este ora 2 dimineața. Acest lucru se datorează faptului că, până atunci, DST era activ.

Mă așteptam ca datetime.datetime.fromtimestamp() să seteze ora tzinfo pe care o folosește în rezultatul returnat datetime instanță, dar nu este așa.

4 răspunsuri
jfs

datetime.fromtimestamp(ts) convertește „secundele de la epocă” într-un obiect datetime naiv care reprezintă ora locală. tzinfo este întotdeauna None în acest caz.

Este posibil ca fusul orar local să fi avut un decalaj UTC diferit în trecut. Pe unele sisteme care oferă acces la o bază de date cu fus orar istoric, fromtimestamp() poate lua în considerare acest lucru.

Pentru a obține decalajul UTC utilizat de fromtimestamp():

utc_offset = fromtimestamp(ts) - utcfromtimestamp(ts)

Consultați, de asemenea, Getting computer’s utc offset in Python.

Comentarii

  • Acesta este de fapt ceea ce aș fi avut nevoie atunci când am pus întrebarea. Cunoașterea regulilor de fus orar nu este importantă, doar decalajul UTC este suficient pentru ceea ce făceam. –  > Por Feuermurmel.
Matt Johnson-Pint

De la documentația Python:

classmethod datetime.fromtimestamp(timestamp, tz=None)

Returnează data și ora locală corespunzătoare timestamp-ului POSIX, așa cum este returnat de către time.time(). În cazul în care argumentul opțional tz este None sau nu este specificat, timestamp-ul este convertit în data și ora locală a platformei, iar valoarea returnată datetime este naiv.

În caz contrar, tz trebuie să fie o instanță a unei clase tzinfo subclasă, iar marca temporală este convertită la tz‘s time zone. În acest caz, rezultatul este echivalent cu tz.fromutc(datetime.utcfromtimestamp(timestamp).replace(tzinfo=tz)).

Partea esențială a acestei descrieri în legătură cu întrebarea dumneavoastră este că, atunci când nu se specifică un fus orar, nu numai că se utilizează fusul orar local, dar rezultatul este naiv. Se pare că doriți ca acesta să fie conștient.

Aceasta este o distincție specială făcută de Python și este discutată chiar în partea de sus a cărții documentația datetime.

Dacă ceea ce doriți este un datetime care este cunoscută de fusul orar local, încercați tzlocal . Aceasta se concentrează pe această problemă specifică. Vedeți și această întrebare.

Comentarii

  • Da, vreau o aplicație conștientă datetime dar caut o modalitate de a face acest lucru fără a utiliza biblioteci suplimentare, deoarece Python evident, are deja acces la logica necesară pentru a calcula decalajul corect de la un timestamp POSIX. –  > Por Feuermurmel.
  • De fapt, nu o are pe cont propriu. Se bazează pe mediul gazdă pentru a furniza traducerea. Deoarece acest lucru este specific platformei, iar platformele diferite au implementări diferite ale bazei de date tz, nu poate copia regulile de conversie înapoi într-un obiect tzinfo. –  > Por Matt Johnson-Pint.
  • Știu că acesta este cazul. Dar, prin intermediul bibliotecii C, are acces la logica care poate atribui un offset UTC unui timestamp POSIX folosind setările sistemului de operare (altfel, codul din întrebare nu ar funcționa). –  > Por Feuermurmel.
  • Exact. Doar că nu poate copia acea logică înapoi într-un obiect python tzinfo, așa că nu poate reprezenta niciodată acest lucru ca un conștient datatime. De aceea, biblioteca tzlocal încearcă să ghicească regulile de fus orar. Ea interoghează sistemul de operare, dar apoi atribuie propria valoare înapoi la tzinfo. Nu există nimic încorporat care să facă acest lucru. –  > Por Matt Johnson-Pint.
  • @Feuermurmel: .tm_zone, .tm_gmtoff nu sunt disponibile pe toate platformele. Iar time.timezone, time.tzname pot da greș pentru unele zone orare. Consultați ultimul link din răspunsul meu. tzlocal returnează timezone pytz care este cea mai bună opțiune pentru soluții cross-platform. În plus, diferite versiuni ale bazei de date tz pot furniza diferite definiții pentru aceleași fus orar – instalarea modulului pytz pur Python vă permite să controlați versiunea utilizată. –  > Por jfs.
Emil Stenström

Dacă știți fusul orar al mărcii temporale pe care doriți să o convertiți, puteți pur și simplu să o trimiteți în timp ce apelați fromtimestamp:

>>> from datetime import datetime
>>> import pytz
>>>
>>> datetime.fromtimestamp(1562684265, pytz.timezone("Europe/Stockholm"))
datetime.datetime(2019, 7, 9, 16, 57, 45, tzinfo=<DstTzInfo 'Europe/Stockholm' CEST+2:00:00 DST>)
>>>
>>> datetime.fromtimestamp(1562684265, pytz.timezone("UTC"))
datetime.datetime(2019, 7, 9, 14, 57, 45, tzinfo=<UTC>)

AChampion

Utilizând time.gmtime puteți extrage fusul orar așa cum este descris în acest răspuns anterior: Obțineți informații TZ ale sistemului în Python?.

>>> from __future__ import print_function
>>> from time import gmtime, strftime
>>> print(strftime("%z", gmtime()))
-0600

Imprimă -06:00 pentru laptopul meu CST atât în python-2.7, cât și în python-3.3Puteți utiliza, de asemenea, localtime() pentru a obține o structură de timp locală.

>>> from __future__ import print_function
>>> from time import localtime
>>> lt = localtime()
>>> print(lt.tm_zone)
"CDT"
>>> print(lt.tm_gmtoff/(60*60))
-5.0
>>> print(lt.tm_gmtoff/(60*60) - (1 if lt.tm_isdst == 1 else 0)) # Adjusted for DST
-6.0

Sper că vă ajută

Comentarii

  • Nu v-a plăcut un răspuns specific (puteți face acest lucru făcând clic pe share sub un răspuns și copiind url-ul), la care vă referiți? –  > Por Feuermurmel.
  • Probabil ați vrut să spuneți time.gmtime. În Python 3.3, se tipărește time.struct_time(tm_year=2008, tm_mon=12, tm_mday=27, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=362, tm_isdst=0). Nu văd nicio informație despre fusul orar. –  > Por Feuermurmel.
  • Oh, probabil ați vrut să spuneți time.gmtime().tm_gmtoff! Nu funcționează. Se întoarce 0 pe un sistem care este setat pe CEST. –  > Por Feuermurmel.
  • Două note: Nu ar trebui ca primul tău exemplu să imprime +0000, , ca gmtimes()precizează că în documentația lui struct_time este în UTC? Și lt.tm_gmtoff pare să fie singura modalitate pe care am găsit-o până acum, dar asta înseamnă că localtime() trebuie să fie apelat de două ori (o dată de către datetime.fromtimestamp()) pentru a crea un fișier conștient datetime instanță. –  > Por Feuermurmel.
  • De asemenea, offset UTC la 40 * 356 * 86400 timestamp poate fi diferit de offsetul UTC curent. Șitm_gmtoff nu este disponibil pe toate sistemele, a se vedea răspunsul meu. –  > Por jfs.