- SQLite'ın yerleşik tarih işlevleri yetersiz kaldığında,
sqlean-timebir eklenti olarak nanosaniye hassasiyetinde Time·Duration tipleri ve tarih/saat işlevleri ekler - Time değeri,
0001-01-01 00:00:00 UTCsonrasındaki saniyeler ile içinde bulunulan saniyedeki nanosaniyelerden oluşur; 13 baytlık BLOB olarak saklandığında geçmişte ve gelecekte milyarlarca yıllık aralığı kapsayabilir - Unix epoch tabanlı 64 bit NUMBER olarak saklamak da mümkündür, ancak birim küçüldükçe aralık daralır; nanosaniye biriminde yalnızca
1678ile2262yılları arası temsil edilebilir - API; oluşturma, alan çıkarma, Unix time dönüşümü, karşılaştırma, aritmetik, kırpma·yuvarlama, ISO 8601 biçimlendirme·ayrıştırmayı içerir ve değerler her zaman UTC olarak saklanıp işlenir
- Takvim hesaplamaları Gregoryen takvim varsayımıyla yapılır ve artık saniyeler ele alınmaz; bu yüzden gün·ay·yıl hesaplarında Duration tabanlı
time_add()yerinetime_add_date()kullanılmalıdır
sqlean-time zaman modeli
sqlean-time, SQLite'a yüksek hassasiyetli tarih·saat işleme ekleyen bir eklentidir- SQLite eklentileri, dosya indirilip veritabanında tek bir komut çalıştırılarak eklenebilir
- Eklenti iki tür değer etrafında çalışır
- Time: belirli bir an
- Duration: süre
Time gösterimi ve saklama aralığı
- Time,
(seconds, nanoseconds)ikilisinden oluşurseconds: zero time olan0001-01-01 00:00:00 UTCsonrasındaki saniyeleri gösteren 64 bit tamsayınanoseconds: mevcut saniye içindeki nanosaniye değeri; aralığı0-999999999
- En yüksek esneklik gerekiyorsa, Time değeri dahili gösterimi olan 13 baytlık BLOB olarak saklanabilir
- Bu yöntem, geçmişte ve gelecekte milyarlarca yılı nanosaniye hassasiyetinde ifade eder
- Unix epoch olan
1970-01-01 00:00:00 UTCsonrasındaki saniye, milisaniye, mikrosaniye, nanosaniyeyi 64 bit tamsayı NUMBER olarak saklama da desteklenir- saniye: geçmişte ve gelecekte milyarlarca yılı saniye hassasiyetinde ifade eder
- milisaniye: 1970'in öncesi ve sonrasında 292 milyon yılı milisaniye hassasiyetinde ifade eder
- mikrosaniye:
-290307yılından294246yılına kadar ifade eder - nanosaniye:
1678yılından2262yılına kadar ifade eder
- Time her zaman UTC olarak saklanır ve işlenir
- Belirli saat dilimi ofsetlerine dönüşüm mümkündür
- Takvim hesaplamaları her zaman Gregoryen takvimi varsayar
- Artık saniyeler kullanılmaz
Duration ve değer oluşturma
- Duration, nanosaniye cinsinden 64 bit tamsayıdır
- Yaklaşık 290 yıla kadar olan süreleri ifade edebilir
- NUMBER olarak saklanabilir
- Geçerli zaman
time_now()ile oluşturulabilir- Örn:
time_fmt_iso(time_now()),2024-08-06T21:22:15.431295000Zgibi bir ISO dizgesi döndürür
- Örn:
- Belirli tarih·saat
time_date()ile oluşturulur- Yalnızca tarih verilirse UTC gece yarısı olur
- Saat·dakika·saniye ve nanosaniye birlikte belirtilebilir
- Saat dilimi ofseti verilirse UTC anına dönüştürülür
Tarih·saat alanlarını çıkarma
- Tek tek alan çıkarma işlevleri yıl, ay, gün, saat, dakika, saniye, nanosaniye, haftanın günü, yılın günü, ISO yılı, ISO haftasını döndürür
- Örn:
time_get_year(),time_get_month(),time_get_day(),time_get_hour(),time_get_minute(),time_get_second(),time_get_nano()
- Örn:
- Genel amaçlı
time_get()işlevi, alan adı dizgesiyle değer çıkarır- Desteklenen örnekler:
millennium,century,decade,year,quarter,month,day - Zaman birimi örnekleri:
hour,minute,second,milli,micro,nano - ISO·takvim ile ilgili örnekler:
isoyear,isoweek,isodow,yearday,weekday - Unix epoch değeri
epochile alınabilir
- Desteklenen örnekler:
Unix time dönüşümü
- Unix time'dan Time değeri oluşturan işlevler sunulur
time_unix(seconds)time_unix(seconds, nanoseconds)time_milli(milliseconds)time_micro(microseconds)time_nano(nanoseconds)
- Time değerini yeniden Unix time'a çeviren işlevler de vardır
time_to_unix()time_to_milli()time_to_micro()time_to_nano()
- Unix türevi işletim sistemleri zamanı çoğu zaman 32 bit saniye değeriyle kaydeder, ancak
time_to_unix()64 bit değer döndürür- Geçmişte ve gelecekte milyarlarca yıllık aralıkta geçerlidir
time_to_milli()1970'in öncesi ve sonrasında 292 milyon yıla kadar ifade edertime_to_micro()-290307yılından294246yılına kadar ifade edertime_to_nano()1678yılından2262yılına kadar ifade eder
Karşılaştırma ve aritmetik
- Zaman karşılaştırma işlevleri iki Time değerinin sırasını belirler
time_after(): ilk zamanın ikinciden sonra olup olmadığını döndürürtime_before(): ilk zamanın ikinciden önce olup olmadığını döndürürtime_compare(): sonraysa1, önceyse-1, eşitse0döndürürtime_equal(): iki değerin aynı anı gösterip göstermediğini döndürür
time_add()bir Time değerine Duration ekler- Negatif Duration kullanılarak çıkarma yapılabilir
dur_us(),dur_ms(),dur_s(),dur_m(),dur_h()gibi Duration sabitleri birlikte kullanılabilir
- Gün·ay·yıl eklerken
time_add()değil,time_add_date()kullanılmalıdırtime_add_date()yıl, ay, gün ekler; negatif değerlerle çıkarma da yapılabilir
time_sub()iki Time değeri arasındaki süreyi nanosaniye olarak döndürürtime_since()belirtilen andan bu yana geçen süreyi nanosaniye olarak döndürürtime_until()belirtilen ana kadar kalan süreyi nanosaniye olarak döndürür
Kırpma ve yuvarlama
time_trunc()bir Time değerini belirtilen alan hassasiyetine kadar aşağı yuvarlar- Desteklenen örnekler:
millennium,century,decade,year,quarter,month,week,day,hour,minute,second,milli,micro - Örneğin
2011-11-18T15:56:35.666777888Zdeğerihourdüzeyine kırpılırsa2011-11-18T15:00:00Zolur
- Desteklenen örnekler:
- Belirli bir Duration katına göre de aşağı yuvarlanabilir
- Örn:
12*dur_h(),dur_h(),30*dur_m(),dur_m(),30*dur_s(),dur_s()
- Örn:
time_round()belirtilen Duration'ın en yakın katına yuvarlar- Örn:
2011-11-18T15:56:35.666777888Zdeğeridur_h()ile yuvarlanırsa2011-11-18T16:00:00Zolur - Aynı değer
dur_s()ile yuvarlanırsa2011-11-18T15:56:36Zolur
- Örn:
Biçimlendirme ve ayrıştırma
time_fmt_iso()bir Time değerini ISO 8601 dizgesi olarak döndürür- Saat dilimi ofseti isteğe bağlı olarak alınabilir ve bu ofsete dönüştürüldükten sonra biçimlendirilebilir
- Nanosaniyeli değerler
2011-11-18T15:56:35.666777888Zgibi gösterilir - Ofset belirtilirse
2011-11-18T18:56:35.666777888+03:00gibi gösterilir
time_fmt_datetime(),time_fmt_date(),time_fmt_time()sırasıyla datetime, date, time dizgeleri döndürür- Saat dilimi ofseti isteğe bağlı olarak verilebilir
time_parse()biçimlendirilmiş dizgeyi Time değerine ayrıştırır- ISO 8601 nanosaniye ve saat dilimi içeren dizgeler
- ISO 8601 nanosaniye ve UTC
Zdizgeleri - ISO 8601 saat dilimi içeren dizgeler
- ISO 8601 UTC dizgeleri
YYYY-MM-DD HH:MM:SSbiçimindeki UTC tarih·saatYYYY-MM-DDbiçimindeki UTC tarihHH:MM:SSbiçimindeki UTC saat
time_parse()tarafından desteklenen layout'lar sınırlı bir kümedir
Duration sabitleri
- Yaygın Duration'ları nanosaniye olarak döndüren işlevler sunulur
dur_ns()→1dur_us()→1000dur_ms()→1000000dur_s()→1000000000dur_m()→60000000000dur_h()→3600000000000
Uygulama temeli ve kurulum
- Eklenti C ile yazılmış olsa da tasarım ve uygulama büyük ölçüde Go standart kütüphanesindeki time paketine dayanır
- İlgili paket BSD 3-Clause License lisansına sahiptir
- Kurulum, latest release dosyasını indirip SQLite CLI içinde eklentiyi yükleme şeklindedir
- Örn:
.load ./time - Yüklemeden sonra
select time_now();gibi sorgular kullanılabilir
- Örn:
1 yorum
Hacker News yorumları
Jon Skeet’in meşhur şekilde derlediği saat dilimi değişiklikleri ve yerel saatteki süreksizlikler gibi özel durumları da ele alıp almadığını merak ediyorum
https://stackoverflow.com/questions/6841333/why-is-subtracti...
Computerphile da 10 dakikalık bir videoda bunu çok iyi açıklıyor
https://www.youtube.com/watch?v=-5wpm-gesOY
Uzun zaman önce tarih/saat ya da kriptografi kütüphanelerini kendim yazmamayı öğrendim. Ölümcül biçimde can yakabilecek uç durumlar bitmek bilmiyor; bu yüzden böyle yeni bir kütüphane görünce şüpheyle yaklaşıyorum
Belgelerin biraz daha net olabileceğini düşünüyorum. Yazar “time zones” diyor ama kütüphane aslında yalnızca saat dilimi ofsetlerini ele alıyor. Saat dilimi America/New_York gibi bir şeydir; saat dilimi ofseti ise UTC ile arasındaki farktır. New York bugün -14400 saniye, ama yaz saati uygulaması değişikliği nedeniyle birkaç ay sonra -18000 saniye olacak
Üç farklı zaman gösterimi/boyutu ilginç. Örneğin milyarlarca yıllık aralıkta nanosaniye hassasiyet gerektiren kullanım senaryosunun ne olduğunu bilmiyorum
Daha da kafa karıştırıcı olan, zaman çözünürlüğü aşırı inceyken duration tarafında nanosaniye hassasiyetinin aralığının yalnızca ±290 yıl olması
Ama 2 bit ekleyecekseniz 16 ya da 32 bit eklememek için de bir neden yok. Böylece 30 cm’yi ışığın katetme süresini hesaplayandan evrenin yaşını hesaplayana kadar herkesi kapsayabilirsiniz
Tasarım kararının muhtemelen böyle geliştiğini hayal ediyorum :)
Elbette artık saniye desteği olmadan saniye altı doğruluk sunmak zor; insan uygarlığı öncesi artık saniye desteğinin ne anlama geldiği de belirsiz
İlgili bir yan konu ama veritabanları birimleri izlemeli. Bir zaman sütunu varsa, örneğin float64 saniye cinsinden duration diye tanımlanabilmeli
O zaman
SELECT * FROM my_table WHERE duration_s >= 2hgibi yazılabilmeli ve veritabanı “2h” değerini otomatik olarak 7200.0 saniyeye çevirip tablo taraması sırasında aynı birimlerle karşılaştırmalıBirkaç yıl önce böyle yerel birim işleme özelliği olan özel amaçlı bir SQL veritabanı yapmıştım; ama öncesinde de sonrasında da görmedim ve bu, UI ekosisteminde bir boşluk gibi görünüyor
Bunun yalnızca zamanla sınırlı olması gerekmez. Kütle, hacim, bilgi miktarı, sıcaklık vb. tüm birim listesini ele alabilmeli.
SELECT 2h + 15kg -- type error!gibi matematiksel olarak anlamsız ifadeleri de veritabanı reddedebilmeliBu, analiz hatalarını erken yakalamada çok yardımcı olur
İşaretli tamsayı kullanılıp kullanılmadığının belirtilmesinin önemli olduğunu düşünüyorum. Belgeleri okuyunca işaretli gibi duruyor ama olmayabilir de
İşaretli tamsayıysa aynı tarih ve saati temsil eden birden fazla bit dizisi ortaya çıkabilir; bu iyi değil
Ancak bit deseni kütüphanenin iç meselesi. Kodda bir hata bulabiliyorsanız elbette işaret edin; mümkünse düzeltme de önerin
SQLite3’te genişletilebilir bir tip sistemi olsaydı gerçekten iyi olurdu
Genişletilebilir tip sistemi, veritabanı son kullanıcı performansı için berbat. Böyle olunca sorgu ayrıştırma ve optimizasyonunda hiçbir şeyi kestirmeden işleyemezsiniz. Her işlenenin tipini kontrol etmek, doğru operatör implementasyonunu bulmak, doğru indeks operatör ailesini/sınıfını bulmak vb. için sorgu sistem kataloğuna sürekli bakmak gerekir
Değerlerin giriş/çıkışı da sistem kataloğunda saklanan fonksiyonlardan geçer.
select 1bile sistem kataloğuna bakmadan yanıtlanamazUygun bir yerleşik tip kümesi ve struct/JSON gibi bileşim yöntemleri olmalı. PostgreSQL dışındaki çoğu veritabanı böyle ve doğru yönün bu olduğuna güçlü biçimde inanıyorum
Biraz tembel bir Ask HN tarzı soru ama deneyime göre hangisi daha kullanışlı ya da değerli? Nanosaniye gösterimi mi, yoksa 1678~2200 gibi nanosaniye aralığının dışındaki yılları gösterebilmek mi?
Ciddi bilimsel işler yapmadığım için nanosaniyenin değerinin çok akıllıca deneylerle ya da daha dar aralıklı finansal işlem takibiyle sınırlı olduğunu düşünüyorum
Buna karşılık tarihsel tarihleri gösterebilme yeteneğine daha sık ihtiyaç duyulacak gibi. Ne düşünüyorsunuz?
Hassasiyeti yalnızca 10 nanosaniyeye düşürseniz bile pratikte yeterli bir aralık elde edebilirsiniz
Neden Go tarzı gibi Unix zaman damgasını nanosaniye cinsinden signed int64 olarak kullanmadığını merak ediyorum. Nanosaniye hassasiyetiyle milyonlarca yılı kapsayamazsınız ama buna gerçekten ihtiyaç var mı?
select time_to_nano(time_now());-- 1722979335431295000“epoch’tan sonraki saniyeler” gibi ifadelerin yalnızca gerçekten o anlama geldiğinde kullanılmasını isterdim
select time_sub(time_date(2011, 11, 19), time_date(1311, 11, 18));ne döndürür merak ediyorumAklıma birkaç makul neden geliyor ama gerçekten önemli olan tek şey “hangi epoch?” sorusu. UNIX tabanlı sistemlerde ya da onun davranışını taklit etmeye çalışan sistemlerde bu iyi tanımlıdır. Ama şikâyetinizin ne olduğunu söylemediğiniz için bunun neden şu anki gibi olduğunu çürütmek ya da gerekçelendirmek zor
time_date(1311, 11, 18)çoğu bilgisayar sisteminin kullandığı epoch’ta tanımlı değildir; bu yüzden herhangi bir sonuç mümkün. MAX_INT, MIN_INT, 0, makul görünen ama takvim reformlarını yansıtmayan bir değer, başka bir epoch’a dönüştürüp doğru saniye sayısını hesaplayan bir değer vb. her şey olabilir. GMT/UTC öncesinde her şey yerel saatti; bu yüzden geçerli bir epoch olmadığını da savunabilirsinizElbette negatif değerlerin desteklenip desteklenmemesi iki yönden de savunulabilir. 1970-1-1 0:00:00 UTC’den tam 24 saat öncesinin -86400 olmasını bekleyebilirsiniz, ama “since” yalnızca pozitifliği güçlü biçimde ima eder
Başkalarının bambaşka nedenlerle tamamen farklı epoch’ları olabilir ve kullanıldığı alan içinde herkes hemfikirse bu da sorun değildir
Yoksa başka bir itiraz nedeniniz mi vardı?