Windows BATCH dosyalarında tarih(DATE, DAY, MONTH, YEAR v.b.) bilgisinin bölgesel ayarlardan bağımsız olarak Gnuwin32 araçları ile formatlanması

Windows(2000, XP, 2003, Vista, 2008, Windows7) üzerinde BATCH dosyalar ile uğraşmak zorunda iseniz eninde sonunda Tarih bilgisine bağımlı olarak bir işlem yaptırmak zorunda kalmışsınızdır. Fakat eninde sonunda farkettiğiniz üzere DOS, Tarih bilgisinin Ay, Gün, Yıl, Saat, Saniye gibi spesifik bölümlerini ayrı ayrı göstermek için doğal metotlara sahip değildir. Bu durum da, örneğin 15 günden önceki bir tarihi seçmek gibi özel durumlarda çok ciddi sıkıntılara yol açmaktadır.

Ayrıca Bölgesel ayarları birbirinden farklı olan makinalarda, Tarih bilgisine bağımlı olan BATCH dosyaları çalıştırdığınız zaman sıkıntı daha da artmaktadır. Çünkü komut satırı üzerinden aldığınız tarih bilgisi tamamen bölgesel ayarlara bağımlıdır.

echo %date% komutunu Türkçe bölgesel ayarlara sahip bir Windows makina üzerinde çalıştırdığınızda aşağıdaki formatta çıktı alınmaktadır.
DD.MM.YYYY

Aynı komut İngilizce(Amerika) bölgesel ayarlara sahip bir Windows makina üzerinde çalıştırdığınızda ise aşağıdaki formatta çıktı alınmaktadır.
MM/DD/YYYY

Bu durumda, örneğin 15 günden önceki bir tarihi seçmek gibi bir işlemi birbirinden ayrı bölgesel ayarlara sahip makinalar üzerinde yapmak içinden tamamen çıkılmaz bir hal almaktadır.

Ama linux’un çok gelişmiş komut satırına ait birçok aracın windows versiyonlarını kullanarak bu sıkıntıyı aşabilmek mümkündür. Gerekli “date.exe” komutunu içeren açık kaynak kodlu GNU coreutils paketi bileşenleri aşağıdaki adreslerden indirilebilir.

http://sourceforge.net/projects/gnuwin32/files/coreutils/5.3.0/coreutils-5.3.0-bin.zip/download
http://sourceforge.net/projects/gnuwin32/files/coreutils/5.3.0/coreutils-5.3.0-dep.zip/download

Aslında bizim şimdilik sadece coreutils-5.3.0-bin.zip içerisinden “date.exe” komut satırı programına, coreutils-5.3.0-dep.zip içerisindende “libiconv2.dll” ve “libintl3.dll” kütüphanelerine ihtiyacımız bulunmaktadır.

GNU date komutu 1970 senesinden, içinde bulunulan ana kadar geçen saniyeleri gösteren(EPOCH) bir çıktı formatına sahiptir. Aşağıdaki BATCH file ile(test.bat diyelim…) istenilen sayıda gün öncesinin tarih bilgisine erişmek bu sayede son derece kolay olacaktır.

@echo off
for /f "tokens=*" %%a in ('date.exe +%%s') do set /a EPOCHTODAY=%%a
set /a MAXDAYS=%EPOCHTODAY%/86400
if "%1" == "" (
  echo No Parameter specified...
  GOTO EXIT
)
if %1 GTR 0 (
  if %1 LSS %MAXDAYS% (
    set /a OLDDAYS=%1
  ) else (
    echo "%1" is not between 0 - %MAXDAYS% ^>%MAXDAYS% 
    GOTO EXIT
  )
) else (
  echo "%1" is not between 0 - %MAXDAYS% ^<0
  GOTO EXIT
)
set /a DAYSEC=86400*%OLDDAYS%
set /a EPOCHTHATDAY=%EPOCHTODAY%-%DAYSEC%
for /f "tokens=1,2,3* delims=-" %%A in ('date.exe -d @%EPOCHTHATDAY% +"%%d-%%m-%%Y"') do (
  set THATDAY=%%A
  set THATMONTH=%%B
  set THATYEAR=%%C
)
echo %OLDDAYS% Gun once :
echo YIL : %THATYEAR%
echo AY  : %THATMONTH%
echo GUN : %THATDAY%
:EXIT

Bu BATCH dosyasını parça parça incelersek:

@echo off

Bu satır komuların doğrudan ekrana basılmasını engellemekte sadece komut çıktılarını görmemizi sağlamaktadır.

for /f "tokens=*" %%a in ('date.exe +%%s') do set /a EPOCHTODAY=%%a

date.exe +%%s komutunun çıktısı, saniye cinsinden içinde bulunduğumuz anın EPOCH değerini(1970’den itibaren geçen süreyi) göstermektedir. date.exe +%%s komutunun çıktısı %%a değişkenine atanmakta, %%a değişkeni ise set /a EPOCHTODAY=%%a ile sayısal olarak EPOCHTODAY değişkenine atanmaktadır. Sayısal olarak atama yapmaz isek, değişken STRING tipinde varsayılıp bizim işlem yapmamızı olanaksız hale getirecektir. Dolayısı ile EPOCHTODAY değişkeninin içeriği, 1970 senesinden şu ana kadar olan geçen toplam saniyedir.

set /a MAXDAYS=%EPOCHTODAY%/86400

1970 senesinden şu ana kadar olan geçen toplam saniyeyi, bir gündeki toplam saniye olan 86400 değerine bölersek, bu script ile geriye doğru gidebileceğimiz maksimum gün sayısını bulmuş oluruz.

if "%1" == "" (
  echo No Parameter specified...
  GOTO EXIT
)
if %1 GTR 0 (
  if %1 LSS %MAXDAYS% (
    set /a OLDDAYS=%1
  ) else (
    echo "%1" is not between 0 - %MAXDAYS% ^>%MAXDAYS% 
    GOTO EXIT
  )
) else (
  echo "%1" is not between 0 - %MAXDAYS% ^<0
  GOTO EXIT
)

if “%1” == “” satırı ile batch dosyasının parametre ile çağırılıp çağrılmadığı, if %1 GTR 0 satırı ile parametrenin “0”dan büyük olup olmadığı, if %1 LSS %MAXDAYS% satırı ile parametrenin geriye gidebileceğimiz maksimum gün sayısından büyük olup olmadığı kontrol edilmektedir. Eğer her şart sağlanmış ise set /a OLDDAYS=%1 satırı ile, girdiğimiz parametre sayısal olarak OLDDAYS değişkenine atanmaktadır.

set /a DAYSEC=86400*%OLDDAYS%
set /a EPOCHTHATDAY=%EPOCHTODAY%-%DAYSEC%

set /a DAYSEC=86400*%OLDDAYS% satırı ile geriye doğru gidilecek gün sayısı saniye cinsinden hesaplanır. set /a EPOCHTHATDAY=%EPOCHTODAY%-%DAYSEC% satırı ile de saniye cinsinden ulaşmak istediğimiz güne ait EPOCH değerine ulaşmış ve EPOCHTHATDAY değişkenine sayısal olarak atamış oluruz.

for /f "tokens=1,2,3* delims=-" %%A in ('date.exe -d @%EPOCHTHATDAY% +"%%d-%%m-%%Y"') do (
  set THATDAY=%%A
  set THATMONTH=%%B
  set THATYEAR=%%C
)

date.exe -d @%EPOCHTHATDAY% +”%%d-%%m-%%Y” komutu, EPOCHTHATDAY değişkeninin değerini +”%%d-%%m-%%Y” ile formatlayarak, yani “DD-MM-YYYY” şeklinde formatlayarak göstermektedir. “delims=-“ ile bu çıktıyı “-” delimiteri ile ayırıp “tokens=1,2,3*” ile 3(* ve daha fazla) değişkene atayacağımızı belirtmiş oluruz. Değişken isimleri %%A ile başlayıp %%B, %%C … gibi sıra ile devam etmektedir. set THATDAY=%%A, set THATMONTH=%%B ve set THATYEAR=%%C satırları ile de “DD-MM-YYYY” şeklinde formatlayarak gösterdiğimiz tarihi parçalara ayırıp atama işlemini tamamlamış oluruz.

echo %OLDDAYS% Gun once :
echo GUN : %THATDAY%
echo AY  : %THATMONTH%
echo YIL : %THATYEAR%

Bulunan değerler, yukarıdaki satırlar ile ekrana basılmaktadır.

:EXIT

GOTO EXIT yönergesi kullanılarak hiç bir işlem yapmadan batch dosyasından çıkabilmek için bu :EXIT etiketi kullanılmıştır.

Aslında aşağıdaki 4 satır ile istenilen sonuca ulaşılmış oluyor fakat tabii ki şekillendirmek için ekstra kod kullanılması gerekli olmaktadır.

for /f "tokens=*" %%a in ('date.exe +%%s') do set /a EPOCHTODAY=%%a
set /a DAYSEC=86400*%OLDDAYS%
set /a EPOCHTHATDAY=%EPOCHTODAY%-%DAYSEC%
date.exe -d @%EPOCHTHATDAY% +"%%d-%%m-%%Y"

Fakat internette yapılan kısa bir arama ile bile GnuWin32 date komutunu kullanmadan, bu işlemi yapmanın en azından onlarca satır süreceğini rahatlıkla söyleyebiliriz. Ayrıca GnuWin32 date komutunu kullanmadan bölgesel ayarlar sorunu da tam olarak çözülebilmiş olmamaktadır.