Zoeken…


Opmerkingen

Python biedt zowel ingebouwde methoden als externe bibliotheken voor het maken, wijzigen, parseren en manipuleren van datums en tijden.

Een tekenreeks parseren in een tijdzone-bewust datetime-object

Python 3.2+ biedt ondersteuning voor %z indeling bij het parseren van een string in een datetime object.

UTC-offset in de vorm +HHMM -HHMM of -HHMM (lege tekenreeks als het object naïef is).

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

Voor andere versies van Python kunt u een externe bibliotheek gebruiken, zoals dateutil , waardoor een string met tijdzone snel in een datetime object kan worden dateutil .

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

De variabele dt is nu een datetime object met de volgende waarde:

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

Eenvoudige rekenkundige datum

Datums staan niet op zichzelf. Het is gebruikelijk dat u de hoeveelheid tijd tussen datums moet vinden of moet bepalen wat de datum morgen zal zijn. Dit kan worden bereikt met behulp van timedelta objecten

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)

Dit levert resultaten op die vergelijkbaar zijn met:

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

Basis datetime objecten gebruik

De datetime-module bevat drie primaire typen objecten: datum, tijd en datetime.

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)

Rekenkundige bewerkingen voor deze objecten worden alleen ondersteund binnen hetzelfde gegevenstype en het uitvoeren van eenvoudige rekenkundige bewerkingen met instanties van verschillende typen resulteert in een 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)

Herhaal over datums

Soms wilt u herhalen over een datumbereik vanaf een startdatum tot een einddatum. U kunt dit doen met behulp van de datetime bibliotheek en het timedelta object:

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)

Welke produceert:

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

Een string met een korte tijdzonenaam in een tijdzone-bewust datetime-object verwerken

Met behulp van de dateutil bibliotheek zoals in het vorige voorbeeld voor het parsen van tijdzone-bewuste tijdstempels , is het ook mogelijk om tijdstempels te parseren met een opgegeven "korte" tijdzonenaam.

Voor data geformatteerd met korte tijdzone namen of afkortingen, die over het algemeen zijn dubbelzinnig (zoals CST, die zouden kunnen worden Central Standard Time, China Standard Time, Cuba Standard Time, etc - meer kan worden gevonden hier ) noodzakelijkerwijs beschikbaar in een standaard database of niet , is het noodzakelijk om een toewijzing tussen tijdzone-afkorting en tzinfo object op te geven.

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)

Na het uitvoeren van dit:

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

Het is vermeldenswaard dat als een pytz tijdzone met deze methode wordt gebruikt, deze niet correct zal worden gelokaliseerd:

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

Dit bevestigt eenvoudig de pytz tijdzone aan de datetime:

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

Als u deze methode gebruikt, moet u na het parseren waarschijnlijk het naïeve gedeelte van de datetime opnieuw localize :

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

Tijdzone-bewuste datetijden construeren

Standaard zijn alle datetime objecten naïef. Om ze tijdzone-bewust te maken, moet u een tzinfo object toevoegen, dat de UTC-offset en tijdzone-afkorting als functie van datum en tijd levert.

Vaste offset-tijdzones

Voor tijdzones die een vaste offset zijn van UTC, in Python 3.2+, biedt de datetime module de timezone , een concrete implementatie van tzinfo , waarvoor een timedelta en een (optionele) tzinfo nodig zijn:

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'

Voor Python-versies vóór 3.2 is het noodzakelijk om een externe bibliotheek te gebruiken, zoals dateutil . dateutil biedt een equivalente klasse, tzoffset , die (vanaf versie 2.5.3) argumenten van de vorm dateutil.tz.tzoffset(tzname, offset) , waarbij offset in seconden wordt opgegeven:

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'

Zones met zomertijd

Voor zones met zomertijd bieden standaardbibliotheken van Python geen standaardklasse, dus is het noodzakelijk om een externe bibliotheek te gebruiken. pytz en dateutil zijn populaire bibliotheken die tijdzoneklassen bieden.

Naast statische tijdzones biedt dateutil tijdzoneklassen die gebruik maken van zomertijd (zie de documentatie voor de tz module ). U kunt de methode tz.gettz() gebruiken om een tijdzoneobject op te halen, dat vervolgens rechtstreeks aan de datetime constructor kan worden doorgegeven:

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

VOORZICHTIG : vanaf versie 2.5.3 kan dateutil dubbelzinnige dateutil niet correct verwerken en zal altijd standaard de latere datum gebruiken. Er is geen manier om een object te construeren met een dateutil tijdzone die bijvoorbeeld 2015-11-01 1:30 EDT-4 , omdat dit tijdens een zomertijdovergang is.

Alle pytz worden correct behandeld bij het gebruik van pytz , maar pytz tijdzones moeten niet rechtstreeks aan tijdzones worden bevestigd via de constructor. In plaats daarvan moet een pytz tijdzone worden gekoppeld met behulp van de localize van de tijdzone:

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

Houd er rekening mee dat als u datetime-rekenkunde uitvoert op een pytz bewuste tijdzone, u de berekeningen in UTC moet uitvoeren (als u absoluut verstreken tijd wilt), of u normalize() moet aanroepen op het resultaat:

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

Fuzzy datetime parsing (extraheren van datetime uit een tekst)

Het is mogelijk om een datum uit een tekst te extraheren met behulp van de dateutil parser in een "fuzzy" -modus, waarbij componenten van de tekenreeks die niet worden herkend als onderdeel van een datum worden genegeerd.

from dateutil.parser import parse

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

dt is nu een datetime object en u zou datetime.datetime(2047, 1, 1, 8, 21) afdrukken.

Schakelen tussen tijdzones

Als u tussen tijdzones wilt schakelen, hebt u datetime-objecten nodig die zich bewust zijn van de tijdzone.

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.

Een willekeurige ISO 8601-tijdstempel parseren met minimale bibliotheken

Python biedt slechts beperkte ondersteuning voor het parseren van ISO 8601-tijdstempels. Voor strptime moet je precies weten in welk formaat het is. Als complicatie is de stringificatie van een datetime een ISO 8601-tijdstempel, met spatie als scheidingsteken en een breuk van 6 cijfers:

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

maar als de fractie 0 is, wordt er geen fractioneel gedeelte uitgevoerd

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

Maar deze 2 formulieren hebben een ander formaat nodig voor strptime . Verder 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` kan niet.

Er is een bibliotheek met één bestand genaamd iso8601 die de ISO 8601-tijdstempels correct iso8601 en alleen deze.

Het ondersteunt breuken en tijdzones, en het T scheidingsteken allemaal met een enkele functie:

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

Als er geen tijdzone is ingesteld, wordt iso8601.parse_date standaard ingesteld op UTC. De standaardzone kan worden gewijzigd met het argument default_zone keyword. Met name, als dit None plaats van de standaard, worden die tijdstempels die geen expliciete tijdzone hebben in plaats daarvan als naïeve datetijden geretourneerd:

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

Tijdstempel converteren naar datetime

De datetime module kan een POSIX- timestamp omzetten in een ITC- datetime object.

Het tijdvak is 1 januari 1970 om middernacht.

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)

Maanden nauwkeurig van een datum aftrekken

Gebruik van de 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)

Gebruik van de dateutils module

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)

Rekentijdverschillen

de timedelta module is handig om verschillen tussen tijden te berekenen:

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

Tijd opgeven is optioneel bij het maken van een nieuw datetime object

delta = now-then

delta is van het type timedelta

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

Om n dag na en n dag vóór datum te krijgen, kunnen we gebruiken:

n dag na datum:

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 dag vóór datum:

 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)

Ontvang een ISO 8601-tijdstempel

Zonder tijdzone, met microseconden

from datetime import datetime

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

Met tijdzone, met microseconden

from datetime import datetime
from dateutil.tz import tzlocal

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

Met tijdzone, zonder microseconden

from datetime import datetime
from dateutil.tz import tzlocal

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

Zie ISO 8601 voor meer informatie over het ISO 8601-formaat.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow