Go'da tarih ve saat işlemleri time paketiyle yapılır. Şu anki zamanı time.Now(), belirli bir anı time.Date(...) verir; süreler time.Duration tipindedir. Biçimlendirme ve ayrıştırmada Go, YYYY-MM-DD gibi kodlar yerine bir referans zaman kullanır: Mon Jan 2 15:04:05 MST 2006. İstediğiniz biçimi bu tarihin o biçimde nasıl görüneceğini yazarak tarif edersiniz; örneğin t.Format("02.01.2006 15:04") Türkiye'de alışık olunan gün.ay.yıl biçimini üretir.
Bu yazıda referans zaman düzenini, hazır biçim sabitlerini, Parse ile ParseInLocation farkını, saat dilimlerini, Duration aritmetiğini, AddDate normalleştirmesini, zamanları karşılaştırmanın doğru yolunu ve monotonik saati Go 1.27.3 ile çalıştırılmış örneklerle anlatıyoruz. Örneklerde sabit tarihler kullandık; böylece çıktılar her çalıştırmada aynıdır. time.Timer, time.Ticker ve zaman aşımı desenleri select ve zaman aşımı yazısında, dizinin tamamı Go öğrenme rehberinde yer alıyor.
Time değeri: an, konum ve sıfır değer
time.Time nanosaniye hassasiyetinde bir anı temsil eder ve her zaman bir konuma (*time.Location) bağlıdır. Belge, zamanların işaretçi olarak değil değer olarak saklanmasını ve aktarılmasını önerir: struct alanları *time.Time değil time.Time olmalıdır. Sıfır değer 1 Ocak 1. yıl, 00:00:00 UTC'dir; bir zamanın hiç atanıp atanmadığını IsZero ile anlarsınız. Local, UTC ve In metotları zamanın konumunu değiştirir ama temsil ettiği anı değiştirmez; yalnızca hangi saat diliminde gösterileceğini belirler.
time.Date(yıl, ay, gün, saat, dakika, saniye, nanosaniye, konum) belirli bir an oluşturur. Ay, gün, saat gibi değerler normal aralıklarının dışında olabilir ve dönüşüm sırasında normalleştirilir: belgedeki örneğe göre 32 Ekim, 1 Kasım olur. Konum nil verilirse Date panik üretir; konum olarak genellikle time.UTC, time.Local ya da LoadLocation ile yüklenmiş bir bölge kullanılır.
Referans zaman ile biçimlendirme

