koddla

Yazılımcıları bilgi ile güçlendirir.

Python Tarih ve Zaman

Python, tarih ve saatlerin oluşturulması, değiştirilmesi, ayrıştırılması ve manipüle edilmesi için hem yerleşik yöntemler hem de harici kütüphaneler sağlar.

Temel datetime nesneleri kullanımı

Datetime modülü üç ana nesne türü içerir: tarih, saat ve datetime.

import datetime

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

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

# şimdiki zaman - datetime
now = datetime.datetime.now()

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

Bu nesneler için aritmetik işlemler yalnızca aynı veri türü içinde desteklenir ve farklı türlerdeki örneklerle basit aritmetik işlemler gerçekleştirmek bir TypeError ile sonuçlanır.

# öğlenin bugünden çıkarılması
noon-today
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for -: 'datetime.time' and 'datetime.date'
Ancak, türler arasında dönüştürme yapmak kolaydır.

# Bunun yerine şunu yapın
print('Gece yarısı milenyumdan bu yana geçen zaman: ',
      datetime.datetime(today.year, today.month, today.day) - millenium_turn)

# Ya da bunu.
print('Gece yarısı milenyumdan bu yana geçen zaman: ',
      datetime.datetime.combine(today, noon) - millenium_turn)

Tarihler üzerinde yineleme

Bazen bir başlangıç tarihinden bir bitiş tarihine kadar bir tarih aralığı üzerinde yineleme yapmak istersiniz. Bunu datetime kütüphanesini ve timedelta nesnesini kullanarak yapabilirsiniz:

import datetime

# Her adımın gün cinsinden büyüklüğü
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)

Bu da şu sonucu üretir:

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

Basit tarih aritmetiği

Tarihler tek başına var olmazlar. Tarihler arasındaki süreyi bulmanız veya tarihin yarın ne olacağını belirlemeniz gerekebilir. Bu, timedelta nesneleri kullanılarak gerçekleştirilebilir

import datetime

today = datetime.date.today()
print('Bugün:', today)

yesterday = today - datetime.timedelta(days=1)
print('Dün:', yesterday)

tomorrow = today + datetime.timedelta(days=1)
print('Yarın:', tomorrow)

print('Yarın ve dün arasındaki fark:', tomorrow - yesterday)

Bu, aşağıdakine benzer sonuçlar üretecektir:

Bugün 2016-04-15
Dün: 2016-04-14
Yarın: 2016-04-16
Yarın ile dün arasındaki fark: 2 gün, 0:00:00

Zaman farklarının hesaplanması

timedelta modülü zamanlar arasındaki farkları hesaplamak için kullanışlıdır:

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

Yeni bir datetime nesnesi oluştururken zaman belirtmek isteğe bağlıdır

delta = simdi-once

delta timedelta türündedir

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

n gün sonraki ve n gün önceki tarihi elde etmek

n gün sonraki tarih:

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 gün önceki tarih:

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)

Bir tarihten ayları doğru bir şekilde çıkarma

calendar modülünü kullanma

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)

dateutils modülünü kullanma:

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)

Zaman dilimine duyarlı veri zamanları oluşturma

Varsayılan olarak tüm datetime nesneleri naiftir. Bunları zaman dilimine duyarlı hale getirmek için, tarih ve saatin bir fonksiyonu olarak UTC ofsetini ve zaman dilimi kısaltmasını sağlayan bir tzinfo nesnesi eklemeniz gerekir.

Sabit Ofset Zaman Dilimleri

UTC’den sabit bir uzaklığa sahip zaman dilimleri için, Python 3.2+’da datetime modülü, bir timedelta ve (isteğe bağlı) bir ad parametresi alan tzinfo’nun somut bir uygulaması olan timezone sınıfını sağlar:

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'

Python’un 3.2’den önceki sürümleri için, dateutil gibi üçüncü parti bir kütüphane kullanmak gerekir. dateutil, (2.5.3 sürümünden itibaren) dateutil.tz.tzoffset(tzname, offset) biçiminde argümanlar alan eşdeğer bir sınıf olan tzoffset’i sağlar; burada offset saniye cinsinden belirtilir:

from datetime import datetime, timedelta
from dateutil import tz

JST = tz.tzoffset('JST', 9 * 3600) # saat için 3600 saniye
dt = datetime(2015, 1, 1, 12, 0, tzinfo=JST)
print(dt)
# 2015-01-01 12:00:00+09:00
print(dt.tzname)
# 'JST'

Yaz saati uygulaması olan bölgeler

Yaz saati uygulamasına sahip bölgeler için python standart kütüphaneleri standart bir sınıf sağlamaz, bu nedenle üçüncü taraf bir kütüphane kullanmak gerekir. pytz ve dateutil, saat dilimi sınıfları sağlayan popüler kütüphanelerdir. 

Statik zaman dilimlerine ek olarak, dateutil yaz saati uygulamasını kullanan zaman dilimi sınıfları sağlar (tz modülünün belgelerine bakın). Bir zaman dilimi nesnesi almak için tz.gettz() yöntemini kullanabilirsiniz; bu nesne daha sonra doğrudan datetime kurucusuna aktarılabilir:

from datetime import datetime
from dateutil import tz
local = tz.gettz() # yerel saat
PT = tz.gettz('US/Pacific') # Pacific saati

dt_l = datetime(2015, 1, 1, 12, tzinfo=local) # EST
dt_pst = datetime(2015, 1, 1, 12, tzinfo=PT)
dt_pdt = datetime(2015, 7, 1, 12, tzinfo=PT) # DST otomatik düzenlenir
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

DİKKAT: 2.5.3 sürümünden itibaren, dateutil belirsiz tarih zamanlarını doğru bir şekilde ele almaz ve her zaman daha sonraki tarihi varsayar. Örneğin 2015-11-01 1:30 EDT-4 gibi bir dateutil zaman dilimini temsil eden bir nesne oluşturmanın bir yolu yoktur, çünkü bu bir yaz saati uygulaması geçişi sırasındadır.

Tüm uç durumlar pytz kullanılırken düzgün bir şekilde ele alınır, ancak pytz zaman dilimleri zaman dilimlerine kurucu aracılığıyla doğrudan eklenmemelidir. Bunun yerine, bir pytz zaman dilimi, zaman diliminin localize yöntemi kullanılarak eklenmelidir:

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

Eğer pytz farkındalı bir zaman diliminde datetime aritmetiği yaparsanız, hesaplamaları ya UTC’de yapmalısınız (eğer mutlak geçen zaman istiyorsanız), ya da sonuç üzerinde normalize() çağırmalısınız:

dt_new = dt_pdt + timedelta(hours=3) # 2:30 AM PST olmalı
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

Saat dilimleri arasında geçiş yapma

Zaman dilimleri arasında geçiş yapmak için zaman dilimi farkındalığı olan datetime nesnelerine ihtiyacınız vardır.

from datetime import datetime
from dateutil import tz

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

utc_now = datetime.utcnow()
utc_now # Zaman dilimine duyarlı değil.

utc_now = utc_now.replace(tzinfo=utc)
utc_now # Zaman dilimine duyarlı.

local_now = utc_now.astimezone(local)
local_now # Yerel saate dönüştürüldü.

Bir dizeyi zaman dilimine duyarlı bir datetime nesnesine ayrıştırma

Python 3.2+, bir dizeyi tarih-saat nesnesine ayrıştırırken %z biçimi için desteğe sahiptir.

HHMM veya -HHMM biçiminde UTC ofseti (nesne naifse boş dize).

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

Python’un diğer sürümleri için, dateutil gibi harici bir kütüphane kullanabilirsiniz, bu da zaman dilimi içeren bir dizeyi bir datetime nesnesine ayrıştırmayı hızlı hale getirir.

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

dt değişkeni artık aşağıdaki değere sahip bir datetime nesnesidir:

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

Kısa bir zaman dilimi adı içeren bir dizeyi zaman dilimine duyarlı bir datetime nesnesine ayrıştırma

Zaman dilimine duyarlı zaman damgalarının ayrıştırılmasıyla ilgili önceki örneklerde olduğu gibi dateutil kütüphanesini kullanarak, zaman damgalarını belirtilen “kısa” bir zaman dilimi adıyla ayrıştırmak da mümkündür.

Genellikle belirsiz olan kısa saat dilimi adları veya kısaltmalarıyla biçimlendirilmiş tarihler için (örneğin, Merkezi Standart Saat, Çin Standart Saati, Küba Standart Saati vb. olabilen CST ve diğerleri..) veya standart bir veritabanında bulunması gerekmeyen tarihler için, saat dilimi kısaltması ile tzinfo nesnesi arasında bir eşleme belirtmek gerekir.

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)

Bunu çalıştırdıktan sonra:

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

Bu yöntemle bir pytz zaman dilimi kullanılıyorsa, bunun düzgün bir şekilde yerelleştirilmeyeceğini belirtmek gerekir:

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

Bu basitçe pytz zaman dilimini datetime’a ekler:

dt.tzinfo # Yerel Saat'te olacak!
# <DstTzInfo 'America/New_York' LMT-1 day, 19:04:00 STD>

Bu yöntemi kullanıyorsanız, ayrıştırma işleminden sonra muhtemelen tarih saatinin naif kısmını yeniden yerelleştirmelisiniz:

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

Zaman damgasını tarih saatine dönüştürme

datetime modülü, bir POSIX zaman damgasını bir ITC datetime nesnesine dönüştürebilir.

Dönem 1 Ocak 1970 gece yarısıdır.

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)

Bir metinden tarih saati değeri çıkarma

dateutil ayrıştırıcısını ” fuzzy” modunda kullanarak bir metinden tarih çıkarmak mümkündür; burada dizenin tarihin bir parçası olarak tanınmayan bileşenleri göz ardı edilir.

from dateutil.parser import parse

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

dt artık bir datetime nesnesidir ve datetime.datetime(2047, 1, 1, 8, 21) yazdırıldığını görürsünüz.

Rastgele bir ISO 8601 zaman damgasını ayrıştırma

Python, ISO 8601 zaman damgalarını ayrıştırmak için yalnızca sınırlı bir desteğe sahiptir. Strptime için tam olarak hangi formatta olduğunu bilmeniz gerekir. Bir komplikasyon olarak, bir tarih saatinin dizilimi, ayırıcı olarak boşluk ve 6 basamaklı kesir ile bir ISO 8601 zaman damgasıdır:

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

ancak kesir 0 ise, hiçbir kesirli kısım çıktılanmaz

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

Ancak bu 2 biçim strptime için farklı bir biçime ihtiyaç duyar. Ayrıca, strptime’ içinde iki nokta üstüste (:) olan dakika zaman dilimlerinin ayrıştırılmasını desteklemez, bu nedenle 2016-07-22 09:25:59+0300 ayrıştırılabilir, ancak standart format 2016-07-22 09:25:59+03:00 ayrıştırılamaz.

ISO 8601 zaman damgalarını ve sadece onları düzgün bir şekilde ayrıştıran iso8601 adında tek dosyalık bir kütüphane vardır.

Kesirleri, saat dilimlerini ve T ayırıcısını tek bir işlevle destekler:

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

Herhangi bir zaman dilimi ayarlanmamışsa, iso8601.parse_date varsayılan olarak UTC’dir. Varsayılan bölge default_zone anahtar kelime argümanı ile değiştirilebilir. Özellikle, bu varsayılan yerine None ise, açık bir zaman dilimine sahip olmayan zaman damgaları bunun yerine naive datetimes olarak döndürülür:

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

ISO 8601 zaman damgası alma

Zaman dilimi olmadan, mikrosaniyelerle 

from datetime import datetime

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

Zaman dilimiyle, mikrosaniyelerle 

from datetime import datetime
from dateutil.tz import tzlocal

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

Zaman dilimi ile, mikrosaniye olmadan 

from datetime import datetime
from dateutil.tz import tzlocal

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

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Back to top