İçeriğe geç

Zaman ve diller

Bu sayfa İngilizceden çevrilmiştir. İngilizce sayfayı okuyun

Tarih ve saatler iş uygulamalarında yaygın bir hata kaynağıdır: kullanıcı seyahat edince bir gün kayan doğum günü, saat değişikliğinden sonra bir saat geç başlayan vardiya. Zeyn her değer türüne kendi türünü verir; böylece derleyici bunları birbirinden ayırır.

Dört tür

TürNedirÖrnek
DateBir takvim günü, dilimsizBir doğum günü, bir fatura tarihi
TimeBir duvar saati zamanı, dilimsizÇalışma saatleri
DateTimeKesin bir an, UTC olarak saklanırBir kaydın oluşturulduğu zaman
LocalDateTimeBir yerdeki duvar saati tarih ve zamanıİstanbul'da saat 14:00'te bir randevu

Bir takvim gününü asla bir an olarak saklamayın. Date her dilimde aynı gündür; DateTime her yerde aynı andır ve her dilimde farklı bir duvar saati gösterir.

let day = Date::new(2026, 3, 29).unwrap_or_default();
let at = Time::new(9, 30, 0).unwrap_or_default();
let slot = LocalDateTime::new(day, at);
let zone = TimeZone::named("Europe/Istanbul").unwrap_or(TimeZone::UTC);
let moment = DateTime::from_local(slot, zone)?;
let back = moment.local(zone);

DateTime::from_local, dilimde bulunmayan bir duvar saati için (ilkbahardaki saat değişikliği sırasında olduğu gibi) tahmin yürütmek yerine hata verir.

Saat

Sistem saatini değil, ctx.now() ve ctx.today() kullanın. ctx.today() kullanıcının diliminde bugündür. Testler, her istek için saati App::fixed_now(moment) ile sabitler.

Saat dilimleri

App::new(t!("app.name"))
    .time_policy(TimePolicy::User { default: TimeZone::named("Europe/Istanbul").unwrap_or(TimeZone::UTC) })
    .time_zone_picker()
PolitikaAnlar şu dilimde gösterilir
TimePolicy::User { default }Kullanıcının tarayıcısının bildirdiği dilim; bildirene kadar default
TimePolicy::Organization(zone)Herkes için tek bir dilim

.time_zone_picker() menüye bir seçici ekler; böylece kullanıcılar dilimi elle seçebilir. Bir single sign on proxy'si de dilimi bir başlıkta gönderebilir (ForwardAuth::time_zone). DateTime sütunlarındaki grid filtreleri kullanıcının diliminde okunur.

Seçiciler

Tarih, saat ve tarih saat alanları klavye dostu seçiciler alır. DateOptions seçilebilecekleri sınırlar:

Form::of(visit)
    .row(|r| r.field(Visit::day).field(Visit::arrives))
    .range(Visit::stay_from, Visit::stay_to)
    .date_options(Visit::day, DateOptions::new().no_weekends().week_numbers())
    .date_options(Visit::arrives, DateOptions::new().step_minutes(15))

Biçim: 31.12.2024. Şunları da yazabilirsiniz: bugün, +3g.

Biçim: 14:30. Şunları da yazabilirsiniz: şimdi, 930.

Biçim: 31.12.2024 14:30. Şunları da yazabilirsiniz: bugün, +3g.

Biçim: 31.12.2024. Şunları da yazabilirsiniz: bugün, +3g.

Dil seçimi

Sunucu dili önce zeyn_locale çerezinden, sonra tarayıcının Accept-Language başlığından, sonra uygulama varsayılanından seçer. <html lang> her zaman eşleşir. Menüdeki dil seçici çerezi ayarlar ve sayfayı yeniden yüklemeden yerinde değiştirir.

App::locale_paths() ile dil bunun yerine URL'nin parçası olur: varsayılan dil /orders adresinde kalır, diğerleri /tr/orders veya /ar/orders alır. Kararı yalnızca yol verir; böylece paylaşılan bir bağlantı aynı dilde açılır, her screen'in yine tek bir route'u vardır ve dili ctx.locale() ile okur. Menü bağlantıları dili korur, seçici de aynı sayfayı yeniden yüklemeden diğer dilde açar. Arapça ve sağdan sola yazılan diğer diller <html dir="rtl"> alır. Public bir sayfanın dillerini arama motorlarına Screen::alternate("tr", "/tr/orders") ile bildirin.

Sayılar, para ve tarihler

Değerler sunucuda kullanıcının diline göre biçimlendirilir: Türkçede 1.234,56, İngilizcede 1,234.56, tarihler 29.03.2026 veya 3/29/2026 olarak ve para para birimi simgesiyle. Girdiler aynı biçimleri geri okur.

Money tam sayı küçük birimleri ve bir para birimini tutar; böylece toplamlar bir kuruş bile kaybetmez:

let price = Money::tl(2_500_000);
let text = price.format("tr");