Go biçim dizelerinde her bileşen referans zamanın o bileşenine karşılık gelen değerle yazılır. Referans zaman 2 Ocak 2006, 15:04:05, UTC'nin 7 saat batısındaki bir saat dilimidir; sayısal sırayla yazıldığında 01/02 03:04:05PM '06 -0700 olur. Belge bu tarihin ayı günden önce yazan Amerikan geleneğini izlemesini "tarihî bir hata" olarak niteler, ama sırayı akılda tutmak kolaydır: ay 1, gün 2, saat 3 (15), dakika 4, saniye 5, yıl 6, saat dilimi 7. Tanınan bileşenler şunlardır:
| Bileşen | Düzen öğeleri | Örnek çıktı |
|---|---|---|
| Yıl | 2006, 06 | 2026, 26 |
| Ay | January, Jan, 01, 1 | November, Nov, 11, 11 |
| Gün | 02, 2, _2 | 07, 7, " 7" |
| Haftanın günü | Monday, Mon | Saturday, Sat |
| Yılın günü | 002, __2 | 311 |
| Saat | 15, 03, 3 | 14, 02, 2 |
| Dakika, saniye | 04, 4 ve 05, 5 | 05, 5 ve 09, 9 |
| ÖÖ/ÖS işareti | PM | PM |
| Saniye kesri | .000 veya .999 | .123 |
| Saat dilimi | MST, -0700, -07:00, Z07:00 | UTC, +0000, +00:00, Z |
Düzende tanınmayan her metin çıktıya olduğu gibi kopyalanır. Nokta veya virgülden sonra gelen sıfırlar o kadar basamaklı saniye kesrini, dokuzlar ise sondaki sıfırları atılmış kesri ifade eder. Ay ve gün adları İngilizce üretilir (aşağıdaki örnekte November ve Saturday); düzen öğeleri arasında Türkçe adlar yoktur, Türkçe ay adları gerekiyorsa kendi eşleme tablonuzu kullanmanız gerekir. Sık kullanılan düzenler için paket sabitler tanımlar; Go 1.20 sürüm notları bunlara DateTime, DateOnly ve TimeOnly sabitlerini ekledi.
package main
import (
"fmt"
"time"
)
func main() {
t := time.Date(2026, time.November, 7, 14, 5, 9, 123456789, time.UTC)
fmt.Println(t)
fmt.Println(t.Format(time.RFC3339))
fmt.Println(t.Format(time.RFC3339Nano))
fmt.Println(t.Format(time.DateTime))
fmt.Println(t.Format(time.DateOnly), t.Format(time.TimeOnly))
fmt.Println(t.Format("02.01.2006 15:04"))
fmt.Println(t.Format("2 January 2006, Monday 3:04PM"))
fmt.Println(t.Format("15:04:05.000"))
yil, hafta := t.ISOWeek()
fmt.Println(t.Weekday(), t.YearDay(), yil, hafta)
}
// Çıktı:
// 2026-11-07 14:05:09.123456789 +0000 UTC
// 2026-11-07T14:05:09Z
// 2026-11-07T14:05:09.123456789Z
// 2026-11-07 14:05:09
// 2026-11-07 14:05:09
// 07.11.2026 14:05
// 7 November 2026, Saturday 2:05PM
// 14:05:09.123
// Saturday 311 2026 45RFC3339 düzeni saniye kesrini yazmaz, RFC3339Nano ise yazar ama belgeye göre sondaki sıfırları attığı için biçimlendirilmiş metinler doğru sıralanmayabilir. Yeni protokoller için belge RFC3339 düzenini önerir. ISOWeek, ISO 8601 yılını ve hafta numarasını verir; yılın ilk ve son günleri bir önceki veya sonraki yılın haftasına düşebilir. fmt.Println(t) ise String metodunu kullanır ve hata ayıklamaya uygun, sabit bir biçim üretir.
Parse ve ParseInLocation: metinden zamana

time.Parse(düzen, metin) aynı referans zaman düzeniyle metni ayrıştırır. Belgede dikkat edilmesi gereken üç kural var. Birincisi, metinde saat dilimi bilgisi yoksa sonuç UTC kabul edilir. İkincisi, düzende olmayan bileşenler sıfır (sıfır olamıyorsa bir) kabul edilir. Üçüncüsü, metin -0700 gibi bir fark içeriyorsa ve bu fark yerel saat diliminde kullanılan bir farkla eşleşiyorsa Parse yerel konumu kullanır; aksi halde o farka sabitlenmiş yapay bir konum oluşturur. Bu son kural, aynı programın farklı saat dilimine ayarlı sunucularda farklı konum adları yazdırmasına yol açabilir.
ParseInLocation(düzen, metin, konum) iki noktada farklıdır: saat dilimi bilgisi olmayan metni verilen konumda yorumlar ve fark ya da kısaltma eşleştirmesini yerel konum yerine verilen konumla yapar. Kullanıcının "29.10.2026 19:23" diye girdiği bir randevu saatini Türkiye saati olarak yorumlamak için doğru araç budur:
package main
import (
"fmt"
"time"
)
func main() {
t, err := time.Parse("02.01.2006 15:04", "29.10.2026 19:23")
fmt.Println(t, err)
ist, err := time.LoadLocation("Europe/Istanbul")
if err != nil {
fmt.Println("bölge yüklenemedi:", err)
return
}
t2, _ := time.ParseInLocation("02.01.2006 15:04", "29.10.2026 19:23", ist)
fmt.Println(t2)
fmt.Println(t2.UTC())
fmt.Println(t2.Equal(t), t2.Sub(t))
r, err := time.Parse(time.RFC3339, "2026-11-07T10:00:00+03:00")
fmt.Println(r.Format(time.RFC3339), err)
fmt.Println(r.In(time.UTC))
_, err = time.Parse(time.DateOnly, "2026-13-01")
fmt.Println(err)
_, err = time.Parse(time.DateOnly, "07.11.2026")
fmt.Println(err)
tokyo := time.FixedZone("JST", 9*60*60)
fmt.Println(r.In(tokyo))
}
// Çıktı:
// 2026-10-29 19:23:00 +0000 UTC <nil>
// 2026-10-29 19:23:00 +0300 +03
// 2026-10-29 16:23:00 +0000 UTC
// false -3h0m0s
// 2026-11-07T10:00:00+03:00 <nil>
// 2026-11-07 07:00:00 +0000 UTC
// parsing time "2026-13-01": month out of range
// parsing time "07.11.2026" as "2006-01-02": cannot parse "07.11.2026" as "2006"
// 2026-11-07 16:00:00 +0900 JSTAynı metin Parse ile UTC 19:23, ParseInLocation ile İstanbul 19:23 olarak okundu; ikisi farklı anlardır ve aralarında üç saat vardır. Europe/Istanbul bölgesinin kısaltması IANA veritabanında +03 olarak kayıtlı olduğu için çıktıda öyle görünüyor. LoadLocation bu veritabanını sırasıyla ZONEINFO ortam değişkeninde, Unix sistemlerinin standart konumunda, $GOROOT/lib/time/zoneinfo.zip dosyasında ve programa time/tzdata paketi eklenmişse onun içinde arar. time/tzdata paketinin belgesine göre bu paket programın herhangi bir yerinde içe aktarılırsa (genellikle main paketinde import _ "time/tzdata" ile) ve sistemde saat dilimi dosyaları bulunamazsa gömülü kopya kullanılır; bedeli programın yaklaşık 450 KB büyümesidir. Yalnızca sabit bir fark gerekiyorsa time.FixedZone veritabanına ihtiyaç duymaz.
Duration: süreler ve birimleri
time.Duration, iki an arasındaki süreyi nanosaniye cinsinden tutan bir int64 tipidir; belgeye göre bu temsil en uzun süreyi yaklaşık 290 yılla sınırlar. Paket Nanosecond, Microsecond, Millisecond, Second, Minute ve Hour sabitlerini tanımlar. Gün veya daha büyük bir birim bilerek tanımlanmamıştır, çünkü yaz saati geçişlerinde bir gün her zaman 24 saat değildir. Bir tamsayıyı süreye çevirmek için çarparsınız (time.Duration(n) * time.Second), bir süredeki birim sayısını bulmak için bölersiniz.
package main
import (
"fmt"
"time"
)
func main() {
d, err := time.ParseDuration("1h30m45.5s")
fmt.Println(d, err)
fmt.Println(d.Hours(), d.Minutes(), d.Seconds())
fmt.Println(d.Round(time.Minute), d.Truncate(time.Hour))
sure := 90
fmt.Println(time.Duration(sure) * time.Second)
fmt.Println(time.Duration(sure))
fmt.Println(int64(time.Second / time.Millisecond))
fmt.Println(1500*time.Millisecond, 2*time.Hour+15*time.Minute, -3*time.Second)
fmt.Println(time.Duration(0), 999*time.Nanosecond, 1500*time.Microsecond)
_, err = time.ParseDuration("3d")
fmt.Println(err)
}
// Çıktı:
// 1h30m45.5s <nil>
// 1.5126388888888889 90.75833333333334 5445.5
// 1h31m0s 1h0m0s
// 1m30s
// 90ns
// 1000
// 1.5s 2h15m0s -3s
// 0s 999ns 1.5ms
// time: unknown unit "d" in duration "3d"ParseDuration işaretli, kesirli ve birim sonekli sayı dizilerini kabul eder; geçerli birimler "ns", "us" (veya "µs"), "ms", "s", "m" ve "h" olarak belirtilmiştir. "3d" bu yüzden hata verir. time.Duration(90) yazmak 90 saniye değil 90 nanosaniyedir; birim çarpanını unutmak en yaygın süre hatasıdır ve time.Sleep(5) gibi bir çağrının neredeyse hiç beklememesine yol açar. Hours, Minutes ve Seconds sonucu float64 olarak verir; tam sayı birimler için bölme kullanın. Komut satırından süre almak için flag.Duration aynı sözdizimini kullanır.
Zaman aritmetiği ve karşılaştırma
t.Add(d) bir zamana süre ekler, t.Sub(u) iki zaman arasındaki süreyi verir. Süre çıkarmak için ayrı bir metot yoktur; belge t.Add(-d) kullanılmasını söyler. t.AddDate(yıl, ay, gün) ise takvim aritmetiği yapar ve sonucu Date gibi normalleştirir: 31 Ekim'e bir ay eklemek önce 31 Kasım'ı üretir, bu tarih olmadığı için 1 Aralık olur. Belge ayrıca AddDate(0, 0, 1) çağrısının yaz saati geçişi olan konumlarda mutlak zamanda 24 yerine 23 saatlik bir kayma üretebileceğini belirtir.
package main
import (
"fmt"
"time"
)
func main() {
t := time.Date(2026, time.October, 31, 12, 0, 0, 0, time.UTC)
fmt.Println(t.AddDate(0, 1, 0).Format(time.DateOnly))
fmt.Println(t.AddDate(0, 0, 1).Format(time.DateOnly))
fmt.Println(time.Date(2026, time.October, 32, 0, 0, 0, 0, time.UTC).Format(time.DateOnly))
fmt.Println(t.Add(36 * time.Hour))
fmt.Println(t.Add(-90 * time.Minute))
bitis := time.Date(2026, time.December, 31, 23, 59, 0, 0, time.UTC)
kalan := bitis.Sub(t)
fmt.Println(kalan, int(kalan.Hours()/24))
fmt.Println(t.Before(bitis), t.After(bitis), t.Compare(bitis), bitis.Compare(t))
ist := time.FixedZone("TRT", 3*60*60)
ayni := t.In(ist)
fmt.Println(ayni)
fmt.Println(ayni == t, ayni.Equal(t))
var sifir time.Time
fmt.Println(sifir, sifir.IsZero())
fmt.Println(t.Unix(), time.Unix(1793448000, 0).UTC())
fmt.Println(t.Truncate(24*time.Hour), t.Month(), int(t.Month()))
}
// Çıktı:
// 2026-12-01
// 2026-11-01
// 2026-11-01
// 2026-11-02 00:00:00 +0000 UTC
// 2026-10-31 10:30:00 +0000 UTC
// 1475h59m0s 61
// true false -1 1
// 2026-10-31 15:00:00 +0300 TRT
// false true
// 0001-01-01 00:00:00 +0000 UTC true
// 1793448000 2026-10-31 12:00:00 +0000 UTC
// 2026-10-31 00:00:00 +0000 UTC October 10En önemli satır ayni == t sonucudur: iki değer aynı anı gösterdiği halde == false döndü. Belge, == operatörünün yalnızca anı değil konumu ve monotonik saat okumasını da karşılaştırdığını açıkça yazar ve zamanları Equal ile karşılaştırmanızı önerir. Aynı nedenle time.Time değerlerini harita anahtarı olarak kullanmadan önce hepsini aynı konuma (UTC()) getirmeniz ve monotonik okumayı t.Round(0) ile temizlemeniz gerekir. Go 1.20 sürüm notları ile gelen Compare metodu -1, 0 veya +1 döndürür ve slices.SortFunc ile zaman sıralamasında doğrudan kullanılabilir; sıralama fonksiyonları slices ve sort yazısında anlatılıyor.
Unix metodu 1 Ocak 1970 UTC'den bu yana geçen saniyeyi verir ve konumdan bağımsızdır; time.Unix(sn, nsn) tersini yapar. Truncate ve Round ise sıfır zamandan itibaren mutlak süre üzerinde çalışır; belge Truncate(Hour) çağrısının konuma bağlı olarak dakikası sıfır olmayan bir zaman döndürebileceğini not eder. Yerel gün başlangıcını bulmak için time.Date(y, m, d, 0, 0, 0, 0, konum) daha doğru bir yoldur.
Monotonik saat ve süre ölçümü
İşletim sistemleri iki saat sunar: saat senkronizasyonuyla değişebilen "duvar saati" ve değişmeyen "monotonik saat". Belgeye göre time.Now() ikisini birden okur; zamanı göstermek için duvar saati, ölçmek için yani karşılaştırma ve çıkarma işlemlerinde monotonik saat kullanılır. Bu sayede time.Since(baslangic) ölçüm sırasında sistem saati ileri veya geri alınsa bile doğru süreyi verir. AddDate, Round, Truncate, In, Local ve UTC monotonik okumayı sonuçtan siler; Date, Parse ve Unix ile oluşturulan zamanlarda hiç yoktur. Monotonik okuma JSON gibi serileştirilmiş biçimlere de yazılmaz.
package main
import (
"fmt"
"time"
)
func main() {
basla := time.Now()
time.Sleep(20 * time.Millisecond)
gecen := time.Since(basla)
fmt.Println(gecen >= 20*time.Millisecond)
simdi := time.Now()
duz := simdi.Round(0)
fmt.Println(simdi.Equal(duz), simdi == duz)
}
// Çıktı:
// true
// true falsegecen değerinin kendisi her çalıştırmada değişir, bu yüzden örnekte yalnızca en az 20 milisaniye olup olmadığını yazdırdık. Round(0) monotonik okumayı temizlediği için iki değer Equal ile eşit, == ile farklı çıktı. Belge, bilgisayar uyku moduna geçtiğinde bazı sistemlerde monotonik saatin durabileceğini ve bu durumda Sub sonucunun gerçekte geçen süreyi yansıtmayabileceğini de belirtir. Uzun süreli zamanlayıcılar ve zaman aşımları için time.Timer kullanılır; Go 1.23 sürüm notları zamanlayıcı kanallarını tamponsuz yaptı ve Go 1.27 sürüm notları bunu ayarlayan asynctimerchan GODEBUG seçeneğini tamamen kaldırdı.
Sık yapılan hatalar

- Düzende
2006-02-01yazmak. Bu yıl-gün-ay sırasıdır; ISO tarih2006-01-02düzeniyle yazılır. Go 1.20 sürüm notları ilego vetbu düzeni raporlamaya başladı. - Saat için
03yerine15kullanmamak ya da tersini yapmak.0312 saatlik,1524 saatlik gösterimdir. time.Parsesonucunu yerel saat sanmak. Saat dilimi bilgisi olmayan metin UTC olarak okunur; yerel yorum içinParseInLocationkullanın.- Zamanları
==ile karşılaştırmak. Konum veya monotonik okuma farklıysa aynı an false döner;Equalkullanın. time.Duration(n)yazıp birimle çarpmayı unutmak. Sonuç nanosaniyedir.- Bir günü
24 * time.Hourile eklemek. Yaz saati uygulanan bölgelerde takvim günü içinAddDate(0, 0, 1)daha doğrudur. - Struct alanlarında
*time.Timekullanmak. Belge değer olarak saklamayı önerir; boşluk bilgisi içinIsZeroyeterlidir.
Vet uyarısının gerçek çıktısı şöyledir:
package main
import (
"fmt"
"time"
)
func main() {
t := time.Date(2026, time.November, 7, 0, 0, 0, 0, time.UTC)
fmt.Println(t.Format("2006-02-01"))
}main.go:10:24: 2006-02-01 should be 2006-01-02Sık Sorulan Sorular
Go'da tarihi gün.ay.yıl biçiminde nasıl yazdırırım?
t.Format("02.01.2006") kullanın; saatle birlikte "02.01.2006 15:04". Aynı düzeni time.ParseInLocation ile ayrıştırmada da kullanabilirsiniz.
Neden YYYY-MM-DD gibi kodlar yok?
Go, düzeni örnek bir tarihle tarif etmeyi seçmiştir: referans zaman 2 Ocak 2006 15:04:05 -0700. Belgeye göre bu yöntemde biçim, referans zamanın o biçimde nasıl görüneceğini göstererek tanımlanır ve aynı düzen hem Format hem Parse için geçerlidir.
İki tarih arasındaki gün sayısını nasıl bulurum?
İki zamanı Sub ile çıkarıp Hours()/24 hesaplayabilirsiniz; örnekte 61 gün çıktı. Yaz saati uygulanan bir bölgede çalışıyorsanız hesaplamayı önce iki tarihi de UTC gece yarısına getirerek yapmak sonucun tam sayı olmasını sağlar.
JSON'da time.Time nasıl görünür?
time.Time kendi MarshalJSON metoduyla RFC 3339 biçiminde, saniye kesriyle birlikte tırnaklı bir string olarak yazılır; çözme sırasında da RFC 3339 bekler. Sıfır zamanı JSON'dan çıkarmak için omitzero etiketi gerekir; ayrıntılar encoding/json yazısında.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: Go öğrenme rehberi · select ve zaman aşımı · context paketi · encoding/json kullanımı · fmt ile biçimlendirme · slices, maps ve sort paketleri