rss
    System.out.println("Hello World");

sâmbătă, 24 aprilie 2010

Compara date calendaristice

Aseara lucram la un program de pontaj cand, la un moment dat m-am lovit de urmatoarea problema. Aveam un obiect care avea ca atribute o data de inceput si o data de sfarsit(obiectul concediu) vroiam sa marchez in foaia de pontaj concediile si eventualele invoiri in functie de atributele precizate. Zis si facut...continui prin a va prezenta logica programului :

1 /* Metoda care verifica daca o data calendaristica se afla intr-un interval de date calendaristice
2 Folosim metoda compareTo a obiectului Date, metoda care returneza -1,0,1(mai mic,egal,mai mare)
3 */
4 private boolean dataInInterval(Date dataC,Date dataS,Date dataE){
5 if(dataC.compareTo(dataS)>=0 && dataC.compareTo(dataE)<=0){
6 return true;
7 }
8 return false;
9 }
10 //obiectul Concediu are printre atributele sale dataStart si dataEnd de tip Date
11 //initializam arrayListul de concedii
12 ArrayList<Concediu> concedii=concediiDinBD.getConcedii();
13 //initializam un obiect de tip calendar
14 Calendar lunaCurenta=Calendar.getInstance();
15 //extragem ultima zi din luna curenta pentru a o folosi in for
16 int ultimaZiDinLuna=lunaCurenta.getActualMaximum(Calendar.DAY_OF_MONTH);
17 for(int i=1;i<=ultimaZiDinLuna;i++)
18 {
19 lunaCurenta.set(Calendar.DAY_OF_MONTH, i);
20 //aici apelam metoda normalizare(lunaCurenta.getTime) - metoda este descrisa in continuare
21 for(int j=0;j<concedii.size();j++)
22 {
23 if(dataInInterval(lunaCurenta.getTime(),concedii.get(i).getDataStart(),concedii.get(i).getDataEnd())){
24 //marcheaza concediile sau eventualele invoiri in foaia de pontaj
25 }
26 }
27 }

Contrar asteptarilor mele acest cod nu a functionat cum m-as fi asteptat...
Evaluarea conditiei(dataC.compareTo(dataS)>=0 && dataC.compareTo(dataE)<=0) pentru valorile dataC=lunaCurenta.getTime(), dataS=24/04/2010 si dataE=24/04/2010 unde lunaCurenta.getTime()=24/04/2010 a fost spre surprinderea mea false; Dupa ce am rascolit internetul am aflat ca, deoarece valorile atributelor obiectului Concediu(dataS,dataE) vin din baza de date,deci sunt obiecte de tip java.sql.Date(asta nu ar trebui sa fie nici o problema) in momentul in care un obiect de tip java.util.Date si un obiect de tipul java.sql.Date sunt comparate, ele sunt comparate la nivel de milisecunda...In opinia mea ar trebui lasat la latitudinea programatorului...Deci, practic in conditia mea, desi aveam dataC.compareTo(dataS) ceea ce ar fi trebuit sa imi compare datele, comparatia se face la nivel de milisecunda.

Rezolvarea?

Pai avand in vedere ca obiectul de tip java.sql.Date care vine din bd vine atributele ora,minut,secunda si milisecunda egale cu 0, vom seta si noi obiectul nostru lunaCurenta(de tip calendar) cu aceste valori, pastrand valorile year,month si day.


28 private void normalizare(Calendar cal) {
29 cal.set(Calendar.MILLISECOND, 0);
30 cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
31 }
32


Deci problema noastra se poate rezolva prin apelarea metodei normalizare(lunaCurenta.getTime()) inainte de a intra in for-ul in care testam valoarea functiei dataInInterval

In speranta ca aceasta constatare va ajuta si pe altcineva,

Va multumesc pentru rabdarea de a citit tot ce am scris.

Un comentariu:

  1. In bucata de cod if(dataC.compareTo(dataS)>=0 && dataC.compareTo(dataE)<=0)
    valoarea dataE ai zis ca este trunchiata la prima milisecunda din zi.
    Deci daca iau in considerare prima milisecunda din ziua urmatoare pot rescrie cam asa:
    if(dataC.compareTo(dataS)>=0 && dataC.compareTo(new Date(dataE.getTime() + 24L*60L*60L*1000L))<0)
    Mai exact e ca la matematica, dataC ϵ [dataS,dataE)
    Si astfel nu mai ai nevoie de inca o functie, sau sa apelezi obiectul Calendar

    RăspundețiȘtergere

Va rugam lasati un comentariu!