21 Aralık 2010 Salı

Tarih ve saat hesaplamaları

Gündelik yaşamımızda kullandığımız gerek takvim sistemi gerekse zaman sistemi gerçekten bir çok karılışlığa yol açacak biçimde profesyoneller tarafından hazırlanmış sanki. Her senenin artık yılı Şubat'ın 4 yılda bir 29 çekmesi her bahar takviminde saatlerin 1 saat ileri/geri alınması ve benzeri bir çok problem var. Ama asıl problem rakamların döngü aralıklarının farklı olmasında. Her 60 saniyede 1 dakikanın, her 60 dakikada 1 saatin her 24 saatte bir gün olması problemi yetmezmiş gibi bazı aylar 30 bazıları 31 bazıları da 4 yılda bir 29 gün çekiyor. İşin moral verici kısmı hepsinin katı şartlara bağlı olması.


Tarih ile başlayalım. Saate göre hesaplaması daha zor demek gayet mümkün. Tarih hesaplamadaki başlıca 3 yöntemi ele alalım.

1. Örneksel tarih hesaplama
Bu yöntemde tarih direkt bir string olarak işlem görür. Hesaplanabilmesi için muhakkak ay, gün ve yıl olarak rakamsal biçime çevrilip kontrol edilmesi gerekir. Eğer yapılan işlemlerde insan eli değiyorsa hata çıkartma olasılığı çok yüksektir. Ayrıca fazladan hafıza alanı kaplarlar. Fakat programlama anında deneme ve log dosyaları oluşturmak için en iyi yöntem budur.
Örneğin 25/12/2005

2. Sınırlı aralıklı hesaplama
Tarih bilgisi gün, ay ve yıl olarak bitlere bölünerek hesaplanır. Bu biçimde aynı zamanda opsiyonel olarak saatte saklanır. 2 Byte tarih ve 2 Byte saat bilgisini içerir. Bu yönteme tipik örnek olarak, FAT sistemini verebiliriz. Bu yöntem ile 1980 öncesi veya 2107 yılları sonrası yazılamaz. Zaten o yıla kadar yaşamayız dediğinizi duyar gibiyim ama bir tarih kitabı yazıyorsanız yaşamış olmanız gerekmez 

Bitler – Belirttiği zaman
15..11 - Saat (0..23)
10..5 - Dakika (0..59)
4..0 – Saniye / 2 (0..29)

5..9 - Yıl (0 = 1980, 127 = 2107)
8..5 - Ay (1 = Ocak, 12 = Aralık)
4..0 - Gün (1..31)

3. Tarih ve Saati indis ile hesaplama
En ideal yöntemdir. Tarih veya Saat opsiyonel olarak ayrı ayrıda kullanılabilir. Tarih en küçük birim olan gün sayısı cinsinden yazılır. Kullanması biraz zahmet verici olsada bir çok hazır prosedur ve fonksiyon ile tarih ve saat üzerine bir çok işlem yapmanıza olanak sağlayacaktır. Taban tarih olarak 30.12.1899 saat 12.00am olarak alınır. Yani 0 rakamı bu tarihi ifade eder. Buna göre 1, bir gün sonrası 31.12.1899 saat 12.00am anlamına gelir. Bu tarih biçimi double değişken tipinde tanımlanır. Bilgiğimiz üzere dobule sayı tipi 8 byte, küsüratlı ve işaretli sayıları tutar. Bu şu anlama gelir, sayının tam kısmı günü ifade ederken ondalıklı kısmı ise saati ifade eder. (Saat biçiminde en küçük birim mili saniye olarak alınır)
Örneğin
20.12.1899 = -10
30.12.1899 = 0 (taban gün)
02.21.2006 = 38769
02.22.2006 = 38770
02.22.2006, 13:19:12 = 38770.555

(Tarih ve saat işlemleri ile ilgili bilgiyi konu sonunda görebilirsiniz)


Saat hesaplamaları Tarih hesaplamasına göre nisbeten daha kolaydır. Başlıca 3 yöntem

1. Örneksel saat hesaplama
Bu hesaplama türünde her saate karşılık gelen rakam 100 lük sayı biçimine çevirilerek saatin yüzdesi alınmış olur. Taban birim olarak dakika kullanılır. Bir dakika yaklaşık olarak 1.66 dır. İşlemler saatler ve dakikalar için ayrı ayrı yapılır ve sonuç dakika cinsinden öğrenilmek isternirse geri bölme yapılır.

Örneğin
16:40:00 ≈ 16.66 (40 x 1.66 = 66)
23:00:00 = 23.00 (0 x 1.66 = 0)
11:15:00 ≈ 11.25 (15 x 1.66 = 24.9)

Çıkan rakamlara kendi aralarında toplama ve çıkartma işlemi yapılabilir. Örnekteki rakamları toplarsak
16.66
23.00
11.25
______
50.91 buluruz.

Burada hassas bir nokta sonucun yüzdelik saat olmasıdır. Eldeki bu veri direkt bir matematik işlemi ile kullanılabilir. Sayı yakın oldugu rakama 2 basamak olacak şekilde yuvarlanır.

Örneğin 50.91 x 5YTL = 254.55 YTL

Sonuç geri dakika cinsinden bulunmak istenirse saat normal yazılır, noktadan sonraki kısım tekrar 1.66 ya bölünür.

91 / 1.66 ≈ 55 ıse 50 saatin yanina 55 dakika eklenir = 50.55

2. Saati birim zamana çevirerek hesaplamak
Zaman sisteminde ölçülebilirlik göz önüne alınarak optimum zaman birimi belirlenir. Genelde dakika yeterli olsada zaman birimi kısaltılarak saniyenin milyarda biri bile baz alınabilir. Mukemmel ölçü en kısa olanı olsa da gündelik kullanım için saniyeden fazlasına gitmeye gerek yok. Eğer amacımız sadece zamanı hesaplamaksa tarih için kullandığımız indis ile hesaplamayı saat içinde kullanabiliriz. Yinede formul olarak açıklamak gerekirse sırasıyla saat dakikaya, dakika saniyeye varsa saniye de mili ve micron saniyeye çevirilerek en küçük zaman birimine indirgenir. Fakat özel bir amaç yoksa bu kadar zahmeti çekmek çok anlamsız olabilir.

Örnek (Birim=saniye)
16:40:15 => 16*3600 + 40*60 + 15 = 60015sn
60015 / 3600 = 16sa (küsuratlı kısım atılır)
(60015 mod 3600) / 60 = 40 (küsuratlı kısım atılır)
60015 mod 60 = 15 sn

3. Tarih ve Saati indis ile hesaplama (devamı)
Tarih ve saat işlemleri üzerinde yapılabilecek başlıca işlemler (Delphi için)

DateTimeToFileDate: Indis ile verilen zaman tipini işletim sisteminin zaman tipine dönüştürür
DateToStr: Tarihi görüntüler
TimeToStr: Saati görüntüler

DayOfTheMonth (DayOf): Ayın gününü görüntüler (1..31)
DayOfTheWeek: Haftanın gününü verir (1=Pazartesi – 7=Pazar)
DayOfTheYear: Yılın kaçıncı günü olduğunu verir (1=Ocak 1, 33=Şubat 3, 365=Aralık 31)

DaysInAMonth: Verilen yıl ve ayın kaç gün olduğu (2000 Şubat=29 çeker)
DaysInAYear: Verilen yılın kaç gün olduğu (2000=366 gün)

WeekOfTheYear (WeekOf): Yılın haftasını verir (360=52. hafta)
MonthOfTheYear (MonthOf): Yılın ayını döndürür
YearOf: Tarih bilgisindeki yılı döndürür

DecodeDate: Zaman indisini tarih bilgilerini dönderir.
DecodeTime: Zaman indisinin saat bilgilerini dönderir.
DecodeDateTime: Zaman indisinin tarih ve saat bilgilerini dönderir.

EncodeDate: Girilen tarih bilgisini zaman indisine dönderir.
EncodeTime: Girilen saat bilgisini zaman indisine dönderir.
EncodeDateTime: Girilen tarih ve saat bilgilerini zaman indisine dönderir.

IncDay: Tarihi belirtilen gün kadar ileri veya geri döndürür.
IncHour, IncMilliSecond, IncMinute, IncSecond, IncWeek, IncYear.

HourOf: Zaman bilgisi içinde sadece saati döndürür
MinuteOf: Zaman bilgisi içinde sadece dakikayı döndürür
SecondOf: Zaman bilgisi içinde sadece saniyeyi döndürür

Now: Sistemin güncel zamanı (tarih, saat)
Date: Sistemin güncel tarihi
Time: Sistemin güncel saati


Daha fazla kaynak için Delphi DateUtils’e bakabilirsiniz...
----------------------------------------------------------------------------------------------
Övünç Mete - 22.02.2006 05:14:35




Cemaliozan

Delphi her türlü tarih fonksiyonu içeren DateUtils unitini içerir.
Aşağıda bu fonksiyonlardan en çok ihtiyacınız olacağınızı düşündüklerimi açıkladım.
Her fonksiyondan sonra, bir örnek ve örneğin döndüreceği değeri yazdım.
Böylelikle konu daha açık anlaşılacaktır.

Günün tarihini "03/09/2002" Salı, saatini ise "11:05:03" olarak kabul ettim.
Bu fonksiyonları kullanırken uses kısmına DateUtils'i eklemeyi unutmayın.

- CompareDate : verilen iki tarihi karşılaştırır. 1. tarih büyükse 1, küçükse -1, eğer iki tarihte aynı ise 0 değerini döndürür.

            CompareDate(Date -2 , Date) = -1

    NOT : Tarihler üzerinde direk toplama ve çıkarma işlemi yapabilirsiniz. "Date -2" iki gün öncesinin tarihini verecektir.

- CompareDateTime : verilen iki tarih ve saat içeren datetime değerini karşılaştırır.
1. değer büyükse 1, küçükse -1, her iki tarihsaat değeri aynı ise 0 döndürür.
Burada değerin aynı olması demek yıl'dan başlayark saliseye kadar tüm değerlerin aynı olması demektir.
- CompareTime : verilen iki saat değerini karşılaştırır. 1. değer büyükse 1, küçükse -1, iki değerde aynı ise 0 döndürür.
- CurrentYear : Geçerli yıl bilgisini 4 karakter olarak döndürür. 2002 gibi.

           CurrentYear = 2002

- Date : Geçerli tarihi döndürür.

            Date = 03/09/2002
- DateOf : Bir datetime değerini alarak bunun sadece tarih kısmını döndürür.
Aslında burada saat bilgisi silinmez, "00:00:00" yani geceyarısını gösterecek şekilde değiştirilir.
Yani tarih ve saat ayrılmaz ikilidir. Sürekli beraberdirler.
            DateOf ( Now ) = 03/09/2002

- DateTimeToStr : Verilen bir DateTime değerini string'e çevirir.

            DateTimeToStr ( Now ) = '03/09/2002 11:05:03'

- DateTimeToString : Verilen bir DateTime değerini istediğiniz formatta string'e çevirir.

            var
              Str : String;

              DateTimeToString(Str, 'd mmmm yyyy dddd, hh:nn', Now);
              ShowMessage ( Str );  = 3 Eylül 2002 Salı, 11:05

- DateToStr : verilen bir DateTime değerini string'e çevirir. Sonuçta sadece tarih verisi bulunur, saat olmaz.

            DateToStr ( Date) = '03/09/2002'

- DayOf : Verilen bir DateTime değerindeki günü döndürür. Yani sonuç 1 ile 31 arasında bir değer olabilir.

            DayOf ( Date ) = 3

- DayOfTheMonth : DayOf fonksiyonu ile tamamen aynıdır.

            DayOfTheMonth ( Date ) = 3

- DayOfTheWeek : Haftanın kaçıncı günü olduğunu döndürür. Pazartesi ise 1, Salı ise 2, ... Pazar ise 7 döndürür.

            DayOfTheWeek ( Date ) = 2

- DayOfTheYear : Yılın kaçıncı günü olduğunu döndürür.

            DayOfTheYear ( Date ) = 246

- DayOfWeek : Haftanın kaçıncı günü olduğunu döndürür.
Bu fonksiyonun farkı Pazar günü ilk gün sayılır.
Yani Pazar ise 1, Pazartesi 2 ... Cumartesi ise 7 döndürür.

            DayOfWeek ( Date ) = 3
- DaysBetween : verilen iki DateTime arasındaki geçen gün sayısını döndürür.
Bu fonksiyonda saatte önemlidir. 24 saat geçmiş olmalıdır.
Yani "02/09/2002 11:54:00" ile "03/09/2002 11:53:59" arasındaki gün sayısı 24 saat dolmadığı için 0 dır.
 - DaysInAMonth : Verilen yıl ve aydaki gün sayısını döndürür.

            DaysInAMonth (2002, 5) = 31

- DaysInAYear : Verilen yılda kaç gün olduğunu döndürür.

            DaysInAYear ( 2002 ) = 365

- DaysInMonth : Verilen tarihteki ayın kaç gün olduğunu hesaplar. Yani yıl ve ay değerini verdiğiniz tarihten alır.

            DaysInMonth ( Date ) = 30

- DaysInYear : Verilen tarihteki yılda kaç gün olduğunu döndürür. Yani yıl değerini verdiğiniz tarihten alır.

            DaysInYear ( Date ) = 365

- DaySpan : Verilen iki DateTime değeri arasındaki gün farkını bulur.
DaysBetween fonksiyonundan farkı, küsratlı değerler döndürür.
Yani iki tarih arasında 1 gün 23 saat ve 58 dakika fark varsa DaySpan : "1,998611" değerini döndürür,
DaysBetween gün tamamlanmadığı için 1 değerini döndürür.
- DecodeDate : Verilen DateTime değerini yıl, ay ve gün değerlerini döndürür.

            var
              Yil, Ay, Gun : word;

            DecodeDate ( Date, Yil, Ay, Gun);

- DecodeDateDay : Verilen DateTime değerinin yıl ve verilen tarihinde yılın kaçıncı günü olduğunu döndürür. 2002 ve 246. gün gibi.

- DecodeDateTime : Verilen DateTime değerinin yıl, ay, gün, saat, dakika, saniye, salise değerlerini döndürür.

            var
              yil, ay, gun, saat, dakika, saniye, salise : Word;

            DecodeDateTime ( Now, yil, ay, gun, saat, dakika, saniye, salise);

- DecodeDateWeek : Verilen DateTime değerinin yılını, yılın kaçıncı haftası olduğunu ve haftanın kaçıncı günü olduğunu döndürür.

- DecodeTime : Verilen DateTime değerinin saat, dakika, saniye ve salise değerlerini döndürür.

            var
              saat, dakika, saniye, salise : Word;

            DecodeTime ( Now, saat, dakika, saniye, salise);

- EncodeDate : Verilen yıl, ay, gün değerlerini birleştirip oluşan tarih değerini döndürür.

            var
              Tarih : TDateTime;

            Tarih := EncodeDate (2002, 10, 5); = 05/10/2002

- TryEncodeDate : Verilen yıl, ay, gün değerlerini birleştirip oluşan tarih değerini döndürür. Eğer yanlış değerler verilmişse fonksiyon False değerini geri döndürür, tarih başarıyla birleştirilmişse True değerini döndürür.

            var
              Tarih : TDateTime;

            if TryEncodeDate(2002, 10, 5, Tarih) then
              ShowMessage (' tarih başarıyla birleştirildi!');

- EndOfAMonth : Verilen yıl ve ayın son günü ve son anını döndürür.

            EndOfAMonth (2002, 5) = 31/05/2002 23:59:59

- FormatDateTime : Verilen DateTime değerini istediğiniz formatta göstermek için kullanılır.

            FormatDateTime ('d mmmm yyyy', Date) = '3 Eylül 2002'

- HourOf, HourofTheDay : Verilen DateTime değerinin saatini döndürür. Yani sonuç 0 ile 23 arasındadır.

            HourOf (Now) = 11

- HoursBetween : Verilen iki DateTime değeri arasında geçen saati döndürür. Fonksiyon 60 dakika tamamlanınca değeri arttırır. Yani 12:00:00 ile 12:59:59 arasındaki fark 0 (sıfır) dır, ancak 13:00:00 olduğunda 1 döndürür.

- HourSpan : Verilen iki DateTime değeri arasında geçen saati döndürür. Yukarıdaki fonksiyondan farkı saat tam olmasa bile değeri küsuratlı olarak döndürür. Mesela 12:00:00 ile 12:59:59 arasındaki saat farkı 0,9998 saat gibi.

- IncMonth : Verilen tarihi, istenilen ay kadar artırır veya azaltır.
      o Eğer parametre - verilirse önceki ayları döndürür. Örneğin -1 verilirse bir ay önceki tarihi döndürür.
      o Eğer parametre 1 den büyük bir değer verilirse o kadar ay sonrasını döndürür.
      o Eğer tarih arttırıldığı zaman verilen gün o ay içerinde yoksa, o ayın son günü döndürülür. Mesela 31/01/2002 tarihini bir ay artırırsanız şubat ayında 31. gün olmadığı için sonuç 28/02/2002 olacaktır.

            IncMonth ( Date ) = 03/10/2002

- IncDay : Verilen tarihi istenilen gün kadar artırır veya azaltır. Parametre + verilirse artırır, - verilirse azaltır.

            IncDay ( Date ) = 04/09/2002
            IncDay ( Date, 3 ) = 06/09/2002
            IncDay ( Date, -1) = 02/09/2002

- IncHour : Verilen DateTime değerinin saatinin istenilen değer kadar artırır veya azaltır. Benzer şekilde IncMinute, IncMilisecond, IncSecond fonksiyonları da vardır.

- IncWeek : Verilen tarihi istenilen hafta sayısı kadar artırır veya azaltır. Parametre + verilirse artırır, - verilirse azaltır.

            IncWeek ( Date ) = 10/09/2002

- IncYear : Verilen tarihin senesini istediğinz kadar artırır veya azaltır. Parametre + verilirse artırır, - verilirse azaltır.

            IncYear ( Date ) = 03/09/2003
            IncYear ( Date, -2) = 03/09/2000

- IsInLeapYear : Verilen tarihin artık bir senede (Şubat'ın 29 gün olduğu) olup olmadığını test eder.

            if IsInLeapYear (Date) then
              ShowMessage (' 2002 senesi artık yıl olmadığı için, bu mesajı asla göremezsiniz!');

- IsLeapYear : Verilen senenin artık sene (Şubat'ın 29 gün olduğu) olup olmadığını test eder.

            if IsLeapYear ( CurrentYear ) then
              ShowMessage (' Bu sene Şubat ayı 29 gün çekiyor');

- IsToday : Verilen tarihin bugünün tarihi olup olmadığını test eder. Aynı gün ise True döndürür.

            if IsToday ( Date ) then
              ShowMessage ( 'Date bugünün tarihini verdiği için bu mesajı görürsünüz');

- IsValidDate : Verilen yıl, ay, gün değerlerinin geçerli bir tarih olup olmadığını test eder. Örneğin ay 2 ve gün 30 ise, Şubat hiç bir zaman 30 gün olamayacağı için False döndürür.

            if IsValidDate (2002, 10, 1) then
              ShowMessage ('geçerli bir tarihtir');

- IsValidDateTime : Verilen yıl, ay, gün, saat, dakika, saniye, salise değerlerinin geçerli bir DateTime değeri olup olmadığın test eder. Geçerli ise True, değilse False döndürür.

            if not IsValidDateTime ( 2002, 13, 5, 11, 11, 11, 11 ) then
              ShowMessage (' ay hiç bir zaman 13 olamaz, 1 ile 12 arası bir değer olamlıdır!');

- IsValidTime : Verilen saat, dakika, saniye, salise değerlerinin geçerli bir saat değeri olup olmadığın test eder. Geçerli ise True, değilse False döndürür.

            if not IsValidTime (30, 11, 10, 1) then
              ShowMessage (' saat 23'' ten büyük olamayacağı için geçersiz bir tarihtir');

- MinutesBetween : Verilen iki tarih arasındaki dakika farkını verir. Dakika tam olduğu zaman değeri artırır. Örneğin 9:00:00 ile 9:00:59 arasındaki farkı 0 (sıfır) olarak döndürür.

- MinuteSpan : Verilen iki tarih arasındaki dakika farkını verir. Dakika tam olmasa bile küsuratlı olarak değeri döndürür. Örneğin 9:00:00 ile 9:00:59 arasındaki farkı 0,998 dakika gibi döndürür.

- MonthOf : Verilen tarihin ayını döndürür. Yani sonuç 1 ile 12 arasında bir değer olmalıdır.

            MonthOf ( Date ) = 9

- MonthsBetween : Verilen iki tarih arasındaki ay farkını verir. Ayların uzunlukları eşit olmadığı için bir ay 30.4375 gün olarak belirlenmiştir. Her 30.4375 gün için değer 1 arttırılır.

- MonthSpan : Verilen iki tarih arasındaki ay farkını verir. 1 ay yine 30.4375 gün olarak belirlenmiştir. Süre tamalanmasa bile küsuratlı olarak değeri döndürür.

- Now : Geçerli tarih ve saati döndürür.

            Now = 03/09/2002 11:05:03

- NthDayOfWeek : Verilen tarihteki günün, o ay içindeki kaçıncı iş günü olduğunu döndürür. Mesela gün Salı ve ayın ikinci Salısı ise 2 döndürür.

            NthDayOfWeek ( Date ) = 1

- StartOfAMonth : Verilen yıl ve aydaki ilk günün ilk anını döndürür.

            StartOfAMonth (2002, 5) = 01/05/2002 00:00:00

- StrToDate: Verilen stringi tarih değerine çevirir.

            StrToDate ('01/01/2002') = 01/01/2002

- StrToDateTime : Verilen stringi DateTime değerine çevirir.

            StrToDateTime ('01/01/2002 05:22:00') = 01/01/2002 05:22:00

- Time : Geçerli saati döndürür.

            Time = 11:05:03

- TimeToStr : Verilen saat değerini stringe çevirir.

            TimeToStr ( Time ) = '11:05:03'

- Today : Bugünün tarihini döndürür.

            Today = 03/09/2002

- Tomorrow : Ertesi günün (yarın) tarihini döndürür.

            Tomorrow = 04/09/2002

- YearOf : Verilen tarihin yılını döndürür.

            YearOf ( Date ) = 2002

- YearsBetween : Verilen iki tarih arasındaki yıl farkını döndürür.

- Yesterday : Bir önceki günün (dün) tarihini döndürür.

            Yesterday = 02/09/2002



DateUtils uniti içinde bunun en az iki katı daha fonksiyon var. Ben en çok kullandıklarımı ve lazım olabileceğini düşündüklerimi burada açıkladım. Listenin tamamını görmek için, Help'ten "date/time routines" kısmına bakın.

Hiç yorum yok:

Yorum Gönder