Sök…


Anmärkningar

Python tillhandahåller både inbyggda metoder och externa bibliotek för att skapa, ändra, analysera och manipulera datum och tider.

Parsar en sträng i ett tidszonsmedvetet datatobjekt

Python 3.2+ har stöd för %z format vid parsning av en sträng i ett datetime objekt.

UTC-offset i formen +HHMM eller -HHMM (tom sträng om objektet är naivt).

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

För andra versioner av Python kan du använda ett externt bibliotek som dateutil , vilket gör att parsning av en sträng med tidszon till ett datetime objekt är snabb.

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

dt variabeln är nu ett datetime objekt med följande värde:

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

Enkel datum aritmetik

Datum existerar inte isolerat. Det är vanligt att du måste hitta tiden mellan datum eller bestämma vad som kommer att bli imorgon. Detta kan uppnås med hjälp av timedelta objekt

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)

Detta ger resultat som liknar:

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

Grundläggande användning av datetime-objekt

Datetime-modulen innehåller tre primära typer av objekt - datum, tid och 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)

Aritmetiska operationer för dessa objekt stöds endast inom samma datatyp och att utföra enkel aritmetik med instanser av olika typer kommer att resultera i en 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)

Iterera över datum

Ibland vill du upprepa flera datum från ett startdatum till ett slutdatum. Du kan göra det med datetime bibliotek och timedelta objekt:

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)

Som producerar:

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

Parsar en sträng med ett kort tidszonnamn i ett tidszonsmedvetet datitobjekt

Med hjälp av dateutil biblioteket som i föregående exempel för att analysera tidszonmedvetna tidsstämplar är det också möjligt att analysera tidsstämplar med ett angivet "kort" tidszonnamn.

För datum formaterade med korta tidszonnamn eller förkortningar, som i allmänhet är tvetydiga (t.ex. CST, som kan vara Central Standard Time, China Standard Time, Cuba Standard Time, etc. - mer kan hittas här ) eller inte nödvändigtvis tillgänglig i en standarddatabas , är det nödvändigt att ange en kartläggning mellan tzinfo och tzinfo objekt.

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)

Efter att ha kört detta:

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

Det är värt att notera att om du använder en pytz tidszon med den här metoden, kommer den inte att vara korrekt lokaliserad:

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

Detta fäster helt enkelt pytz till datatiden:

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

Om du använder den här metoden, bör du nog åter localize den naiva delen av datetime efter tolkning:

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

Konstruera tidszonmedvetna datatider

Som standard är alla datetime objekt naiva. För att göra dem tidszonmedvetna måste du bifoga ett tzinfo objekt som ger UTC-offset och tidszonförkortning som en funktion av datum och tid.

Fasta förskjutningstidszoner

För tidszoner som är en fast förskjutning från UTC, i Python 3.2+, datetime modulen timezone , en konkret implementering av tzinfo , som tar en timedelta och en (valfritt) namnparameter:

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'

För Python-versioner före 3.2 är det nödvändigt att använda ett tredjepartsbibliotek, till exempel dateutil . dateutil tillhandahåller en motsvarande klass, tzoffset , som (från version 2.5.3) tar argument för formen dateutil.tz.tzoffset(tzname, offset) , där offset anges i sekunder:

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'

Zoner med sommartid

För zoner med sommartid ger inte Python-standardbibliotek en standardklass, så det är nödvändigt att använda ett tredjepartsbibliotek. pytz och dateutil är populära bibliotek som erbjuder tidszonklasser.

Förutom statiska tidszoner tillhandahåller dateutil som använder sommartid (se dokumentationen för tz modulen ). Du kan använda tz.gettz() för att få ett tidszonobjekt som sedan kan skickas direkt till 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

FÖRSIKTIGHET : Från version 2.5.3 hanterar dateutil inte tvetydiga datatider korrekt och kommer alltid att vara det senare datumet. Det finns inget sätt att konstruera ett objekt med en dateutil tidszon som representerar, till exempel 2015-11-01 1:30 EDT-4 , eftersom det är under en sommartidövergång.

Alla kanter behandlas korrekt när du använder pytz , men pytz tidszoner bör inte fästas direkt på tidzonerna genom konstruktören. Istället pytz en pytz tidszon bifogas med hjälp av pytz localize :

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

Var medveten om att om du utför datitidens aritmetik på en pytz varnings-tidszon måste du antingen utföra beräkningarna i UTC (om du vill ha absolut förfluten tid), eller så måste du ringa normalize() på resultatet:

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 (extrahera datetime ur en text)

Det är möjligt att extrahera ett datum ur en text med hjälp av dateutil i ett "fuzzy" -läge, där komponenter i strängen som inte erkänns som en del av ett datum ignoreras.

from dateutil.parser import parse

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

dt är nu ett datetime objekt och du skulle se datetime.datetime(2047, 1, 1, 8, 21) tryckt.

Växla mellan tidszoner

För att växla mellan tidszoner behöver du datatidsobjekt som är tidszonsmedvetna.

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.

Analysera en godtycklig ISO 8601-tidsstämpel med minimala bibliotek

Python har endast begränsat stöd för att analysera ISO 8601-tidsstämplar. För strptime måste du veta exakt vilket format det är i. Som en komplikation är strängningen av en datetime en ISO 8601-tidsstämpel, med utrymme som en separator och 6-siffrig bråk:

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

men om fraktionen är 0, matas ingen fraktionerad del ut

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

Men dessa två former behöver ett annat format för strptime . Dessutom 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 inte.

Det finns ett bibliotek med en fil som heter iso8601 som korrekt analyserar ISO 8601-tidsstämplar och bara dem.

Den stöder fraktioner och tidszoner och T separatorn alla med en enda funktion:

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

Om ingen tidszon är inställd, är iso8601.parse_date standard för UTC. Standardzonen kan ändras med default_zone . Om detta är None istället för standard, kommer de tidsstämplar som inte har en tydlig tidszon att returneras som naiva datatider istället:

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

Konvertera tidsstämpel till datetime

datetime modulen kan konvertera en POSIX- timestamp till ett ITC- datetime objekt.

Epokchen är 1 januari 1970 midnatt.

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)

Att dra månader från ett datum exakt

Använda 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)

Med hjälp av dateutils modulen

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)

Beräkna tidsskillnader

timedelta modulen är praktiskt att beräkna skillnader mellan gånger:

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

Att ange tid är valfritt när du skapar ett nytt datetime objekt

delta = now-then

delta är av typen timedelta

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

För att få n dag efter och n dag före datum kunde vi använda:

n dag efter 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 före 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)

Få en ISO 8601-tidsstämpel

Utan tidszon, med mikrosekunder

from datetime import datetime

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

Med tidszon, med mikrosekunder

from datetime import datetime
from dateutil.tz import tzlocal

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

Med tidszon, utan mikrosekunder

from datetime import datetime
from dateutil.tz import tzlocal

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

Se ISO 8601 för mer information om ISO 8601-formatet.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow