Szukaj…


Uwagi

Python zapewnia zarówno wbudowane metody, jak i biblioteki zewnętrzne do tworzenia, modyfikowania, analizowania i manipulowania datami i godzinami.

Przetwarzanie ciągu znaków do obiektu datetime rozpoznającego strefę czasową

Python 3.2+ obsługuje format %z podczas parsowania łańcucha do obiektu datetime .

Przesunięcie UTC w postaci +HHMM lub -HHMM (pusty ciąg, jeśli obiekt jest naiwny).

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

W przypadku innych wersji Pythona możesz użyć zewnętrznej biblioteki, takiej jak dateutil , co sprawia, że parsowanie łańcucha ze dateutil czasową w obiekcie datetime jest szybkie.

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

Zmienna dt jest teraz obiektem typu datetime o następującej wartości:

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

Prosta arytmetyka dat

Daty nie istnieją w oderwaniu. Często zdarza się, że musisz znaleźć czas między datami lub ustalić, która data będzie jutro. Można to osiągnąć za pomocą obiektów 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)

Spowoduje to uzyskanie wyników podobnych do:

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

Podstawowe użycie obiektów datetime

Moduł datetime zawiera trzy podstawowe typy obiektów - datę, godzinę i datę i godzinę.

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)

Operacje arytmetyczne na tych obiektach są obsługiwane tylko w ramach tego samego typu danych, a wykonywanie prostej arytmetyki z wystąpieniami różnych typów spowoduje błąd typu.

# 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)

Iteruj po datach

Czasami chcesz iterować w zakresie dat od daty początkowej do pewnej daty końcowej. Możesz to zrobić za pomocą biblioteki datetime i obiektu 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)

Który produkuje:

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

Przetwarzanie ciągu o krótkiej nazwie strefy czasowej do obiektu datetime rozpoznającego strefę czasową

Korzystając z biblioteki dateutil tak jak w poprzednim przykładzie, podczas analizowania znaczników czasowych uwzględniających strefy czasowe , możliwe jest także analizowanie znaczników czasowych z określoną „krótką” nazwą strefy czasowej.

W przypadku dat sformatowanych za pomocą krótkich nazw stref lub skrótów, które są na ogół niejednoznaczne (np. CST, który może być czasem standardowym centralnym, czasem standardowym w Chinach, czasem standardowym na Kubie itp. - więcej informacji można znaleźć tutaj ) lub niekoniecznie jest dostępny w standardowej bazie danych , konieczne jest określenie odwzorowania między skrótem strefy czasowej a obiektem 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)

Po uruchomieniu tego:

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'))

Warto zauważyć, że w przypadku korzystania z pytz strefę czasową z tej metody, nie będzie on prawidłowo zlokalizowane:

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})

To po prostu dołącza pytz czasową pytz do pytz godziny:

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

Jeśli używasz tej metody, prawdopodobnie powinieneś ponownie localize naiwną część daty i godziny po analizie:

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>)

Konstruowanie czasów danych uwzględniających strefy czasowe

Domyślnie wszystkie obiekty datetime są naiwne. Aby uświadomić im strefę czasową, musisz dołączyć obiekt tzinfo , który zapewnia przesunięcie UTC i skrót strefy czasowej jako funkcję daty i godziny.

Naprawiono przesunięte strefy czasowe

Dla stref czasowych, które są stałym przesunięciem w stosunku do UTC, w Pythonie 3.2+ moduł datetime udostępnia klasę timezone , konkretną implementację tzinfo , która przyjmuje parametr timedelta i (opcjonalnie) nazwę:

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'

W przypadku wersji Python wcześniejszych niż 3.2 konieczne jest użycie biblioteki innej firmy, takiej jak dateutil . dateutil zapewnia równoważną klasę, tzoffset , która (od wersji 2.5.3) przyjmuje argumenty w postaci dateutil.tz.tzoffset(tzname, offset) , gdzie offset jest określany w sekundach:

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'

Strefy z czasem letnim

W strefach z czasem letnim standardowe biblioteki Pythona nie zapewniają standardowej klasy, dlatego konieczne jest użycie biblioteki innej firmy. pytz i dateutil to popularne biblioteki zapewniające klasy stref czasowych.

Oprócz statycznych stref czasowych dateutil udostępnia klasy stref czasowych, które wykorzystują czas letni (patrz dokumentacja modułu tz ). Możesz użyć metody tz.gettz() , aby uzyskać obiekt strefy czasowej, który można następnie przekazać bezpośrednio do konstruktora 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

PRZESTROGA : Począwszy od wersji 2.5.3, dateutil nie obsługuje poprawnie niejednoznacznych dateutil i zawsze dateutil domyślną datę późniejszą . Nie ma możliwości skonstruowania obiektu ze dateutil czasową dateutil reprezentującą na przykład 2015-11-01 1:30 EDT-4 , ponieważ odbywa się to podczas zmiany czasu letniego.

Wszystkie przypadki krawędzi są obsługiwane poprawnie podczas używania pytz , ale strefy czasowe pytz nie powinny być bezpośrednio dołączane do stref czasowych za pośrednictwem konstruktora. Zamiast tego należy pytz strefę czasową pytz przy użyciu metody localize strefy czasowej:

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

Należy pamiętać, że jeśli wykonujesz arytmetykę czasu i godziny w strefie czasowej pytz , musisz albo wykonać obliczenia w UTC (jeśli chcesz mieć bezwzględny upływ czasu), albo musisz wywołać normalize() dla wyniku:

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

Rozmyte analizowanie daty i godziny (wyodrębnianie daty i godziny z tekstu)

Możliwe jest wyodrębnienie daty z tekstu za pomocą parsera dateutil w trybie „rozmytym”, w którym komponenty ciągu nierozpoznanego jako część daty są ignorowane.

from dateutil.parser import parse

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

dt jest teraz obiektem datetime i wydrukowano by datetime.datetime(2047, 1, 1, 8, 21) .

Przełączanie między strefami czasowymi

Aby przełączać się między strefami czasowymi, potrzebujesz obiektów datetime, które uwzględniają strefy czasowe.

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.

Analiza dowolnego znacznika czasu ISO 8601 przy minimalnej liczbie bibliotek

Python ma ograniczoną obsługę analizowania znaczników czasu ISO 8601. Dla strptime trzeba dokładnie wiedzieć, co jest w formacie jako powikłanie stringification o. datetime jest ISO 8601 datownik, z miejsca jako separator i frakcją 6 cyfr:

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

ale jeśli ułamkiem jest 0, nie jest generowana żadna część ułamkowa

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

Ale te 2 formularze wymagają innego formatu czasu strptime . Co więcej, 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` nie może.

Jest to pojedynczy plik biblioteki nazywa iso8601 który właściwie analizuje ISO 8601 znaczniki czasu i tylko ich.

Obsługuje ułamki i strefy czasowe, a separator T wszystkie z jedną funkcją:

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' ...>)

Jeśli nie ustawiono żadnej strefy czasowej, domyślnie iso8601.parse_date to UTC. Strefę domyślną można zmienić za pomocą argumentu słowa kluczowego default_zone . W szczególności, jeśli jest to None zamiast wartości domyślnej, wówczas te znaczniki czasu, które nie mają wyraźnej strefy czasowej, są zwracane jako naiwne czasy danych:

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>)

Konwertowanie znacznika czasu na datę i godzinę

Moduł datetime może konwertować timestamp POSIX na obiekt datetime ITC.

Epoka przypada na północ 1 stycznia 1970 roku.

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)

Odejmowanie miesięcy dokładnie od daty

Korzystanie z modułu 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)

Korzystanie z modułu 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)

Obliczanie różnic czasowych

moduł timedelta przydaje się do obliczania różnic między czasami:

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

Określanie czasu jest opcjonalne podczas tworzenia nowego datetime obiektu

delta = now-then

delta jest typu timedelta

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

Aby uzyskać n dzień po i n dzień przed datą, możemy użyć:

n dzień po dacie:

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)

dzień przed datą:

 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)

Uzyskaj znacznik czasu ISO 8601

Bez strefy czasowej, z mikrosekundami

from datetime import datetime

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

Ze strefą czasową, z mikrosekundami

from datetime import datetime
from dateutil.tz import tzlocal

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

Ze strefą czasową, bez mikrosekund

from datetime import datetime
from dateutil.tz import tzlocal

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

Zobacz ISO 8601, aby uzyskać więcej informacji na temat formatu ISO 8601.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow