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'