"Boş" bir tarih alanı gerçekte boş değildir

TROIA'da bir tarih alanını boş bırakırsanız, o alan aslında NULL değil, NULLDATE adlı özel bir değer taşır — ekranda " . . " (tarih için) ya da " . . : : " (tarih-saat için) olarak görünür. Bu ayrım önemli çünkü bir tarih alanının "boş mu" olduğunu == '' gibi bir string karşılaştırmasıyla test etmeye çalışmak işe yaramaz; bunun için özel bir fonksiyon var: NULLDATE().

Dört tarih/saat tipi

  • DATE: Sadece tarih (23.04.1920), varsayılan değeri tanımlandığı gün.
  • DATETIME: Tarih + saat (29.10.1923 16:30:30), varsayılan tanımlandığı an.
  • TIME: Saat:dakika (21:30).
  • TIMES: Saat:dakika:saniye (21:30:13), v5.01.01 sonrası destekleniyor.

Otomatik dönüşüm kuralları

  • DATETIME → DATE atarsanız sadece tarih kısmı kalır.
  • DATE → DATETIME atarsanız saat kısmı 00:00:00 olur.
  • DATETIME → TIME/TIMES atarsanız sadece saat kısmı kalır.

İçeride tüm tarih tipleri, 01.01.1970 00:00:00'dan itibaren geçen milisaniye olarak bir LONG değer şeklinde tutuluyor. DATETOMILLISECONDS() ve MILLISECONDSTODATE() ile bu ham değere inip çıkabilirsiniz — iki tarih arasındaki farkı yüksek hassasiyetle hesaplamanız gerektiğinde işe yarar.

Sık kullanılan fonksiyonlar

Kategori Fonksiyonlar
Anlık değer SYS_CURRENTDATE (her okumada güncel), CURRENTTIMEMILLIS()
Doğrulama ISDATE(), CHECKDATE(), CHECKTIME(), NULLDATE()
Parça çıkarma GETDATE(), GETTIME(), GETDAY(), GETMONTH(), GETYEAR(), GETHOUR(), GETMINUTE(), GETDAYOFWEEK(), GETWEEK()
Hesaplama ADDDAYS(), ADDYEARS(), ADDHOURS(), ADDMINUTES(), SUBDAYS(), SUBMONTHS()
Ay/hafta sınırları FIRSTDATEINMONTH(), LASTDATEINMONTH(), GETDATEFROMWEEK()
Fark GETMINUTEDIFF(), ya da doğrudan çıkarma: (TARIH2 - TARIH1) / (1000*60) dakika verir

GETDAYOFWEEK()'in 1 değerinin Pazartesi olduğunu unutmayın — haftanın Pazar'dan başladığını varsayan bir kültürden geliyorsanız bu, "hafta sonu" kontrolünde kapalı kapı arkasında bir off-by-one hatasına yol açabilir.

NULLDATE ve min/max sınırları

IF NULLDATE(TESLIMTARIHI) == 1 THEN
    MESSAGE 'Teslim tarihi girilmemiş.' TYPE WARNING;
    RETURN;
ENDIF;

Sistem ayrıca sınır değerler tanımlıyor: SYS_MINDATE/SYS_MAXDATE ve bunları kontrol eden ISMINDATE()/ISMAXDATE(). Eski sürümlerde (v3.08.x) varsayılan aralık 01.01.1975–01.01.2030 idi; v5.01 sonrasında bu sınırlar IASSYSTEM tablosundaki MINDATEYEAR/MAXDATEYEAR kolonlarıyla yapılandırılabiliyor. 2030 sınırının hâlâ eski bir varsayılan olarak durduğu bir ortamda, 2030 sonrası bir vade tarihi girmeye çalışan bir kullanıcı garip bir hatayla karşılaşabilir — bu sınırları özellikle uzun vadeli sözleşme/amortisman hesaplayan modüllerde kontrol etmekte fayda var.

Formatlama ve ayrıştırma

Varsayılan format tarihler için DD.MM.YYYY, tarih-saat için DD.MM.YYYY HH:MM:SS — yerelleştirmeden bağımsız, sabit. v5.02.05 sonrası FORMATDATE()/PARSEDATE() fonksiyonları ve SYS_DATETIMEFORMAT/SYS_DATEFORMAT/SYS_TIMEFORMAT gibi sistem değişkenleri geldi:

STRINGDEGER = FORMATDATE(SYS_CURRENTDATE, 'yyyy.MM.dd');

Veritabanı formatı ve zaman dilimi

Veritabanı katmanı, SYST06'da tanımlı tek bir tarih/saat formatını kullanıyor; bir sorguda tarihi elle string olarak yazmanız gerekiyorsa GETDBDATESTR() fonksiyonu bu formata uygun bir metin üretiyor — SQL içine elle DD.MM.YYYY formatında bir tarih string'i gömmek, farklı yapılandırılmış bir veritabanında sessizce yanlış yorumlanabilir.

Kullanıcı saat dilimi SYST03'te, veritabanı saat dilimi SYST06'da ayrı ayrı tanımlanıyor; sistem tarihleri "Veritabanı Saat Dilimi"nde saklıyor. Uyumsuzluk uyarıları varsayılan olarak açık; gerekirse sunucu ayarlarındaki IgnoreTimezoneWarnings parametresiyle kapatılabiliyor — ama bu uyarıyı kapatmak, altında yatan gerçek bir yapılandırma sorununu gizleyebilir, dikkatli kullanılmalı.

Sık yapılan hatalar

  • Boş tarihi == '' ile kontrol etmeye çalışmak — NULLDATE() yerine string karşılaştırması yazmak, tip uyumsuzluğu ya da yanlış sonuç üretir.
  • GETDAYOFWEEK()'te Pazar'ı 1 sanmak — TROIA'da 1 Pazartesi'dir; hafta sonu kontrollerinde bu varsayımı doğrulamadan kod yazmak sessiz mantık hatalarına yol açar.
  • Tarihi elle sabit DD.MM.YYYY formatında SQL'e gömmek — veritabanı formatı farklı yapılandırılmışsa bu, ya hataya ya da (daha kötüsü) yanlış ama geçerli görünen bir tarihe yorumlanmaya yol açar; GETDBDATESTR() kullanın.
  • Saat dilimi uyarılarını düşünmeden kapatmak — IgnoreTimezoneWarnings bir "sessize alma" ayarı; asıl yapılandırma tutarsızlığını çözmeden bu uyarıyı kapatmak, ileride teşhisi zor zaman farkı hatalarına yol açabilir.
  • SYS_MAXDATE sınırının farkında olmadan uzun vadeli tarih hesaplamak — özellikle eski/varsayılan sınırlarla çalışan bir ortamda 2030 sonrası bir tarih hesaplamak beklenmedik davranışa yol açabilir.

Sıradaki adım

Bir sonraki yazıda XML/JSON verisinin TROIA'da nasıl ayrıştırılıp üretildiğine değineceğim.