Python'da Tarih ve Saat İşlemleri: datetime, strftime ve timedelta
Python'da metni tarihe çevirmeyi, tarihi biçimlendirmeyi ve iki tarih arasındaki farkı hesaplamayı datetime modülüyle öğrenirsiniz; saat dilimi tuzaklarına da değinilir.
Bir bakışta
- Dört tür vardır: date, time, datetime, timedelta. Tarih, saat, ikisi birlikte ve aradaki süre ayrı türlerle ifade edilir.
- strptime metni nesneye, strftime nesneyi metne çevirir. İkisi aynı biçim kodlarını kullanır; biçim metinle birebir uyuşmalıdır.
- İki tarihin farkı timedelta verir. Toplam süre için .seconds değil total_seconds() kullanılır.
- Naive ve aware nesneler karıştırılamaz. Karşılaştırma ve çıkarma TypeError üretir.
- Ay ve yıl eklemek timedelta ile yapılamaz. timedelta gün ve altı birimleri bilir; takvim ayı için ek mantık gerekir.
datetime modülündeki temel türler
Python'da tarih ve saat işleri için standart kütüphanedeki datetime modülü kullanılır. Modülün dört temel türü vardır. date yalnız takvim tarihini (yıl, ay, gün), time yalnız günün saatini, datetime ise ikisini birlikte taşır. timedelta ise iki an arasındaki süreyi, yani farkı ifade eder.
Bu ayrım pratik sonuçlar doğurur. Yalnız gün önemliyse date kullanın, çünkü saat belirsizliği sorun yaratmaz. Saatin de önemli olduğu kayıtlarda (sipariş zamanı, log) datetime kullanın. İki tarih arasındaki gün sayısını, bir son ödeme tarihini ya da bir süreyi hesaplarken timedelta ile çalışırsınız.
Python belgelerine göre date nesneleri her zaman saat dilimi bilgisi taşımayan (naive) nesnelerdir. datetime nesneleri ise saat dilimi bilgisi taşıyabilir ya da taşımayabilir; bu fark, ileride göreceğimiz gibi karşılaştırma hatalarının ana kaynağıdır.
Tarih ve saat verisi çoğu zaman dışarıdan metin olarak gelir: CSV dosyalarından, API yanıtlarından, formlardan. Bu yüzden asıl iş, metni datetime'a çevirmek (ayrıştırmak), üzerinde hesap yapmak ve sonucu yeniden metne dönüştürmektir. Pandas ile tablo halinde tarih işleme ayrı bir konudur; burada yalnız standart datetime modülü ele alınır.
Tarih işi, metinden nesneye ve yeniden metne uzanır
Dönüşüm zinciri
- Ham metinDosyadan veya formdan gelen tarih yazısı.
- datetime nesnesistrptime ile ayrıştırılır, hesaba hazır olur.
- timedelta sonucuFark veya eklenen süre hesaplanır.
- Biçimli metinstrftime ile okura uygun yazıya çevrilir.
Tarih ve saat nesnesi oluşturmak
Şu anki zamanı almanın yolu datetime.now()'dır:
from datetime import datetime, timedelta, timezone
simdi = datetime.now()
Python belgelerine göre argümansız now(), yerel saati saat dilimi bilgisi olmadan (naive) döndürür. Saat dilimi bilgili (aware) bir değer istiyorsanız dilimi verin:
simdi_utc = datetime.now(timezone.utc)
Belirli bir tarih için datetime sınıfının kurucusuna yıl, ay ve gün verilir; ancak veri çoğu zaman metin halinde geldiği için daha sık kullanılan yol ayrıştırmadır. strptime sınıf yöntemi, metni ve onun biçimini alıp datetime nesnesi döndürür:
tarih = datetime.strptime(metin, "%d.%m.%Y")
Burada biçim kodları metnin yapısını tanımlar: %d gün, %m ay, %Y dört haneli yıl. Biçim, metinle birebir uyuşmak zorundadır; ayraç, sıra ve hane sayısı farklıysa ValueError alırsınız. Saatli veri için %H:%M:%S eklenir.
Eski kodlarda datetime.utcnow() görebilirsiniz. Python belgeleri bu yöntemin 3.12 sürümünden itibaren kullanımdan kaldırıldığını belirtir ve yerine datetime.now(timezone.utc) önerir. Yeni kodda bunu tercih edin.
strftime ile biçimlendirmek
strftime, bir tarih ya da datetime nesnesini istediğiniz biçimde metne çevirir. Aynı biçim kodlarını strptime ile paylaşır:
metin = tarih.strftime("%d.%m.%Y %H:%M")
Sık kullanılan kodlar şunlardır:
- %d: ayın günü, iki haneli.
- %m: ay, iki haneli sayı.
- %Y: dört haneli yıl; %y iki haneli yıl.
- %H: saat, yirmi dört saatlik düzen; %M dakika; %S saniye.
- %B ve %A: ayın ve günün adı.
Ay ve gün adları (%B, %A) bilgisayarın yerel ayarına bağlıdır. Türkçe ay adları görmek istiyorsanız yerel ayar (locale) ayarı gerekir, ve bu ayar işletim sistemine göre değişir. Taşınabilir bir çözüm için ay adlarını kendi sözlüğünüzle eşlemek daha güvenilirdir.
Biçimlendirmenin yönü tek yönlüdür: strftime nesneyi metne, strptime metni nesneye çevirir. Günlük kullanımda raporlara yazarken strftime, dışarıdan gelen tarihleri okurken strptime kullanılır. Tarih saklarken ve sistemler arası aktarırken, okunaklı ancak belirsiz yerel biçimler yerine standart ve sıralanabilir bir biçim (yıl-ay-gün sırası) tercih edin; böylece metin olarak sıralandığında da kronolojik sıra bozulmaz.
Tarih farkı ve timedelta
İki date ya da iki datetime nesnesini birbirinden çıkardığınızda sonuç bir timedelta olur:
fark = bitis - baslangic print(fark.days)
Python belgelerine göre timedelta yalnız gün, saniye ve mikrosaniye saklar. İşin tuzağı burada: fark.days tam gün sayısını verir, fark.seconds ise toplam saniye değil, gün sayısından arta kalan saniyedir. Belgeler, toplam süre istenirken .seconds kullanmanın sık yapılan bir hata olduğunu açıkça belirtir. Toplam süreyi saniye olarak istiyorsanız total_seconds() yöntemini kullanın:
toplam = fark.total_seconds()
Negatif farklarda da dikkatli olun. Başlangıç bitişten sonraysa gün sayısı negatif çıkar. timedelta negatif değerleri gün, saniye ve mikrosaniye olarak alışılmadık biçimde normalleştirir, bu nedenle negatif süreyi saat ya da dakikaya çevirirken total_seconds'tan hesaplamak daha güvenlidir.
Gün farkı ve saat farkı ayrı sorulardır. "Kaç gün geçti" için .days yeterlidir; "kaç saat geçti" için total_seconds() değerini saat birimine bölersiniz. İş günü saymak ya da takvim ayı farkı gibi hesaplar timedelta ile doğrudan yapılamaz; bunlar için ek mantık gerekir.
Tarihe süre eklemek ve çıkarmak
timedelta, bir tarihe süre eklemenin standart yoludur:
son_odeme = siparis_tarihi + timedelta(days=gun_sayisi) hatirlatma = son_odeme - timedelta(hours=saat_sayisi)
timedelta, days, seconds, microseconds, milliseconds, minutes, hours ve weeks parametrelerini alır. Ay ve yıl parametresi yoktur, çünkü bunların uzunluğu değişkendir. "Bir ay sonrası" gibi takvim aylarıyla hesap yapmanız gerekiyorsa, standart kütüphane tek başına yeterli değildir; ayın günü sınırlarını (örneğin ayın son günü) kendiniz yönetmeniz ya da bu iş için tasarlanmış bir üçüncü taraf kütüphane kullanmanız gerekir.
Karşılaştırma doğrudan çalışır: iki datetime nesnesini <, > ve == ile karşılaştırabilirsiniz. Bu, bir sürenin dolup dolmadığını kontrol etmenin en okunaklı yoludur:
if datetime.now() > son_odeme: print("Süre doldu")
Yalnız tarih önemliyse nesneyi date'e çevirin: tarih.date(). Saatli ve saatsiz nesneleri birbirine karıştırmak kafa karıştırıcı karşılaştırmalar üretir; her iki taraf da aynı türde olmalıdır. Bir datetime ile bir date doğrudan karşılaştırılamaz.
Saat dilimi: naive ve aware
Python belgelerine göre saat dilimi bilgisi olmayan datetime nesnesi naive, saat dilimi bilgisi olan ise aware olarak adlandırılır. Naive nesnenin anlamı programa bırakılmıştır: "bu saat hangi saat diliminde" sorusunu yalnız siz bilirsiniz. Aware nesne ise belirli bir anı temsil eder.
En önemli kural şudur: naive ve aware nesneleri birbirleriyle karşılaştıramaz ya da birbirinden çıkaramazsınız; belgeler bu işlemlerin TypeError verdiğini belirtir. Eşitlik denetimi hata vermez ama her zaman False döner, bu da sessiz bir mantık hatasına yol açabilir.
İki türü dönüştürmenin farklı yöntemleri vardır. replace(tzinfo=...) saat değerini değiştirmeden dilim bilgisi ekler ya da kaldırır, yani anı kaydırmaz. astimezone(...) ise aynı anı başka bir dilimde gösterir. Hangisinin gerektiğini bilmeden kullanmak, saatleri kaydırmanın en kolay yoludur.
Pratik kural: sunucularda ve veri tabanlarında zamanı standart bir dilimde (genellikle UTC) saklayın ve yalnız kullanıcıya gösterirken yerel dilime çevirin. Kodunuzda naive ve aware nesneleri karıştırmayın; bir projede tek yaklaşımı seçip tutarlı kullanın. Yaz saati uygulaması gibi ayrıntılar için standart kütüphanenin zoneinfo modülüne bakabilirsiniz.
Sık yapılan hatalar
İlk hata, .seconds ile toplam süreyi hesaplamaktır; doğru yöntem total_seconds()'dır. İkinci hata, strptime biçiminin metinle uyuşmamasıdır: ayraç, sıra ya da hane farkı ValueError üretir. Üçüncü hata, %m (ay) ile %M (dakika) kodlarını karıştırmaktır; büyük-küçük harf anlam değiştirir.
Dördüncü hata, naive ve aware nesneleri karşılaştırmaktır. Beşinci hata, Türkçe ay adlarının her ortamda çalışacağını varsaymaktır; yerel ayar bağımlıdır. Altıncı hata, tarihi metin olarak saklayıp metin olarak karşılaştırmaktır: gün-ay-yıl sırasındaki metin kronolojik sıralanmaz.
Yedinci hata, takvim ayı eklemeyi timedelta ile yapmaya çalışmaktır. Son olarak, sistem saatine bağımlı kodu test etmeyi unutmayın: datetime.now() çağıran bir işlev her çalıştığında farklı sonuç verir; testlerde şu anki zamanı fonksiyona parametre olarak geçmek, davranışı tekrarlanabilir kılar.
Bu hataların bir kısmı küçük bir deneme betiği ile hızla yakalanır. Bir tarih biçimi yazdıktan sonra birkaç örnek metinle hem ayrıştırın hem de yeniden biçimlendirin; sonucun girdiyle uyuştuğunu görmeden kodu kullanmayın.
Bu beceriyi Mindset programlarında nerede çalışırsınız
Python programlama programlarındaki modüller ve paketler bölümü, standart kütüphane modüllerinin kullanımını uygulamalı olarak işler. Veri bilimi yolunda ise zaman damgalı verilerle çalışmak, log analizi, sipariş ve oturum verisi gibi alanlarda temel bir beceridir.
İlgili Mindset programı
Data Science Bootcamp
Sık sorulan sorular
strftime ile strptime arasındaki fark nedir?
strftime bir tarih nesnesini istediğiniz biçimde metne çevirir. strptime ise tersini yapar: belirtilen biçime göre bir metni datetime nesnesine ayrıştırır. İkisi aynı biçim kodlarını kullanır. Raporlarda strftime, dışarıdan gelen tarihlerde strptime tercih edilir.
İki tarih arasındaki gün farkını nasıl hesaplarım?
İki date ya da datetime nesnesini birbirinden çıkarın; sonuç bir timedelta olur ve .days özelliği tam gün sayısını verir. Saat farkı da önemliyse total_seconds() değerini saniyeden saate çevirin. .seconds toplam süre değil, gün dışında kalan saniyedir.
Python'da bir tarihe ay eklemek mümkün mü?
timedelta ay ve yıl birimlerini bilmez, çünkü uzunlukları değişkendir. Standart kütüphanede ay eklemek için ayın gün sınırlarını kendiniz yönetmeniz gerekir; bunu kolaylaştıran üçüncü taraf kütüphaneler de vardır. Gün, hafta ve saat eklemek ise timedelta ile doğrudan yapılır.
Naive ve aware datetime ne demek, neden önemli?
Naive nesne saat dilimi bilgisi taşımaz, aware nesne taşır. Python belgelerine göre ikisini karşılaştırmak ya da birbirinden çıkarmak TypeError verir. Kodda tutarlı kalın: sunucuda UTC gibi standart bir dilimde saklayıp yalnız gösterirken yerel dilime çevirin.
datetime.utcnow() kullanmalı mıyım?
Hayır. Python belgelerine göre utcnow 3.12 sürümünden itibaren kullanımdan kaldırıldı ve yerine datetime.now(timezone.utc) önerildi. Bu çağrı saat dilimi bilgili bir nesne döndürür ve naive-aware karışıklığını önlemeye yardımcı olur.