Ricerca…


Osservazioni

Python fornisce sia metodi incorporati che librerie esterne per creare, modificare, analizzare e manipolare date e ore.

Analisi di una stringa in un oggetto datetime timezone aware

Python 3.2+ supporta il formato %z quando analizza una stringa in un oggetto datetime .

Scostamento UTC nel formato +HHMM o -HHMM (stringa vuota se l'oggetto è ingenuo).

Python 3.x 3.2
import datetime
dt = datetime.datetime.strptime("2016-04-15T08:27:18-0500", "%Y-%m-%dT%H:%M:%S%z")

Per altre versioni di Python, è possibile utilizzare una libreria esterna come dateutil , che rende dateutil analisi di una stringa con fuso orario in un oggetto datetime .

import dateutil.parser
dt = dateutil.parser.parse("2016-04-15T08:27:18-0500")

La variabile dt è ora un oggetto datetime con il seguente valore:

datetime.datetime(2016, 4, 15, 8, 27, 18, tzinfo=tzoffset(None, -18000))

Data semplice aritmetica

Le date non esistono in isolamento. È normale che tu debba trovare la quantità di tempo tra le date o determinare quale sarà la data di domani. Questo può essere realizzato usando oggetti timedelta

import datetime

today = datetime.date.today()
print('Today:', today)

yesterday = today - datetime.timedelta(days=1)
print('Yesterday:', yesterday)

tomorrow = today + datetime.timedelta(days=1)
print('Tomorrow:', tomorrow)

print('Time between tomorrow and yesterday:', tomorrow - yesterday)

Ciò produrrà risultati simili a:

Today: 2016-04-15
Yesterday: 2016-04-14
Tomorrow: 2016-04-16
Difference between tomorrow and yesterday: 2 days, 0:00:00

Utilizzo di oggetti datetime di base

Il modulo datetime contiene tre tipi principali di oggetti: data, ora e data / ora.

import datetime

# Date object
today = datetime.date.today()
new_year = datetime.date(2017, 01, 01) #datetime.date(2017, 1, 1)

# Time object
noon = datetime.time(12, 0, 0) #datetime.time(12, 0)

# Current datetime
now = datetime.datetime.now()

# Datetime object
millenium_turn = datetime.datetime(2000, 1, 1, 0, 0, 0) #datetime.datetime(2000, 1, 1, 0, 0)

Le operazioni aritmetiche per questi oggetti sono supportate solo nello stesso tipo di dati e l'esecuzione di operazioni aritmetiche semplici con istanze di tipi diversi comporterà un'eccezione TypeError.

# subtraction of noon from today
noon-today
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for -: 'datetime.time' and 'datetime.date'
However, it is straightforward to convert between types.

# Do this instead
print('Time since the millenium at midnight: ',
      datetime.datetime(today.year, today.month, today.day) - millenium_turn)

# Or this
print('Time since the millenium at noon: ',
      datetime.datetime.combine(today, noon) - millenium_turn)

Scorri le date

A volte si desidera eseguire un'iterazione su un intervallo di date da una data di inizio a una data di fine. Puoi farlo usando la libreria datetime e timedelta oggetto timedelta :

import datetime

# The size of each step in days
day_delta = datetime.timedelta(days=1)

start_date = datetime.date.today()
end_date = start_date + 7*day_delta

for i in range((end_date - start_date).days):
    print(start_date + i*day_delta)

Che produce:

2016-07-21
2016-07-22
2016-07-23
2016-07-24
2016-07-25
2016-07-26
2016-07-27

Analisi di una stringa con un nome breve fuso orario in un oggetto datetime timezone aware

Utilizzando la libreria dateutil come nell'esempio precedente dateutil timestamp sensibili al fuso orario , è anche possibile analizzare i timestamp con un nome di fuso orario "breve" specificato.

Per le date formattate con i nomi di zona breve tempo o abbreviazioni, che sono generalmente ambigua (ad esempio CST, che potrebbe essere centrale Standard Time, Cina Standard Time, Cuba Standard Time, ecc - più può essere trovato qui ) o non necessariamente disponibili in un database standard , è necessario specificare una mappatura tra l'abbreviazione del fuso orario e l'oggetto tzinfo .

from dateutil import tz
from dateutil.parser import parse

ET = tz.gettz('US/Eastern')
CT = tz.gettz('US/Central')
MT = tz.gettz('US/Mountain')
PT = tz.gettz('US/Pacific')

us_tzinfos = {'CST': CT, 'CDT': CT,
              'EST': ET, 'EDT': ET,
              'MST': MT, 'MDT': MT,
              'PST': PT, 'PDT': PT}

dt_est = parse('2014-01-02 04:00:00 EST', tzinfos=us_tzinfos)
dt_pst = parse('2016-03-11 16:00:00 PST', tzinfos=us_tzinfos)

Dopo aver eseguito questo:

dt_est
# datetime.datetime(2014, 1, 2, 4, 0, tzinfo=tzfile('/usr/share/zoneinfo/US/Eastern'))
dt_pst
# datetime.datetime(2016, 3, 11, 16, 0, tzinfo=tzfile('/usr/share/zoneinfo/US/Pacific'))

Vale la pena notare che se si utilizza un pytz fuso orario con questo metodo, non sarà adeguatamente localizzato:

from dateutil.parser import parse
import pytz

EST = pytz.timezone('America/New_York')
dt = parse('2014-02-03 09:17:00 EST', tzinfos={'EST': EST})

Questo semplicemente associa il pytz orario pytz al datetime:

dt.tzinfo # Will be in Local Mean Time!
# <DstTzInfo 'America/New_York' LMT-1 day, 19:04:00 STD>

Se si utilizza questo metodo, è consigliabile localize la parte ingenua del datetime dopo l'analisi:

dt_fixed = dt.tzinfo.localize(dt.replace(tzinfo=None))
dt_fixed.tzinfo # Now it's EST.
# <DstTzInfo 'America/New_York' EST-1 day, 19:00:00 STD>)

Costruzione di datetize sensibili al fuso orario

Di default tutti gli oggetti datetime sono ingenui. Per renderli sensibili al fuso orario, è necessario allegare un oggetto tzinfo , che fornisce l'offset UTC e l'abbreviazione del fuso orario in funzione della data e dell'ora.

Fissi i fusi orari di offset

Per i fusi orari che sono un offset fisso da UTC, in Python 3.2+, il modulo datetime fornisce la classe timezone , un'implementazione concreta di tzinfo , che accetta un parametro nome timedelta e (facoltativo):

Python 3.x 3.2
from datetime import datetime, timedelta, timezone
JST = timezone(timedelta(hours=+9))

dt = datetime(2015, 1, 1, 12, 0, 0, tzinfo=JST)
print(dt)
# 2015-01-01 12:00:00+09:00

print(dt.tzname())
# UTC+09:00

dt = datetime(2015, 1, 1, 12, 0, 0, tzinfo=timezone(timedelta(hours=9), 'JST'))
print(dt.tzname)
# 'JST'

Per le versioni di Python precedenti alla 3.2, è necessario utilizzare una libreria di terze parti, come dateutil . dateutil fornisce una classe equivalente, tzoffset , che (a partire dalla versione 2.5.3) prende gli argomenti del modulo dateutil.tz.tzoffset(tzname, offset) , dove l' offset è specificato in secondi:

Python 3.x 3.2
Python 2.x 2.7
from datetime import datetime, timedelta
from dateutil import tz

JST = tz.tzoffset('JST', 9 * 3600) # 3600 seconds per hour
dt = datetime(2015, 1, 1, 12, 0, tzinfo=JST)
print(dt)
# 2015-01-01 12:00:00+09:00
print(dt.tzname)
# 'JST'

Zone con ora legale

Per le zone con ora legale, le librerie standard Python non forniscono una classe standard, quindi è necessario utilizzare una libreria di terze parti. pytz e dateutil sono librerie popolari che forniscono classi di fuso orario.

Oltre ai fusi orari statici, dateutil fornisce classi di fuso orario che utilizzano l'ora legale (consultare la documentazione del modulo tz ). È possibile utilizzare il metodo tz.gettz() per ottenere un oggetto del fuso orario, che può quindi essere passato direttamente al costruttore datetime :

from datetime import datetime
from dateutil import tz
local = tz.gettz() # Local time
PT = tz.gettz('US/Pacific') # Pacific time

dt_l = datetime(2015, 1, 1, 12, tzinfo=local) # I am in EST
dt_pst = datetime(2015, 1, 1, 12, tzinfo=PT)
dt_pdt = datetime(2015, 7, 1, 12, tzinfo=PT) # DST is handled automatically
print(dt_l)
# 2015-01-01 12:00:00-05:00
print(dt_pst)
# 2015-01-01 12:00:00-08:00
print(dt_pdt)
# 2015-07-01 12:00:00-07:00

ATTENZIONE : A partire dalla versione 2.5.3, dateutil non gestisce correttamente i datetimes ambigui e sarà sempre predefinito alla data successiva . Non v'è alcun modo per costruire un oggetto con un dateutil fuso orario che rappresenta, per esempio 2015-11-01 1:30 EDT-4 , poiché questo è in un periodo di transizione legale.

Tutti i casi limite sono gestiti correttamente quando si utilizza pytz , ma i pytz orari pytz non devono essere collegati direttamente ai fusi orari tramite il costruttore. Invece, un pytz orario di pytz dovrebbe essere collegato usando il metodo di localize del fuso orario:

from datetime import datetime, timedelta
import pytz

PT = pytz.timezone('US/Pacific')
dt_pst = PT.localize(datetime(2015, 1, 1, 12))
dt_pdt = PT.localize(datetime(2015, 11, 1, 0, 30))
print(dt_pst)
# 2015-01-01 12:00:00-08:00
print(dt_pdt)
# 2015-11-01 00:30:00-07:00

Tenere presente che se si esegue l'aritmetica data / ora su un fuso orario pytz , è necessario eseguire i calcoli in UTC (se si desidera il tempo trascorso assoluto) oppure è necessario chiamare normalize() sul risultato:

dt_new = dt_pdt + timedelta(hours=3) # This should be 2:30 AM PST
print(dt_new)
# 2015-11-01 03:30:00-07:00
dt_corrected = PT.normalize(dt_new)
print(dt_corrected)
# 2015-11-01 02:30:00-08:00

Parodia fuzzy parsing (estraendo datetime da un testo)

È possibile estrarre una data da un testo utilizzando l' analizzatore dateutil in modalità "fuzzy", in cui i componenti della stringa non riconosciuti come parte di una data vengono ignorati.

from dateutil.parser import parse

dt = parse("Today is January 1, 2047 at 8:21:00AM", fuzzy=True)
print(dt)

dt ora è un oggetto datetime e datetime.datetime(2047, 1, 1, 8, 21) stampato.

Passaggio da un fuso orario all'altro

Per passare da un fuso orario all'altro, sono necessari oggetti datetime che sono sensibili al fuso orario.

from datetime import datetime
from dateutil import tz

utc = tz.tzutc()
local = tz.tzlocal()

utc_now = datetime.utcnow()
utc_now # Not timezone-aware.

utc_now = utc_now.replace(tzinfo=utc)
utc_now # Timezone-aware.

local_now = utc_now.astimezone(local)
local_now # Converted to local time.

Analisi di un timestamp arbitrario ISO 8601 con librerie minime

Python ha solo un supporto limitato per l'analisi di timestamp ISO 8601. Per strptime riguarda la strptime è necessario sapere esattamente in che formato si trova. Come complicazione, la stringificazione di un datetime è un timestamp ISO 8601, con spazio come separatore e frazione di 6 cifre:

str(datetime.datetime(2016, 7, 22, 9, 25, 59, 555555))
# '2016-07-22 09:25:59.555555'

ma se la frazione è 0, non viene prodotta alcuna parte frazionaria

str(datetime.datetime(2016, 7, 22, 9, 25, 59, 0))
# '2016-07-22 09:25:59'

Ma queste 2 forme hanno bisogno di un formato diverso per la strptime . Inoltre, strptime' does not support at all parsing minute timezones that have a : in it, thus 2016-07-22 09: 25: 59 + 0300 can be parsed, but the standard format 2016-07-22 09:25:59 +03: 00` non può.

Esiste una libreria a file singolo chiamata iso8601 che analizza correttamente i timestamp ISO 8601 e solo loro.

Supporta frazioni e fusi orari e il separatore T tutto con un'unica funzione:

import iso8601
iso8601.parse_date('2016-07-22 09:25:59')
# datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=<iso8601.Utc>)
iso8601.parse_date('2016-07-22 09:25:59+03:00')
# datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=<FixedOffset '+03:00' ...>)
iso8601.parse_date('2016-07-22 09:25:59Z')
# datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=<iso8601.Utc>)
iso8601.parse_date('2016-07-22T09:25:59.000111+03:00')
# datetime.datetime(2016, 7, 22, 9, 25, 59, 111, tzinfo=<FixedOffset '+03:00' ...>)

Se non è impostato un fuso orario, iso8601.parse_date valore predefinito UTC. La zona predefinita può essere modificata con l'argomento della parola chiave default_zone . In particolare, se questo è None invece del valore predefinito, allora quei timestamp che non hanno un fuso orario esplicito vengono restituiti come dati naive invece:

iso8601.parse_date('2016-07-22T09:25:59', default_timezone=None)
# datetime.datetime(2016, 7, 22, 9, 25, 59)
iso8601.parse_date('2016-07-22T09:25:59Z', default_timezone=None)
# datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=<iso8601.Utc>)

Conversione del timestamp in data / ora

Il modulo datetime può convertire un timestamp POSIX in un oggetto datetime ITC.

The Epoch è il 1 gennaio 1970 a mezzanotte.

import time
from datetime import datetime
seconds_since_epoch=time.time()  #1469182681.709

utc_date=datetime.utcfromtimestamp(seconds_since_epoch) #datetime.datetime(2016, 7, 22, 10, 18, 1, 709000)

Sottraendo con precisione mesi da una data

Utilizzando il modulo del calendar

import calendar
from datetime import date

def monthdelta(date, delta):
    m, y = (date.month+delta) % 12, date.year + ((date.month)+delta-1) // 12
    if not m: m = 12
    d = min(date.day, calendar.monthrange(y, m)[1])
    return date.replace(day=d,month=m, year=y)

next_month = monthdelta(date.today(), 1) #datetime.date(2016, 10, 23)

Utilizzando il modulo dateutils

import datetime
import dateutil.relativedelta

d = datetime.datetime.strptime("2013-03-31", "%Y-%m-%d")
d2 = d - dateutil.relativedelta.relativedelta(months=1)  #datetime.datetime(2013, 2, 28, 0, 0)

Calcolo delle differenze di orario

il modulo timedelta è utile per calcolare le differenze tra i tempi:

from datetime import datetime, timedelta
now = datetime.now()
then = datetime(2016, 5, 23)     # datetime.datetime(2016, 05, 23, 0, 0, 0)

La specifica del tempo è facoltativa quando si crea un nuovo oggetto datetime

delta = now-then

delta è di tipo timedelta

print(delta.days)
# 60
print(delta.seconds)
# 40826

Per ottenere il giorno dopo e il giorno prima della data, potremmo usare:

n giorno dopo data:

def get_n_days_after_date(date_format="%d %B %Y", add_days=120):

    date_n_days_after = datetime.datetime.now() + timedelta(days=add_days)
    return date_n_days_after.strftime(date_format)

n giorno prima della data:

 def get_n_days_before_date(self, date_format="%d %B %Y", days_before=120):

        date_n_days_ago = datetime.datetime.now() - timedelta(days=days_before)
        return date_n_days_ago.strftime(date_format)

Ottieni un timestamp ISO 8601

Senza fuso orario, con microsecondi

from datetime import datetime

datetime.now().isoformat()
# Out: '2016-07-31T23:08:20.886783'

Con il fuso orario, con microsecondi

from datetime import datetime
from dateutil.tz import tzlocal

datetime.now(tzlocal()).isoformat()
# Out: '2016-07-31T23:09:43.535074-07:00'

Con il fuso orario, senza microsecondi

from datetime import datetime
from dateutil.tz import tzlocal

datetime.now(tzlocal()).replace(microsecond=0).isoformat()
# Out: '2016-07-31T23:10:30-07:00'

Vedere ISO 8601 per ulteriori informazioni sul formato ISO 8601.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow