9 Şubat 2014 Pazar

İki Tarih Arasındaki Fark - Zaman Aralığı

Not : DateTime İşlemleri Yazısı çok uzun olduğu için içeriğin bir kısmını buraya taşımayı uygun buldum.
Giriş

İki tarih arasındaki fark ile zaman eksenindeki iki noktanın arasındaki mesafeyi ölçüyoruz. Bu mesafe bir çok birim cinsinden ifade edilebilir. Yıl, ay, hafta, gün, dakika vs. gibi.

İki tarih arasındaki farkı bulma amacımız bazen sadece mesafeyi ölçmek iken bazen de iki tarih aralığı arasına düşen kayıtları bulmak olabiliyor.

Bu yazının amacı verilen iki tarih arasındaki farkı yıl/ay/hafta vs gibi birimler cinsinden nasıl bulunacağını göstermek.

Ölçüm sonunda çıkan mesafeyi gösteren süre kavramı ile ilgili sınıfları Süre Temsili başlıklı yazıda bulabilirsiniz.

Aynı Saat Dilimindeki İki Tarih Arasındaki Farkı Ölçmek
C++
Yeni C++ ile chrono namespace'i içinde duration isimli bir sınıf var. Bu sınıf zaman aralığını temsil ediyor. Kullanım kolaylığı için diğer typedef'ler de aşağıdaki gibi tanımlanmış.

namespace std {
namespace chrono {
typedef duration<signed int-type >= 64 bits,nano>        nanoseconds;
typedef duration<signed int-type >= 55 bits,micro>       microseconds;
typedef duration<signed int-type >= 45 bits,milli>       milliseconds;
typedef duration<signed int-type >= 35 bits>             seconds;
typedef duration<signed int-type >= 29 bits,ratio<60>>   minutes;
typedef duration<signed int-type >= 23 bits,ratio<3600>> hours;
}
}
Typedef'e verilen ilk tip - örneğin signed int - birimin tutulacağı primitif tipi belirtir, ikinci parametre olan ratio ise küsüratlı durumlarda saniyeye göre oranı belirtir. Örnekte yarım dakika double tutulacağı için ilk parametre double, ikinci parametre toplam değerin 30 saniye olması için ( 60 * 0.5) 60 tanımlanmış.

std::chrono::duration<double,std::ratio<60>>halfAMinute(0.5);
Bir diğer örnekte ise aşağıda

std::chrono::duration<long,std::ratio<1,1000>> oneMillisecond(1);

Java
TimeUnit sınıfı kullanılabilir.

Calendar cal = Calendar.getInstance ();
cal.clear ();
cal.set (2013,Calendar.MARCH,1);
Date start = cal.getTime ();
cal.set (2013,Calendar.APRIL,1);
Date end = cal.getTime ();
long days = TimeUnit.MILLISECONDS.toDays (end.getTime () - start.getTime ());

C#
C# ile verilen iki tarih arasındaki farkı bulmak için TimeSpan sınıfı var. Bu sınıfta aralığın başlangıç ve bitiş değerleri yok sadece mesafe bilgisi var.  Yani bu sınıf sadece tick'ler ile ilgileniyor.

    DateTime pastTime = //değer ata
    TimeSpan timeSinceContact = DateTime.Now - pastTime;

    // 14 gün geçmişse
    if (timeSinceContact.Days > 14){
    }

TimeSpan sınıfının en işe yarayan özelliklerinden birisi ise TotalSeconds.

Örnek:
 
boost
date sınıfı
Aşağıdaki örnekte iki tarih arasındaki gün farkı bulunuyor. boost'un date sınıfı kullanıldığı için sadece gün farkı bulunur. Saat hesabı yapılmaz.

time_duration sınıfı
Bu sınıf ile iki tarih arasında fark saat ve dakika olarak bulunabilir.
is_negative() , hours() ve minutes() metodları
Örnek:
using boost::posix_time::ptime;
const boost::posix_time::ptime utcNow = boost::posix_time::second_clock::universal_time();
const ptime localTime = boost::date_time::c_local_adjustor<ptime>::utc_to_local(utcNow);
const boost::posix_time::time_duration td = localTime -
utcNow;
td.is_negative(){...}
td.hours();
td.minutes()


ticks metodu
Bir başka örnekte iki tarih arasındaki fark saniye olarak hesaplanmış. Niçin total_seconds() metodu kullanılmamış bilmiyorum.

Joda

Özet

Joda'da aynı saat dilimindeki iki tarih arasındaki farkı ölçmek için bir çok sınıf kullanılabilir. Bu sınıflar temel olarak ikiye ayrılırlar. 

  1. İlk sınıf Period ismiyle anılır. Period'un bir çok alt türevi de mevcuttur. 
  2. İkinci sınıf ise Duration sınıfıdır.

Duration Sınıfı Nedir?
Duration sınıfı tanım olarak süre anlamına geliyor. Başlangıç ve bitişi tanımlı olmak zorunda değil. Period'dan farklı olarak milisaniye cinsinden çalıştığı için genellikle daha kısa aralıklar - 10 dakika vs. - gibi kullanılıyor. Zaten sınıfın açıklamasında "specifying a length of time in milliseconds." deniliyor.

Joda Period Sınıfı Nedir ?
Periyod tanım olarak başlangıç ve bitişi belli olan zaman aralığı anlamına geliyor. Duration'dan farklı olarak daha uzun aralıklar için kullanılıyor. 3 gün 2 saat gibi.

Joda Period ve  Alt Türevleri

Eğer amacımız 2 gün 3 saat 10 dakika gibi bir sonuç elde etmekse Period sınıfını kullanmak gerekir. Yok amacımız sadece 2 gün bilgisini elde etmek saat,dakika bilgilerini dikkate almamak ise BaseSingleFieldPeriod sınıfından türeyen Months, Days,Hours, Minutes gibi sınıfları kullanabiliriz. Aşağıdaki sınıf hiyerarşisi bu durumu gösteriyor.



Joda Duration sınıfını Oluşturmak
Duration sınıfını oluşturmak için iki tane tarih kullanılabilir. Örnek:
DateTime startTime,endTime;
Duration d = new Duration (startTime,endTime);

Joda Period Sınıfını Oluşturmak
Period sınıfını oluşturmak için iki tane tarih kullanılabilir. Örnek :

Joda PeriodType Sınıfı

Bazen farkı bulurken belli birimleri görmek istemeyiz. Bu durumda PeriodType sınıfını aşağıdaki örnekteki  gibi kullanabiliriz.
Period p = new Period(startDate, endDate,PeriodType.standard().withSecondsRemoved().withMillisRemoved());
Bu durumda aradaki farkı saniye ve milisaniye olmadan buluruz. Period sınıfı string'e dönüşürken de bu birimler yazılmaz.
 
Joda Period Sınıfı ve hours() toStandardHours() metodları arasındaki fark
Period sınfı iki tane saate çeviren metod içeriyor. Aralarındaki fark ise bu soruda açıklanmış. Eğer iki tarih arasındaki fark bir günden büyükse hours() ile sadece saat farkını alırız, geri kalan gün ise getDays() ile alınıyor. toStandardHours() ise toplam saat farkını veriyor.

Joda PeriodFormat Sınıfı
PeriodFormat sınıfı Period sınıfını string'e çevirmek için kullanılıyor. Örnek:
DateTime sd = new DateTime(1973,1,1,0,0,0);
DateTime ed = new DateTime(1973,1,31,23,59,59);
Period p = new Period(sd,ed);
//Çıktı olarak 4 weeks, 2 days, 23 hours, 59 minutes and 59 seconds verir
System.out.println(PeriodFormat.getDefault().print(p));
Joda PeriodFormatterBuilder Sınıfı
Bu sınıfı PeriodFormat sınıfını yaratmak için kullanılıyor. Örnek olarak aşağıdaki kod parçasını buradan aldım.
PeriodFormat sınıfı ile verilen Period'u istenilen formatta yazdırma
Timer - How do I calculate the difference between two dates using Joda Time? örneğinde ise
DateTime dt = new DateTime();
DateTime twoHoursLater = dt.plusHours(2).plusMinutes(10).plusSeconds(5);
Period period = new Period(dt, twoHoursLater);
PeriodFormatterBuilder HHMMSSFormater =
        new PeriodFormatterBuilder().appendHours().
                                     appendSeparator("-").
                                     appendMinutes().
                                     appendSeparator("-").
                                     appendSeconds();
System.out.println(HHMMSSFormater.toFormatter().print(period));
PeriodFormat sınıfı ile verilen metini Period olarak okuma
Örnek:
Önce PeriodFormatBuilder kullanılarak bir PeriodFormat sınıfı oluşturuluyor ve  PeriodFormat sınıfının parse() metodu kullanılarak metin Period sınıfına çeviriliyor.

Joda SingleFieldPeriod Türevleri (İki tarih arasındaki fark)
Period ile iki tarih arasındaki farkı bir çok birim cinsinden alabiliyoruz.Eğer sadece tek bir birim cinsinden farkı öğrenmek istersek aşağıdaki sınıfları kullanabiliriz. 

Seconds
Seconds sınıfı saniye farkını bulur. Örnek:
int seconds = Seconds.secondsBetween(rightNow, targetDateTime)
Minutes
Minutes sınıfı dakika farkını bulur. Farkı bulurken time zone bilgisinin etkisiz olduğunu anlatan bu soru da oldukça bilgilendirici.



Hours
Hours sınıfı saat farkını bulur.
int hours =Hours.hoursBetween(new DateTime(today), new DateTime(StartTime1)).getHours();

Days
Days sınıfı daysBetween() metodu ile gün farkını bulur.
Bir başka örnek

Months
Örnekte iki tane tarih arasındaki fark ay cinsinden bulunuyor.
 
SQL
dobs tablosundan dob sütununu çekip sistem saatine bakarak ikisi arasındaki yılı bulan kod aşağıda.
select floor(months_between(sysdate,dob)/12) from dobs;
 

Hiç yorum yok:

Yorum Gönder