Neden gerçek bir “Sadece Tarih” veri türü yok?


24

DateTime değerlerini gerçekten "sadece bir gün" olan veri kümeleri için kullanmak zorunda kaldığım için gülünç oluyorum. Doğum günleri en yaygın örnek olarak görülmektedir, ancak bu her zaman iş uygulamalarında ortaya çıkmaktadır.

"Sadece tarih" kayıtlarının Zaman bölümünü "öğlen" olarak ayarlamaya alışmıştım (saat dilimi ne olursa olsun tarihin değişmesini önler). Bu bir hack gibi görünüyor ve sonsuza dek bu konuyla ilgilenen küçük devlerin böceklerini buluyorum.

Zaman her zaman sabit bir noktaya bağlıdır. 4P, meridyen sonrası 4 saat veya öğlen vaktidir. Güneşin transit halindeki en yüksek noktası gözlemlenebilir ve bir koordinat sistemi kurmamıza izin veriyor. Öğleden 3 saat önce (Ante Meridian), öğleden sonra 2 saat, 1441899402938 1 Ocak 1970'ten bu yana milisaniye. Kartezyen bir dünyada yetişen insanlar için bu ikinci niteliktir.

Ancak Takvimlerimiz Descartes'tan önce. Benim iddiam, bunun bir modulo fonksiyonunun uygulandığı bir numaralandırma olarak daha doğru bir şekilde düşünüldüğüdür. Pazartesi, pazar günleri takip eder, ve böylece pazar günleri cumartesiyi takip eder. Olumlu ve olumsuz değil, bir modül veya mutlak değer.

Benzer şekilde yıl tekrarı. Her 365 günde (ya da öylesine) benim için birkaç özel gün var: doğum günleri, yıldönümleri, çocuk doğum günleri, vb. Bunu bir kayan nokta sayısına eşleştirebiliriz ve gerçekte söz konusu sayıya eşlemek, eski yoldan gerçekten zor olan LOT problemlerini çözer, ancak bu, bunu yapmanın tek yolu anlamına gelmez.

DateTimes'ı depolamak için DateTimes'ı kullanmanın doğası olan "yuvarlak delikli kare kazık" bilinci ve anlayışı size göre daha iyi bir programcıdır.

Bir Date sınıfının tanımlanmasında açıkça bir zamanlama uygulaması olarak tasarlanan bir uygulamada değer var mı, yoksa "her zaman öğleye ayarlanmış" en iyi yaklaşım mı? DateTime kullanmak ve Time bileşenini Noon olarak ayarlamakla ilgili neler olabilir? Saat diliminin kayması böyle bir yaklaşımla açıklanabilir mi? MomentJS kullandım ama bence bu daha iyi bir Date sınıfı.


7
Bu bence oldukça ilginç bir soru. Doğum günü örneğini ele alalım, sadece insanda anlam ifade ediyor, tek bir yerde yaşıyorum ve herkes aynı anda, aynı şekilde uyanıyor. Matematiksel olarak ifade etmeniz gerektiğinde, çok karmaşık bir hal alır. İş vardiyası başlangıç ​​/ bitiş saatleri vb. Gibi şeylerle aynı şeylerdir, 'çalıştığınız zaman diliminde' saat 'onlar' değildir '
Ewan

3
NodaTime (Tarih ve Saat için bir C # kütüphanesi) bir tür tarih vardır.
CodesInChaos 10:15

5
Zamanlarınızı UTC, tarih sorunu, saat dilimi sorunu olmadan saklayın.
Loren Pechtel

3
“Ama Tanrı bu bir hack gibi görünüyor ve sonsuza dek bu konuyla ilgilenen küçük devlerin böceklerini buluyorum.” - Neden sadece kendi DateOnly sınıfını oluşturmuyorsun ya da her neyse onu bir gün ara.
Brandin

5
@MichaelBlackburn Ben ciddiyim. Açıklamanız, iş kuralını uygulayan kendi veri türünün durumunu tam olarak yansıtır (yalnızca tarih, örn. Öğlen olarak ayarlanan zaman bölümü ile dahili olarak "DateTime" olarak saklayabilirsiniz), ancak yalnızca istediğiniz parçaları gösteriniz (ay) , gün vs. yıl / yıl yok).
Brandin

Yanıtlar:


15

Öncelikle, yoldan bir şey çıkaralım: doğum günleri bir şeydir, doğum tarihleri ​​başkadır. Bir Doğum Günü o saat, dakika vb sadece bileşenleri yoksun ama aynı zamanda yıl bileşeni olmadığı için egzotik bir veri türüdür. Doğum günleriyle gerçekten uğraşmak istiyorsanız, ay numarası ve gün numarası dışında hiçbir şey içermeyen ve yerleşik tarih / saat veri türlerinden hiçbiriyle ilgili olmayan kendi veri türünüzü icat etmenizi öneririm.

Öte yandan, doğum yılını da takip etmek istiyorsanız, o zaman sahip olduğunuz doğum günleri değil, doğum tarihidir . Bu nedenle, şimdi soru, neden yalnızca tarih veri türü olmadığından ortaya çıkıyor, böylece doğum tarihini rahatça gösterebiliyorsunuz ve bunun yerine popüler diller sizi bir zaman bileşeni içeren bir tür kullanmaya zorluyor gibi görünüyor.

Tüm programlama dillerinin yalnızca bir zaman bileşeni içeren geçici veri türleri sunduğunun doğru olmadığını kısaca belirteyim . RDBMS'lerde ve karşılık gelen SQL lehçelerinde sadece tarih veri türleriyle karşılaştım. Ancak bu konu dışı: bu veri türlerinin var olması, sahip olmak için iyi bir şey oldukları anlamına gelmez ve RDBMS'lerin depolamayı temsil ile karıştırmak için uzun bir geçmişi vardır.

Zamanın bir koordinat olduğunu anladığınız andan itibaren sadece tarih veri türlerine sahip olmanın neden kötü bir fikir olduğunu anlayacaksınız. Çoğu insan zaman ne olduğu çok muğlak bir fikrim yok ve bu fikir bu kavramlar münhasıran olduğunu fark etmeden, böyle yıllar, aylar ve günler olarak gizli kültürel kavramlarını içeren temsili : Onlar bir insan için gerekli süreyi temsil sadece yararlıdır, ve almak için bir insandan girdi olarak zaman. Fiili zaman girişi GUI kontrolünün altındaki herhangi bir katmanda, zaman, bazı orijinlerden beri tek bir zaman birimi sayısı olan bir zaman koordinatı olarak gösterilmeli ve genellikle temsil edilmelidir.

Örneğin, DateTimeMicrosoft Dotnet'in veri türünde, zaman birimi 100 nanosaniyedir ve zamanın kaynağı saat 12:00, gece yarısı 1 Ocak 0001 CE'dir.

Bir arkana, yalnızca temsili gösterime ilişkin bir başka örnek, dereceler, dereceli dakikalar ve derecenin saniye kullanılarak açı ölçümleridir. Elbette, yararlı bir hesaplama yapmak için, dahili olarak radyan kullanmanız ve gerekiyorsa, bir insan kullanıcısı ile etkileşime girdiğinde derece derecesine çevirmeniz gerekir.

Bu nedenle, bir ölçümün insan tarafından okunabilir gösterimini ölçümün gerçek doğası ile karıştırmayın. Oldukça sıklıkla, ölçümün yapısına en çok uyan bir ölçümü gerçekleştirmek için ideal yöntem, ölçümün insan tarafından okunabilir sunumundan çok farklıdır.

Tüm bunların ışığında, yalnızca tarihleri ​​temsil eden geçici bir veri türü için isteğiniz, yalnızca daha fazla hassasiyeti açıkça önleyen, yalnızca dereceleri temsil edebilecek bir açısal veri türü isteğine benzer. Böyle bir veri türü oldukça sınırlı ve sonuçta işe yaramaz, çünkü bununla ilgili faydalı bir şey elde etmek için onu radyanlardan yine de dönüştürmeniz gerekir.

Doğum tarihiyle ilgili probleminiz, kesin olmayan bir zaman koordinatına sahip olmanızdır : kişi elbette belirli bir zamanda doğdu, ancak saat ve dakika ya hastane tarafından kaydedilmedi ya da biz değiliz. onları umursama. Öyleyse, gerçekte olan şey, doğum tarihi ve saati zaman koordinatınızın eğer isterseniz bir hata payı, hoşgörü ya da belirsizlik olduğu ve bunu en iyi şekilde değerlendirmenin en iyisi olduğu: günün ve üstü kapalı +12 -12 saatlik bir belirsizlik olduğunu düşünün. Ve bu tam olarak sezgisel olarak ulaştığınız çözümdür.


4
Bu, Zamandan daha eski bir kavram olan "Günler" için doğru değildir. En uygun şekilde bir numaralandırma veya modül olarak düşünülürler. Pazar, pazartesi günü vs. Bu gerçekten farklı bir şey.
Michael Blackburn,

10
Tabii ki hastane doğum zamanını yazdı - çoğu hastanede bu standart bir uygulamadır. Hiç sorun değil. Mesele şu ki olayları (doğum günleri, tatiller, yıldönümleri vb.) Anmak amacıyla insanlar, 1 günden daha ince bir çözüm kullanmıyor ya da istemiyor. Git, doğum günü geldiğinde ilk gördüğün kişiye sor, sana bir ay ve bir gün verecekler, ama asla bir saat ve dakika vermeyecekler. Ayrıca: her zaman ölçek içeren birimler kullanıyoruz: milimetre, kilogram, megawatt ve gerçekten de mikrofarad.
Caleb

4
-1: Zamanın tüm kullanımları, zaman içindeki tek bir anı temsil etmek değildir. Doğum günü, Gregoryen takviminde bir ay ve gün tarafından temsil edilen farklı bir fikirdir. "Kevin'in bugün doğum günü mü?" Diye sormak mantıklı. Cevap yere bağlı. Eğer Sydney’deysem doğum günüm olabilirdi, ama bunun yerine Honolulu’da olsaydım daha bir kaç saat olmazdı.
kevin cline

6
@MikeNakis Sonuç saçma değil, mikroamper olurdu. Daha da önemlisi: Bir saniye veya milisaniye yerine bir tarih kullandığınızda, genellikle belirli bir zaman yerine bütün bir günden - bir zaman periyodundan - bahsediyorsunuzdur ve bağlama bağlı olarak yinelenen bir olay olabilir.
Caleb

4
OP, tam olarak java.util.MonthDay tarafından temsil edilen doğum günlerinden bahsediyordu. Doğum günü bir ölçüm değildir, yıllık olarak tekrarlanan bir günün insan anlayışıdır. Zaman içinde tek bir noktayla temsil edilmeyen birçok zaman insan fikri vardır.
kevin cline

9

Tarihler ve saatler, içeriğe bağlı olarak birçok farklı şeydir ve tüm kullanım durumlarını kapsayacak şekilde birçok ayrı türe ihtiyacınız vardır.

DateTimeBirçok dilde mevcut olan tür, zamanın kesin bir noktasını temsil eder ("anlık zaman"). Bunun ötesinde, çoğu zaman belirsiz ve içeriğe bağlı olan, takvim günleri, yinelenen tarihler, aylar, yıllar vs. gibi bir dizi göreceli veya "insan" zaman ve zaman dilimi kavramına sahibiz. Bu türler evrensel olarak yararlı değildir, ancak takvimler, zamanlama araçları ve insanın zaman kavramıyla etkileşime giren diğer uygulamalar gibi belirli uygulama alanlarında gereklidir.

Bir takvim uygulaması gibi bir şey yazıyorsanız , daha zengin bir zaman türleri kümesi sağlayan Joda-time gibi bir kütüphane kullanmaktan kesinlikle faydalanabilirsiniz . Örneğin LocalDate, zamanı olmayan bir tarih. Bu, DateTimezaman bölümü sıfıra ayarlanmış olandan farklı bir semantikliğe sahiptir , çünkü DateTimeyine de belirli bir zaman diliminde (belirli bir saat diliminde gece yarısı) belirli bir zaman noktasını LocalDatebelirtirken, tüm günü gösterir ve belirli bir saat dilimine bağlı değildir. Bu aynı zamanda doğrudan birini diğerine çeviremeyeceğiniz anlamına gelir.

LocalDateDateTimesaat dilimlerinin hesaba katılması gerekmediğinden kesinlikle daha basittir , ancak diğer meselelerin farkında olmalısınız, örneğin şu anki tarih bir zaman dilimini geçtiğinizde gerçekte geriye gidebilir ve zamanın aynı anında farklı zaman dilimlerindeki farklı tarihlere karşılık gelir. Ağa bağlı veya web uygulamalarında yerel tarihler kullanıyorsanız, bu konularda çok dikkatli olmalısınız. Saat bölümünü bir tarihten kaldırmak, saat dilimlerinin temel sorununu çözmez! Tarihsel tarihler ve farklı kültürleri dikkate alırsanız, daha da zorlaşır, çünkü aynı tarih, zaman zaman çılgınca farklı olaylara karşılık gelebilir, yani Julian ve Gregoryen takvimi.

Şimdi, dillerin neden LocalDate yerleşik birşeye sahip olmadığını soruyorsunuz . Öncelikle, SQL ve Visual Basic gibi bazı diller, zaman kısmı olmayan bir tarih türüne sahiptir. Java da LocalDateson sürümde bir ekledi . Ancak .Net gibi diğer platformlar yok. Yalnızca dil tasarımcıları bunun neden standart kütüphaneye dahil edilmediğini gerçekten cevaplayabilir, ancak benim tahminim "anlık zaman" ın kavramsal olarak basit ve evrensel olarak faydalı olduğunu, diğer zaman kavramlarının ise sadece belirli uygulama alanları için yararlı olduğunu (takvimler vb. .). Bu nedenle, uygulama geliştiricisinin daha karmaşık kullanım durumlarını ele almak için özel türler yazmasına izin vermek veya bir üçüncü taraf kütüphanesi (Joda-time gibi) tarafından ele alınmasına izin vermek mantıklıdır.


5

DateTime değerlerini gerçekten "sadece bir gün" olan veri kümeleri için kullanmak zorunda kaldığım için gülünç oluyorum. Doğum günleri en yaygın örnek olarak görülmektedir, ancak bu her zaman iş uygulamalarında ortaya çıkmaktadır.

Bunun nedeni, takvimin karmaşık olması ve çok farklı şekillerde kullanılmasıdır, çünkü hiç kimse, birçok alanda yararlı olacak kadar basit ve genel bir sınıf bulamamıştır.

Programlama dillerinde yaygın olarak bulunan tarih türü, bir bilgisayar sistemindeki işlemleri doğru bir şekilde tarihlemek için kullanılabilir. Diğer kullanım durumları özel bir kütüphane gerektirebilir.

İşte takvimlerle ilgili, karmaşıklıklarını gösteren kısa bir gerçek listesi - çoğu tarihi, bu nedenle dikkatinizi 1.1.1970 tarihinden sonraki tarihlerle sınırlarsanız, bundan etkilenmeyeceksiniz. Bununla birlikte, başvurunuzun 19. yüzyılın sonlarından önce gerçekleşen tarihlerle çalışması gerekiyorsa, bu gerçekler önemli olacaktır. Muhtemel kullanım örnekleri her türlü tarihi veri tabanlarıdır (kitaplar, şecere), fakat bugün hala faaliyette olan büyük şirketlerin veya organizasyonların varlıklarıdır.

Tüm bu gerçekler mükemmel dan cinsindendir SSS Julien Signolles tarafından yazılan OCaml için takvim kütüphanede buldum.

  1. Jülyen takvimi Julius Caesar tarafından MÖ 45'de tanıtıldı. 1500'lere kadar, ülkeler Gregoryen takvimine geçmeye başladıklarında yaygın olarak kullanılıyordu (bölüm 2.2). Bununla birlikte, bazı ülkeler (örneğin, Yunanistan ve Rusya) 1900'lerde kullandı ve Rusya'daki Ortodoks kilisesi, bazı diğer Ortodoks kiliselerinde olduğu gibi hala kullanıyor.

  2. Julian’dan Gregoryen takvimine geçiş aynı şekilde gerçekleşmedi ve değişim yılına bağlı olarak, 10 ila 13 gün düştü. Mesela Fransa'da 9 Aralık 1582, 20 Aralık 1582 ve Yunanistan'da 9 Mart 1924, 23 Mart 1924 takip etti.

  3. Modern çağda bile, bir kaç alıntı yapmak için birçok farklı takvim (Gregoryen, Ortodoks, İslami ve Çince) kullanılır; bu, yıl ve yıldönümlerini veya tarihi dini kutlamaları hesaplamak için farklı yollar kullanır.

Şimdi, genel ticari işlemler için yararlı olan işlemlerle birlikte gelen bir tarih türü için umut veriyorsunuz. Genel iş operasyonları diye bir şey yoktur sanırım. Örneğin, finans dünyasında hesaplamamız gerekiyor:

  1. Yıl kesirleri (“6 ay” gibi, “0,5” 'e tekabül eder), belirli bir süre için bir kredinin fiili faizini hesaplamak için bir faiz oranıyla birlikte kullanılır. Bu fraksiyonları hesaplamak için 6 ila 10 adet tarif vardır, her biri artık yılın uzunluğunu idare etme şekillerine, dönemin Şubat ayının son gününe göre pozisyonunu ve ayın süresine göre değişir.

  2. Tarih haddeleme, yıldönümlerini hesaplarken, bir yıldönümünü bir tatil gününden bir iş gününe geçirmek için bir iş takvimi ve bir kural (6 farklı kuraldan oluşan bir kural kümesinden) kullanırız.

Finans endüstrisinde çalışan insanlar için, tüm bu işlevleri ve kuralları uygulamayan herhangi bir takvim tipi işe yaramaz. Diğer birçok endüstrinin, takvim üzerinde özel hesaplamalar gerektiren başka tür alışkanlıklara ve sözleşmelere sahip olma olasılığı yüksektir.

Bir Date sınıfının tanımlanmasında açıkça bir zamanlama uygulaması olarak tasarlanan bir uygulamada değer var mı, yoksa "her zaman öğleye ayarlanmış" en iyi yaklaşım mı? DateTime kullanmak ve Time bileşenini Noon olarak ayarlamakla ilgili neler olabilir? Saat diliminin kayması böyle bir yaklaşımla açıklanabilir mi? MomentJS kullandım ama bence bu daha iyi bir Date sınıfı.

Tek bir takvim gününü izlemeniz gerekirse, en iyi yol muhtemelen o takvim gününün Jülyen gününü temsil eden büyük bir tamsayı kullanmaktır. Jülyen günden takvim gününe ileri geri dönüştürme algoritmaları - yıl, ay ve takvim ile tanımlanır - bunları uygulamanızda kolayca uygulayabilmeniz için - yaygın olarak bilinir ve ayrıntılı olarak test edilir, Bazı 29 Şubat'ta meydana gelen bir olayın yıldönümünü hesaplamak için dava.


2

Bence yukarıdaki cevabındaki Mike Nakis, genel olarak zamanın mutlak ölçülen bir koordinat olduğunu ve söz konusu zaman koordinatının soyutlanmış bir temsili olduğunu varsayarak, genel olarak zamanın mutlak ölçülen bir koordinat olduğunu açıklamaktan daha iyi bir iş çıkardığını düşünüyorum.

Haftanın Gününe yalnızca zaman içindeki gerçek bir noktanın bir modüllü temsili olarak atıfta bulunurken bu tür temsillerle konuşursunuz. Gerçekte, bundan biraz daha karmaşıktır. Belirli bir süre için Haftanın Günü'nü döndürecek bir işlev yazmakla görevlendirilmişseniz, bu tür bir algoritmaya girdi olarak ihtiyaç duyacağınız aşağıdaki bilgileri göz önünde bulundurun. Zamandaki noktayı, Takvimi, dikkate alınacak zaman dilimini (aklınızda bulundurun, saat dilimlerinin TÜM ZAMAN'ı değiştirmesini ve böylece etkili zaman diliminin belirli zaman koordinatlarında sona erdiğinde ne zaman başladığını bilmeniz gerekir.) onlarınkileri değiştirdiler!) ve Yaz Saati uygulaması geçerliyse, bu zaman içinde de değişir. Şimdi yerel saat diliminde bir DateTime verilip verilmediğini düşünün,

Bu görünüşte basit sorunun gerçekten ne kadar karmaşık olabileceğini görebilirsiniz.

Deneyimsiz geliştiriciler tarafından yazılmış bir ürün için ziyaret planlaması uygulamasında tüm hataları tespit eden bir noktada ayakkabınızda olduğum gibi hissettiğiniz acıyı biliyorum. Her şey hurdaya atılmalıydı.

Zaman gerçekten bir koordinattır, ancak yalnızca bir Tarihin yanı sıra, aşağıdakiler gibi gerekli olabilecek diğer zamana duyarlı verileri de göz önünde bulundurun:

Süre: Belirtilen belirli bir zaman koordinatı olmadan bir zaman uzunluğu veya geçişi anlamına gelebilecek bir milisaniye aralığı. Bir kullanım durumu olabilir

Bir kullanıcı olarak, bu görevin diğer Çarşamba günleri gece yarısı işinin tamamlanmasından 15 saniye sonra yapılmasını istiyorum.

Aralık: İki özel zaman koordinatı arasındaki zaman aralığı. Bir aralığı düşünmek isteyebileceğiniz bir kullanım durumu.

Bir kullanıcı olarak, her ayın belirli bir zaman diliminde yer aldığını görmem gerekiyor.

Yapmak istediğim bir diğer hızlı nokta ise, zamana dayalı veriler için Kayan Nokta sayıları hakkında bir yorum yapmanız ve bununla ilgili tavsiyelerde bulunmak. Kayan nokta aritmetiği kaçınılmaz olarak, zaman için gerektiği kadar kesin bir ölçüm vermeyebilecek yuvarlama hatalarına neden olur.

Sonuç olarak, bu bilgilerin tümü kaçınılmaz olarak aşağıdaki tasarım hususlarına yol açmaktadır:

  • Zaman içinde belirli noktalar veya aralıklar UTC'de veya gerektiğinde kolayca UTC'ye geri çekilebilecek kadar yeterli bilgi içeren bir veri tipinde devam etmelidir.
  • Uygulama mantığı, UTC veya bir dizi UTC koordinatını, son kullanıcı için daha sindirilebilir olan temsili bir veri durumuna biçimlendirmek için yazılmalıdır.
  • Önemli süreler milisaniye olarak sürdürülmelidir
  • Zamanla ilgili herhangi bir verinin görüntülenmesinde yerele özgü veya son kullanıcı tercihleri, ek veri olarak sürdürülmeli ve bir ekran seçeneği gibi değerlendirilmelidir. (Örneğin, Kiosk A, Merkezi Saat Dilimi, Askeri Saat biçimi veya Kullanıcı B tercihleri, Tel Aviv'de Standart Saat (GMT + 7: 00) saat dilimi, vb.)
  • FP numaralarından kaçının

1
Bunların hiçbiri "kaçınılmaz" değil. Birçok uygulama için yaygın olabilir, ancak Büyük Hadron Çarpıştırıcısı nanosaniye ölçeğindeki olaylarla ilgilenir. Sistem zamanları mikrosaniyelere taşındı, çünkü milisaniye yeterli hassasiyete sahip değil. Takvim uygulamalarının, etkinliği oluşturduğunuz aynı saat diliminde olsanız da olmasanız da, yerel bir takvim gününde gerçekleşecek bir tarih kavramı olması gerekir.
Alan Shutko

1
@AlanShutko Ve evet, gerekli olan "ek veriler" yerel saat dilimi, Günler ve ele alınması gereken diğer önemli veriler. Bunların hepsi sadece soyutlamalardır, ancak zamandaki nokta algoritmanız için önemli olmasa bile, zaman içindeki tek bir noktaya kadardır. Nanosaniye ve hatta mikrosaniye ölçeğine gelince, cevabım web ve LOB tipi yazılımlara yöneliktir. Tercih edilen LHC dilinin C # veya Javascript olduğundan şüpheliyim.
maple_shaft

1
Milisaniye, tekrarlanabilir fiziksel işlemler için mükemmeldir. İnsan etkinliği için, bazen uygun birim nominal günlerdir, örneğin günün sonunda gönderilirse, üç gün sonra varış noktasında kullanılabilir.
kevin cline

Geçmişte, zaman koordinatları için 64-bit kayan nokta sayıları kullanmayı ve zaman aralığı için daha önemlisi, çünkü küçük miktarları büyük bir hassasiyetle ifade etmenize izin veriyorlar. . (Peki ya Dinozorlar 65 milyon yıl önce ölmüşlerse ya da birkaç yıl sonra ölmüşlerse?) Peki neden bunlardan kaçınmaları gerektiğini söylüyorsunuz?
Mike Nakis

Mike, endişesinin FP matematiği ile kaçınılmaz bir şekilde yuvarlama değerlerinden ikili değerlere dönüştüğünü düşünüyorum. Örneğin, 0.3 ikili bir FP numarası olarak ifade edildiğinde tekrarlayan bir ondalıktır ve bu nedenle tam olarak gösterilemez. Kapasiteyi kaçırmıyorsunuz, ancak hassasiyeti kaçırıyorsunuz.
Michael Blackburn

2

Kısacası, çoğu bilgisayar tabanlı zaman türleri, zaman ve zaman dilimi sorununu doğru bir şekilde ele almaya odaklanmıştır.

Her zamanki yaklaşımla iyi karşılanmayan 2 kenar vakası vardır. Yerel saati kullanarak gün ışığından yararlanma değişikliğinin diğer tarafında olan bir zaman noktasını belirlemek, daha sonra UTC'ye daha düşük bir soyutlama katmanı ile dönüştürülür ve toplantı için 1 saat erken / geç olur.

Diğeri (soruya göre), bir kişinin doğum tarihini kaydetme gibi keyfi tarih bilgilerini modellemedir. İki kişinin aynı anda doğduğunu, biri Yeni Zelanda'da, diğeri Hawaii'de olduğunu düşünün. Olasılık, pasaportlarında farklı doğum tarihlerine sahip olmaları ve Hawaii'de doğan kişinin Yeni Zelanda'ya taşınması durumunda, aynı zamanda yaşamış olmalarına rağmen Yeni Zelanda'da doğan kişiden bir gün daha yaşlı olarak kabul edilmeleridir.

Tarihin öğlen vakti olması için tarih belirleme konusundaki öneri, UTC çalışacak, her yerde ALMOST. UTC ofsetleri -12 ile +14 arasındadır, bu nedenle pasifikte bu yaklaşımın başarısız olacağı birkaç yer vardır. Bu veri türlerini bir yyyymmdd biçiminde dizeler olarak ele alma eğilimindeyim ve iki tarih arasında karşılaştırma hesaplamaları yapmam gerekiyorsa, bu güvenli bir şekilde dize karşılaştırması olarak yapılabilir. Delta karşılaştırmaları yaparken (örneğin tarih ile şimdi arasında veya X yaşına gelinceye kadar), tüm tarihlerin aynı UTC ofsetinde oluşturulmasını sağlamalısınız ve daha sonra işi yapmak için standart zaman işlevlerini kullanmalısınız.


3
" Ben yyyyaagg biçiminde, dizeleri olarak bu veri türlerini tedavi etmek eğilimindedir ve iki tarih arasındaki karşılaştırmalar hesaplamaları yapmak için varsa, bu güvenle bir dize karşılaştırma olarak yapılabilir. " Bu kesin sesler bir benzeri Dateveri türü, sadece taşınırken aString
Ross Patterson

Dediğiniz gibi, bir tarihin dize olarak gösterilmesi ve orijinal posterin aksine, tarih UTC + 13 saat diliminde olmasından dolayı değişmez.
Michael Shaw,

2

Neden gerçek bir “Sadece Tarih” veri türü yok?

Aynı nedenlerden dolayı, DateTime değerlerinin UTC'de genel olarak belirtildiğini düşünüyorum: Sadelik ve güvenilirlik . DateTime değerinin noktası, zaman dilimi, gün ışığı tasarrufu, takvim ve diğer yerel ayarlardan etkilenmeyen, zaman içindeki tek bir noktayı belirtmektir. DateTime değerleri, bir zaman dilimi veya bir zaman dizisi değil, bir anlık (türün çözünürlük sınırına kadar) belirtir. Bu sınırlamalar, DateTime değerlerini güvenilir, tahmin edilebilir ve karmaşık olmayan bir şekilde karşılaştırmayı mümkün kılar.

DateTime değerine sahip bir tarih belirtmeye çalışmak, bir alanı belirtmek için bir nokta kullanmaya çalışmak gibidir."Bu nokta, 100 m yarıçaplı bir dairenin merkezini temsil eder" gibi bir kongre kullanarak bu işi yapabilirsiniz, ancak burada çok fazla sorun var: herkesin aynı kongre kullanması gerekir, bir demet yazmanız gerekir Yanlış tipte çalışmayı daha az acı verici hale getirmek için destek kodu ve bir noktada konvansiyonel alandan daha büyük veya daha küçük bir alan belirlemeniz gerektiği hemen hemen garanti edilir. Yani tarihlerle birlikte: 'öğlen'i tarihleri ​​belirlemek için geleneksel zaman olarak kullanabilirsiniz, ancak daha sonra saat dilimlerine girersiniz, çünkü insanlar UTC yerine yerel saatlerinde tarihleri ​​belirtmeyi beklerler. Tarih belirtmek için bir DateTime kullanmak için tatmin edici bir yol bulsanız bile, kesin bir tarih mi yoksa akraba mı olduğunu bilmek için daha fazla bilgiye ihtiyacınız olacak: 4 Temmuz mu, 1776 ya da her 4 Temmuz? Ya başka bir dönem kullanarak tekrarlamak istersen? Takvimlerde her türlü çılgın sorun vardır: bazı aylar diğerlerinden daha uzun, bazı yıllar diğerlerinden daha uzun, bazı günler diğerlerinden daha uzun, ve bazı takvimler arasında boşluklar var. Bu sorunları sadece günlerce çözmek istemezsiniz, çünkü aynı sorunlar daha kısa süreler boyunca ortaya çıkar: Muhtemelen "her 4 saatte bir 1 hap al" ifadesini yazıp " Grup her üç Cuma günü toplanıyor. "

Yani, tarihlerle çalışmakla ilgili çok fazla karmaşıklık var. Zaman içinde bir noktayı belirten ve sayı olarak yaptığınız şekilde çalışan bir tür sağlamak nispeten kolay (hedeflenen amaç yok), ancak tarihlerin kullanıldığı tüm yolları ele alan bir tür sağlamak son derece zor.

Diğerleri işaret gibi, orada olan tarihlerde iyi destek sağlayan diller ve kütüphaneler ve onları tam olarak doğru tarih-ilişkili kodu almak için oldukça zor verilen kullanmak genellikle iyi bir fikirdir.


2
"Tarihlerin kullanıldığı tüm yolları ele alan bir tür sağlamak zor." Doğru, bu yüzden hepsini yapmak için tek bir tür sağlamaya çalışmak korkunç bir fikir. İlk Java sürümleri sadece java.util.Date tarafından sağlandı ve sonuç korkunçtu. Sonra karmaşık bir java.util.Calendar hiyerarşisi eklediler ve daha iyi olmadı.
kevin cline

1
@kevincline Tamamen katılıyorum. OP bir dil belirtmedi, ben de genelliği hedefliyordum.
Caleb

" Aynı nedenlerle, DateTime değerlerinin genellikle UTC'de belirtildiğini düşünüyorum " ... Ah, bu doğru mu? 2015, ve yazarın evindeki saat dilimini kullanarak hala çok fazla kod yazılıyor :-(
Ross Patterson

1
Gerçekten, tarihleri ​​çevreleyen genel kabul görmüş bir kongre olmadığını neden merak ediyordum. "Bir bölgeyi temsil etmek için bir noktayı kullanmak", benim hayal kırıklığımı mükemmel bir şekilde kapsıyor.
Michael Blackburn

2

Neden gerçek bir “Sadece Tarih” veri türü yok?

Çeşitli diller için çeşitli kütüphanelerde bu tür birçok tür vardır. Şu anki diliniz için neredeyse kesinlikle bir tane var. Java util paketinin zaman hesaplamaları için korkunç bir API'si vardı, ancak java.time paketinin tanıtımı hayatı çok daha iyi hale getirdi. Yıl-ay-gün değeri içeren java.time.LocalDate veya yalnızca bir ay ve gün numarası içeren java.time.MonthDay'e bakın.


1

Calendrical manipülasyon, hesaplamanın en kötü anlaşılan yönlerinden biridir. Konuyla ilgili tüm kitaplar yazılmıştır. @MichealBlackburn, yeniden yorumlamaya tabi olan bir zaman çizelgesinde bir noktaya kadar çözülmeyen, yalnızca tarihe ait bir veri türü istemek konusunda kesinlikle haklıdır. Tarihsel olarak, bir tarihin anlamı ile ilgili meşru anlaşmazlıklar vardı. Birinin ne kadar karmaşık olabileceğini bulmak için Gregoryen takviminin kabul edilmesinden başka bir şeye bakmamalı. Dahası, yıllardır her zaman 1 Ocak'ta başlamamış, hatta batı Avrupa’da ve sömürgelerinde bile ( örneğin , İngiltere ve İngiltere’nin yılı 25 Mart’ta başladı).


1
Bu doğru. Cevabımda alıntı yaptığım SSS takvimi, klandar manipülasyonlarının karmaşıklığını ve inceliklerini4s keşfetmek için mükemmel bir kaynaktır
Michael Le Barbier Grünewald

-2

Cevap olarak:

Dürüst olmak gerekirse, neden hemen hemen her dilin bunun için sadece bir veri türü olduğunu bilmek istiyorum.

En yaygın neden "gerekli olmadığından" olabilir. Saatleri, dakikaları, saniyeleri, vb. Umrunda olmayan bir tarih saatini istiyorsanız, bu şekilde başlatırsınız:

date = new DateTime(year, month, day, 0, 0, 0);

İsterseniz DateTime uygulamasını kendiniz genişletebilirsiniz:

public class Date extends DateTime {
    ...
    public Date(int year, int month, int day) {
        this(year, month, day, 0, 0, 0);
    }
}

Not: Varsayılan zaman ve saat dilimini bilerek yok sayıyorum. Onları neye ayarladığın önemli değil, onlar için aynı Date. UTC için bir dava açabilirsiniz. Sunucunuzun oturduğu saat dilimini kullanmak için bir dava açabilirsiniz - her iki şekilde de, bunun gibi kesin olmayan bir değeri temsil etmenin önemli olduğunu düşünmüyorum Date. Varsayılan zamanla aynı - 0 yapabilir, öğlen yapabilirsiniz. Önemli değil. Facebook bana 00: 01'de bir doğum günü bildirimi gönderirse, ancak 23: 59'da doğdum. Gerçekten umrumda değil ve 12 saatten fazla oldukları için kırılmayacağım.

Yukarıdakiler Java’dadır ancak DateTimekalıtımı olan ve herhangi bir dilde benzer şekilde çalışacaktır . Java aslında bunu çözmenin sayısız yoluna sahiptir ve yukarıdakiler kullanımdan kaldırılmıştır ( Calendarşimdi kullanmanızı istiyorlar ). Başkaları yorumlarda yayınlanmıştır gibi, bazı diller aslında yok bir sağlamak Datesadece bu nedenle muhtemelen sınıf.

Her ihtimalde, her Dateuygulama muhtemelen sadece dil için bir sarmalayıcıdır DateTimeve zamanı sıfırlar. Aksi takdirde, iki Tarih / DateTimes arasındaki gün sayısı ya da iki kişinin Dateeşit olup olmadığı gibi sorunları çözmek için yinelenen koda ihtiyacınız olacaktır (Peki ya 29 Şubat ve 1 Mart?). Bu tür şeyler genellikle DateTimesınıfta çözülür . Aynı kodu tekrar kullanmak için bir anlam ifade eder Date.


4
-1: Sadece yıl + ay + gün istiyorsanız LocalDate kullanın. DateTime'ı bu amaç için kullanmak, başka bir programcının DateTime'ı gördüğünde ve zamanın bir anını temsil ettiğini varsaydığında hatalara yol açacaktır.
kevin cline

@kevincline Bunun gerekli olmadığını düşündüm çünkü bu soru dille ilgili. Ayrıca "Onaylanmadı" etiketli kodu kullanmanın kendi sorumluluğunuzda bir kullanım senaryosu olduğu açık olduğunu düşünüyorum. Daha da önemlisi, sadece bir şeyin bir örnek olarak, bir dil nerede bir senaryoda yapabileceği kullanılan gelmez bir var LocalDateya Datetip sınıfı ve 'roll-your-kendi' gerekiyor.
Shaz

1
Ancak zamanla ilgili iş kurallarını içeren (fiziksel zamanın aksine) net ve doğru kod için "gereklidir". Eğer kütüphane nominal süre için bir tür sunmuyorsa, programcının bunları icat etmesi ve bunun "DateTime" ile başlamaması gerekli olacaktır.
kevin cline

@kevincline Kodun daha az net veya özlü olacağını nasıl göremiyorum. Arasında bir görüş programcının noktadan fark nedir new Date(2000, 1, 1);ve new Date(2000, 1, 1);? Hangisinin altında boş saat, dakika ve saniye olduğunu söyleyebilir misiniz? Ekstra işlevlerin gösterilmesinden endişeleniyorsanız (setMinutes () gibi), sonradan devralmak yerine Datesarım yolunu DateTimeizleyebilir ve ardından yalnızca setYear, setMonth, setDay, vb. kullandığınız kitaplığın DateTime sürümünden daha doğru.
Shaz

Geçmişim, büyük ölçüde LocalDate ile aynı yapıya sahip olmayan C #. Görünüşe göre sadece DateTime’ı yapıyoruz.
Michael Blackburn
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.