İçeriğe geç

Zaman ve Saat Dilimleri — Havale Hangi Güne Yazılır?

Orta 9 dk Çok sık karşılaşılır

Önce şunu oku: BigDecimal — Parada Kuruş Kaybetmemek

30 saniyede özet

Bir an tek bir noktadır ama her şehrin duvar saati onu başka gösterir. Anı Instant olarak saklarsın, saat dilimini yalnızca gösterirken uygularsın. Ofset bir sabit değildir: yaz saatiyle değişir.

İstanbul’dan Londra’ya uçtun ve indiğinde saatini üç saat geri aldın. Saatin değişti ama sen aynı andasın.

Kodda da bir an ile o anı gösteren duvar saati ayrı şeylerdir. Bunları karıştırmak, bankada havalenin yanlış güne yazılması demektir.

An aynı; değişen yalnızca duvardaki saat.
Adım adım oku
  1. Bir havale gönderildi: zaman çizgisinde tek bir an.
  2. İstanbul'daki duvar saati o anda 23:10 gösteriyor.
  3. Aynı anda Berlin'de 21:10, New York'ta 15:10.
  4. Üç farklı saat, ama hepsi aynı an.
  1. Bayt: Gün sonu raporu tutmuyor! Dünkü toplamda bugünün havaleleri var.

  2. Sen: Her sunucu saati kendi yazıyor, değil mi?

  3. Bayt: Evet... ve hangi şehrin saati olduğunu yazmıyor.

  4. Bayt: O zaman önce 'an' ile 'saat' arasındaki farkı ayıralım.

Bir an, birçok saat

TipNe tutarÖrnek
InstantZaman çizgisinde bir anHavalenin gerçekleştiği an
LocalDateSaat dilimi olmayan bir tarihDoğum günü
LocalDateTimeSaat dilimi olmayan tarih ve saatTakvimdeki bir not
ZonedDateTimeTarih, saat ve bölgenin kurallarıBerlin’de 10:00’da toplantı

Instant bir anı UTCDünyanın ortak saat referansı. Yaz saati yoktur; her saat dilimi UTC'ye göre bir ofsetle tanımlanır, örneğin İstanbul +03:00.Java'da Instant bir anı UTC çizgisinde tutar. Loglar ve kayıtlar UTC'de tutulursa farklı ülkelerdeki sunucular aynı dili konuşur.Sözlükte gör → çizgisinde tutar ve kimseye göre değişmez. LocalDateTime ise “saat 22:20” der ama hangi şehirde olduğunu söylemez; bu yüzden bir an değildir.

Anı sakla, saati göster
Instant at = Instant.now();
ZonedDateTime istanbul = at.atZone(ZoneId.of("Europe/Istanbul"));
Kafam karıştı, daha basit anlat

Olayın ne zaman olduğunu kaydediyorsan Instant. Birine saat gösteriyorsan, onun bölgesiyle ZonedDateTime.

Hızlı kontrolBaşlangıç

Bir havalenin gerçekleştiği anı kaydetmek için hangi tip kullanılır?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Her ihtiyaca uygun java.time tipini seç.

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Sınıflandırılmamış

Instant

Zaman çizgisinde bir an

    LocalDate / LocalTime

    Bölgeden bağımsız tarih ya da saat

      ZonedDateTime

      Bir şehrin kurallarıyla tarih ve saat

        Saat kayınca: yaz saati

        Avrupa ve ABD yılda iki kez saatleri bir saat oynatır. Buna yaz saatiBazı ülkelerin yılda iki kez saatleri bir saat oynatması. İlkbaharda bir saat hiç yaşanmaz, sonbaharda bir saat iki kez yaşanır.Ofset bu yüzden tarihe göre değişir. Türkiye 2016'dan beri yaz saati uygulamıyor ve yıl boyu +03:00 kullanıyor.Sözlükte gör → denir ve ofseti tarihe göre değiştirir.

        Berlin 29 Mart 2026 gecesi saatleri 02:00'dan 03:00'a atlıyor. `ZonedDateTime.of(2026-03-29, 02:30, Europe/Berlin)` ne döner? Cevabı göster

        03:30, ofset +02:00. O gece 02:30 Berlin’de hiç yaşanmaz. Java hata vermez; saati boşluğun uzunluğu kadar ileri kaydırır.

        Sonbaharda tersi olur: 02:30 iki kez yaşanır. Java varsayılan olarak ilkini seçer; withLaterOffsetAtOverlap() ikincisini verir.

        Bu yüzden ofseti koda elle yazmak tehlikelidir. Kuralları bir ZoneIdBir bölgenin saat kurallarının adı, örneğin Europe/Berlin. Hangi tarihte hangi ofsetin geçerli olduğunu bilir; sabit bir ofset değildir.Kurallar IANA tz veritabanından gelir ve JDK güncellemeleriyle yenilenir. ZoneOffset ise yalnızca sabit bir farktır, örneğin +02:00.Sözlükte gör → bilir: Europe/Berlin hangi tarihte hangi ofsette olduğunu kendisi söyler.

        Kafam karıştı, daha basit anlat

        Bazı geceler bir saat kaybolur, bazı geceler bir saat iki kez yaşanır. Bunu sen hesaplama; şehrin adını ver, Java hesaplasın.

        İstanbul neden kolay görünüyor?· istersen atla

        Türkiye 2016’dan beri yıl boyu +03:00 kullanıyor. Ama karşı taraftaki Berlin ya da New York sunucusu yaz saatine geçiyor; senin kodun yine de kurallara uymak zorunda.

        Hızlı kontrolOrta

        Berlin 29 Mart 2026 gecesi saatleri 02:00'dan 03:00'a atlıyor. Bu kod ne yazdırır?

        Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.
        Gap.java
        1ZoneId berlin = ZoneId.of("Europe/Berlin");
        2ZonedDateTime t = ZonedDateTime.of(
        3 LocalDate.of(2026, 3, 29), LocalTime.of(2, 30), berlin);
        4System.out.println(t);
        Java 21UTF-8LF

        t = 2026-03-28T12:00 Europe/Berlin. t.plus(Duration.ofHours(24)) ile t.plus(Period.ofDays(1)) ne verir? (O gece Berlin yaz saatine geçiyor.)

        Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

        Saati test edilebilir yapmak

        Instant.now() her çağrıda başka bir değer döner. “Gece yarısından sonra gelen havale ertesi güne yazılır” kuralını test etmek için saati durdurabilmen gerekir.

        Çözüm, saati bir Clock olarak dışarıdan vermektir. Üretimde gerçek saat, testte sabit bir an kullanılır.

        Testte saat istenen anda durur
        Clock clock = Clock.fixed(Instant.parse("2026-01-15T21:05:00Z"), ZoneId.of("Europe/Istanbul"));
        BusinessDay day = new BusinessDayResolver(clock).today(); // 2026-01-16
        Hızlı kontrolOrta

        Gece yarısı kuralını test etmek için iş kodunda saat nasıl okunmalı?

        Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

        Kendin gör

        Beş havale İstanbul, Berlin ve New York’taki sunuculardan geliyor. Sunucuların zamanı nasıl sakladığını seç ve gün sonu raporuna bak.

        Gün sonu: havale hangi güne yazılır?

        Tohum 1

        Oynat ya da adımla.

        Hız
        Adım 0

        Şu an ne oldu?

        İstanbul'da gün sonu yaklaşıyor

        Beş havale geliyor. Her biri, İstanbul saatiyle gerçekleştiği güne yazılmalı. Gün gece yarısı biter.

        Görevler0/3

        • Saat dilimi kaybolunca iki havalenin yanlış güne yazıldığını göraçık

          İpucu

          Her sunucunun kendi duvar saatini sakladığı seçeneği sonuna kadar oynat.

        • Kışın doğru çalışan sabit ofsetin bozulduğu haftayı bulaçık

          İpucu

          Ofseti kim, hangi mevsimde yazdı?

        • Mart haftasında bile raporu doğru çıkaraçık

          İpucu

          Mevsimden etkilenmeyen tek değer hangisi?

        Olay günlüğü (0)

        Henüz olay yok. Oynat veya adımla.

        1. Varsayılanı oynat. Saat dilimi kaybolunca iki havale yanlış güne yazılıyor ve sıralama bozuluyor.
        2. Sabit ofseti dene. Ocak’ta her şey doğru.
        3. Aynı seçenekte haftayı Mart yap. New York yaz saatine geçti; bir havale kayıyor.
        4. Instant’a geç. Mevsim ne olursa olsun rapor doğru.
        Hızlı kontrolOrta

        Simülatörde sabit ofset (New York -05:00) Ocak'ta doğru çalıştı, Mart'ta bir havaleyi yanlış güne yazdı. Neden?

        Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

        Tuzaklar

        Sunucunun varsayılan dilimine güvenmek. LocalDateTime.now() sunucunun ayarına bağlıdır; aynı kod başka bir makinede başka sonuç verir.

        Bir günü 24 saat sanmak. Yaz saati gecesinde plus(Duration.ofHours(24)) duvar saatini kaydırır. Takvim günü için Period.ofDays(1) kullanılır.

        Eski Date ve SimpleDateFormat. SimpleDateFormat thread-safe değildir; static bir alanda paylaşılınca tarihler karışır. DateTimeFormatter değişmezdir ve paylaşılabilir.

        Hızlı kontrolOrta

        Bu sınıf farklı ülkelerdeki sunucularda çalışıyor ve yük altında. Sorunlu satırları işaretle.

        Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

        Hatalı satıra dokun, sonra kontrol et.

        TransferStamp.java
        Java 21UTF-8LF
        Derinleş · Gün sonu: havaleyi doğru iş gününe yazmak 4 dosya · ~57 satır · ilk okumada atlayabilirsin
        Proje dosyaları

        src/main/java/com/bank/transfer/ Transfer.java Havale kaydı: gerçekleştiği an Instant olarak saklanır.

        src/main/java/com/bank/transfer/Transfer.java
        public record Transfer(String id, BigDecimal amount, Instant executedAt) {
        }

        src/main/java/com/bank/day/ BusinessDayResolver.java İş günü: an, İstanbul kurallarıyla tarihe çevrilir. Saat dışarıdan verilen Clock'tan okunur.

        src/main/java/com/bank/day/BusinessDayResolver.java
        @Component
        public class BusinessDayResolver {
        static final ZoneId BANK_ZONE = ZoneId.of("Europe/Istanbul");
        private final Clock clock;
        public BusinessDayResolver(Clock clock) {
        this.clock = clock;
        }
        public LocalDate today() {
        return LocalDate.now(clock.withZone(BANK_ZONE));
        }
        public LocalDate dayOf(Instant moment) {
        return moment.atZone(BANK_ZONE).toLocalDate();
        }
        }

        src/main/java/com/bank/day/ DayEndReport.java Gün sonu sorgusu: günün başı ile ertesi günün başı arası, yarı açık aralık. Ofseti ZoneId hesaplar.

        src/main/java/com/bank/day/DayEndReport.java
        @Service
        public class DayEndReport {
        private final TransferRepository transfers;
        public DayEndReport(TransferRepository transfers) {
        this.transfers = transfers;
        }
        public BigDecimal total(LocalDate day) {
        Instant from = day.atStartOfDay(BusinessDayResolver.BANK_ZONE).toInstant();
        Instant to = day.plusDays(1).atStartOfDay(BusinessDayResolver.BANK_ZONE).toInstant();
        // Half-open range [from, to): a transfer at exactly midnight belongs to the next day.
        return transfers.findByExecutedAtGreaterThanEqualAndExecutedAtLessThan(from, to).stream()
        .map(Transfer::amount)
        .reduce(BigDecimal.ZERO, BigDecimal::add);
        }
        }

        src/test/java/com/bank/day/ BusinessDayResolverTest.java Test: saat iki farklı ana sabitlenir.

        src/test/java/com/bank/day/BusinessDayResolverTest.java
        class BusinessDayResolverTest {
        private static Clock at(String instant) {
        return Clock.fixed(Instant.parse(instant), ZoneOffset.UTC);
        }
        @Test
        void transferAfterIstanbulMidnightBelongsToNextDay() {
        var resolver = new BusinessDayResolver(at("2026-01-15T21:05:00Z"));
        assertThat(resolver.today()).isEqualTo(LocalDate.of(2026, 1, 16));
        }
        @Test
        void transferBeforeIstanbulMidnightStaysOnTheSameDay() {
        var resolver = new BusinessDayResolver(at("2026-01-15T20:10:00Z"));
        assertThat(resolver.today()).isEqualTo(LocalDate.of(2026, 1, 15));
        }
        }

        Kendini sına

        Önce hızlı bir ısınma: puan yok, kayıt yok. Sonra asıl sorular.

        Şimşek turu1/4

        LocalDateTime zaman çizgisinde tek bir anı gösterir.

        Soru 1/3İleri

        Farklı ülkelerdeki servislerin yazdığı havale zamanlarını PostgreSQL'de nasıl saklarsın?

        Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

        Aklında kalacak üç şey

        1. 1 Instant bir andır, LocalDateTime ise saat dilimi olmayan bir duvar saati. Bir şeyin ne zaman olduğunu kaydederken Instant saklanır.
        2. 2 Ofset tarihe göre değişir. Yaz saatinde bazı saatler hiç yaşanmaz, bazıları iki kez yaşanır; bu kuralları ZoneId bilir, elle yazılan ofset bilmez.
        3. 3 Kod saati doğrudan değil, enjekte edilen bir Clock'tan okursa testler istenen her ana sabitlenebilir.
        Sonraki kapı Sipariş durumunu metin olarak tuttun ve biri KARGODAA yazdı. Kod bunu neden fark etmedi? Enum — Sabit Bir Seçenek Listesi · 8 dk

        3 kart sonraki derste seni bekliyor

        0/4 kart bu dersten toplandı