[ Miloš Baić @ 26.01.2007. 22:15 ] @
Pozdrav,

imam ovakav problem, naime, trebao bih razliku dva datuma predstaviti u godinama, mesecima i danima. Npr. razlika od 20.06.2006. do 15.05.2005 mi treba, otrpilike, kao rezultat broj_godina = 1, broj_meseci = 1, broj_dana = 5.

Da li neko zna kako bih to trebao napraviti?

Hvala unapred. (relativno hitno)
[ Nemanja Avramović @ 26.01.2007. 22:30 ] @
E nisam radio nešto sa datumima u Delphiju, ali jesam u PHPu pa bi trebalo i iz Delphija da može. U stvari sigurno može ako uvedeš UNIX timestamp, a trebalo bi ovako da ide:

1) prebaciš oba datuma u sekunde
2) oduzmeš veći datum od manjeg
3) rezultat iz sekundi pretvoriš u broj dana/meseci/godina

Hint: http://www.delphifaq.com/faq/f91.shtml
[ Miloš Baić @ 27.01.2007. 00:25 ] @
Zaboravio sam reći da sam pretražio forum i nisam rešio problem.

@Nemanja:
na osnovu linka koji si postavio odradio sam:
Code:
const
  // Sets UnixStartDate to TDateTime of 01/01/1970
  UnixStartDate: TDateTime = 25569.0;
...
var
 Dat1, Dat2: TDateTime;
 Razlika: Real;
...
begin
 Dat1:= StrToDateTime(MaskEdit1.Text);
 Dat2:= StrToDateTime(MaskEdit2.Text);
 DateTimeToUnix(Dat1);
 DateTimeToUnix(Dat2);
 Razlika:= Dat2 - Dat1;
 UnixToDateTime(Round(Razlika));
 ShowMessage(FloatToStr(Razlika));
end;

Rezultat je tačan broj dana, npr:
Citat:

MaskEdit1.Text:= '01.01.07'; (datum_od)
MaskEdit2.Text:= '11.01.07'; (danas)

razlika je 10 dana (Razlika = 10). Dotle sam došao. Sad to treba rastaviti na godine, mesece i dane, odnosno, tu razliku. Ako je Razlika veća od broja dana u godini, izdvojiti godine, potom proveriti ostatak, pa ako je veći od broja dana u mesecu izdvojiti broj meseci i na kraju, ostatak u danima.

Ako neko ima ideju, kako ovo rešiti, neka se uključi, ili ako ima bolje rešenje, neka ga izloži.
[ savkic @ 27.01.2007. 00:40 ] @
> E nisam radio nešto sa datumima u Delphiju, ali jesam u PHPu pa bi trebalo i iz Delphija da može. U stvari sigurno može ako uvedeš UNIX
> timestamp, a trebalo bi ovako da ide:

> 1) prebaciš oba datuma u sekunde
> 2) oduzmeš veći datum od manjeg
> 3) rezultat iz sekundi pretvoriš u broj dana/meseci/godina

> razlika je 10 dana (Razlika = 10). Dotle sam došao. Sad to treba rastaviti na godine, mesece i dane, odnosno, tu razliku. Ako je Razlika veća od
> broja dana u godini, izdvojiti godine, potom proveriti ostatak, pa ako je veći od broja dana u mesecu izdvojiti broj meseci i na kraju, ostatak u danima.

Što jednostavno kad može komplikovano je l' tako :) Za prostu razliku u danima (i delovima dana) je dovoljno oduzeti dva datuma jedan od drugog. Npr.
Code:

var
  d1, d2: TDateTime;
begin
  d1 := Now;
  d2 := Now + 40.3;

  Caption := FloatToStr(d2 - d1);
end;


Kvalitetnije rešenje treba da uzme nekoliko stvari u obzir, evo jednog primera, dosta davno sam ga pisao i nije baš reprezentativan primer, može to mnogo lepše i jednostavnije :)

Code:

procedure BrojDana(d1, d2: TDate; var Dan, Mes, God: Integer);
var
  i, Raz: Integer;
  Dan1, Dan2, Mes1, Mes2, God1, God2: Word;
begin
  Dan := 0;
  Mes := 0;
  God := 0;
  DecodeDate(d1, God1, Mes1, Dan1);
  while d1 < d2 do
  begin
    Inc(God1);
    d1 := EncodeDate(God1, Mes1, Dan1);
    if d1 <= d2 then
      Inc(God)
    else begin
      Dec(God1);
      d1 := EncodeDate(God1, Mes1, Dan1);
      Break;
    end;
  end;
  while d1 < d2 do
  begin
    Inc(Mes1);
    if Mes1 = 13 then
    begin
      Inc(God1);
      Dec(Mes1);
    end;
    d1 := EncodeDate(God1, Mes1, Dan1);
    if d1 <= d2 then
      Inc(Mes)
    else begin
      Dec(Mes1);
      d1 := EncodeDate(God1, Mes1, Dan1);
      Break;
    end;
  end;
  while d1 < d2 do
  begin
    d1 := d1 + 1;
    if d1 <= d2 then
      Inc(Dan)
  end;
end;


procedure TForm1.Button1Click(Sender: TObject);
var
  Dan, Mes, God: Integer;
begin
  BrojDana(StrToDate('05/02/2002'), StrToDate('18/04/2002'), Dan, Mes, God);
  Caption := IntToStr(Dan) + ';' + IntToStr(Mes) + ';' + IntToStr(God);
end;
[ Miloš Baić @ 27.01.2007. 01:11 ] @
@savkic
Svaka čast.

@Nemanja
Hvala i tebi na pomoći.
[ viking13 @ 27.01.2007. 02:07 ] @
Citat:
Što jednostavno kad može komplikovano je l' tako


Vidim i ti si počeo toga da se pridržavaš.

Zar ovako nije MNOGO JEDNOSTAVNIJE?

Code:

uses
  DateUtils;

procedure DMYBetween(ANow, AThen: TDate; var Days, Months, Years: Integer);
begin
  Years := YearsBetween(ANow, AThen);
  AThen := IncYear(AThen, Years);
  Months := MonthsBetween(ANow, AThen);
  AThen := IncMonth(AThen, Months);
  Days := DaysBetween(ANow, AThen);
end;


Vidim ja da je bilo krajnje vreme da se pojavim ovde.
[ Miloš Baić @ 27.01.2007. 10:25 ] @
@viking13
Savim korektno.
[ Nemanja Avramović @ 27.01.2007. 11:43 ] @
Sad ja ispade najgori ovde?
Jbg, nisam nikad nešto preterano radio sa datumima u Delphiju, ali mi ono sa unix timestampom mnogo pomaže kad radim komunikaciju php aplikacija sa delphi aplikacijama pa sam mislio da i ovde može pomoći
[ milanescape @ 28.01.2007. 14:41 ] @
Imam nesto JAKO STARO-sto sam ranije koristio za proveru broja dana koriscenja nekog programa.
Ne odnosi se direktno na promenu sati, minuta i sekundi.Moze da posluzi.Aplikacija se postavlja u StartUp. Zbog "malo vece sigurnosti" vrednosti iz tabele mozes upisati u registri (ili na neko drugo po tebi sigurno mesto)a odatle ih ponovo ucitati u tabelu pri startovanju forme-neupuceniji korisnici tesko ce ukapirati odakle stizu podaci. Broj dana se lako pretvara u broj meseci i godina (potrebni su ti dbedit1, edit1,edit2, ,label10,label11,label12,label4,tabela i source...I SIGURNO JOS PO NESTO STO VEROVATNO NISAM PRIMETIO)
Kod se moze lako korigovati

procedure TForm1.FormActivate(Sender: TObject);
var d,m,g,dd,dm,dg:tdatetime;
sd,sm,sg,sdd,sdm,sdg:string;//razdvojeni datumi po danu,mesecu,godini
id,im,ig,idd,idm,idg:integer;
razd,razm,razg,Md,Mp,i,Brd:integer;/razlika u danima,mesecima,godinama...
var Mdanas: array [1..12] of integer;
Mpre: array [1..12] of integer;
begin

edit2.text:=datetostr(date);//EDIT2 PREUZIMA DANASNJI DATUM

if not DirectoryExists('D:\Delphi') then
Begin
CreateDir('D:\Delphi')
end;

if not Session.IsAlias('VREMEDAT') then
begin//ako ne postoji alias
if not DirectoryExists('D:\Delphi\VREMEDAT') then
Begin//*******
CreateDir('D:\Delphi\VREMEDAT');
with Session do
begin
AddStandardAlias('VREMEDAT', 'D:\Delphi\VREMEDAT','paradox');//kreiranje aliasa
SaveConfigFile;
end;
End;//*******
//kreiranje tabele
TABLE1:=TTABLE.CREATE(SELF);
Table1.DatabaseName:='VREMEDAT';
TABLE1.TABLENAME:='DAT.DB';
table1.FieldDefs.Add('Dat',ftstring,11,False);//poslednji datum
table1.FieldDefs.Add('DoS',ftinteger);//koliko do sada dana
Table1.CreateTable;

end;//zavrseno-ako ne postoji alias


//aktiviranje tabele table1.databasename:='VREMEDAT';
Table1.DatabaseName:='VREMEDAT';
TABLE1.TABLENAME:='DAT.DB';
datasource1.dataset:=table1;
Table1.active:=true;

//ODAVDE--------------------------------------------------------------------
LABEL4.CAPTION:=inttostr(TABLE1.FIELDBYNAME('DoS').asinteger);//POKAZUJE KOLIKO DANA DO SADA
If table1.recordcount<1 then Table1.append Else table1.edit;

//povezivanje dbedita1 sa tabelom1
dbedit1.datasource:=datasource1;
dbedit1.datafield:='Dat';

if dbedit1.text='' then
begin
table1.edit;
table1.fieldbyname('Dat').asstring:=datetostr(date);
end;

table1.edit;
table1.Post;

//AKO JE DANASNJI DATUM <OD PRETHODNO UPISANOG (DAKLE AKO JE DATUM VRACEN ZA NEKOLIKO DANA)
IF STRTODATE(EDIT2.TEXT)<STRTODATE(DBEDIT1.TEXT) THEN
BEGIN
TABLE1.EDIT;
TABLE1.FIELDBYNAME('Dat').asstring:=EDIT2.TEXT;//preuzmi sadasnji datum
label12.caption:='1'; //POVECAJ BROJ DANA ZA 1 (UVEK)
table1.fieldbyname('DoS').asinteger:=table1.fieldbyname('DoS').asinteger+1;//DoS-Do sada dana
END
ELSE
BEGIN
//za danasnji datum
Mdanas[1]:=31;
Mdanas[2]:=28;
Mdanas[3]:=31;
Mdanas[4]:=30;
Mdanas[5]:=31;
Mdanas[6]:=30;
Mdanas[7]:=31;
Mdanas[8]:=31;
Mdanas[9]:=30;
Mdanas[10]:=31;
Mdanas[11]:=30;
Mdanas[12]:=31;
//za uneti datum
Mpre[1]:=31;
Mpre[2]:=28;
Mpre[3]:=31;
Mpre[4]:=30;
Mpre[5]:=31;
Mpre[6]:=30;
Mpre[7]:=31;
Mpre[8]:=31;
Mpre[9]:=30;
Mpre[10]:=31;
Mpre[11]:=30;
Mpre[12]:=31;


//za uneti datum
sd:=edit1.text[1]+edit1.text[2];//stringovi
sm:=edit1.text[4]+edit1.text[5];
sg:=edit1.text[7]+edit1.text[8]+edit1.text[9]+edit1.text[10];;
id:=strtoint(sd);
im:=strtoint(sm);
ig:=strtoint(sg);

//za danasnji datum
sdd:=edit2.text[1]+edit2.text[2];//stringovi
sdm:=edit2.text[4]+edit2.text[5];
sdg:=edit2.text[7]+edit2.text[8]+edit2.text[9]+edit2.text[10];;
idd:=strtoint(sdd);
idm:=strtoint(sdm);
idg:=strtoint(sdg);

Md:=0;
Mp:=0;
razg:=idg-ig;

if razg>=1 then
begin/////////
IF IDM=12 THEN Md:=31-idm+1 else
BEGIN
for i:=1 to idm-1 do //ZA DANAS-od pocetka meseca do sad
begin
if i=2 then
begin
if idg mod 4 = 0 then Md:=Md+29 else Md:=Md+Mdanas;
end
else
begin
Md:=Md+Mdanas;
end;

end;
Md:=Md+idd;
END;
label10.caption:=inttostr(Md);

IF IM=12 THEN Mp:=31-id+1 else
BEGIN
for i:=im+1 to 12 do //ZA BROJ DANA PO MESECIMA DO KRAJA PREDHODNE GODINE
begin
if i=2 then
begin
if ig mod 4 = 0 then Mp:=Mp+29 else Mp:=Mp+Mpre;
end
else
begin
Mp:=Mp+Mpre;
end;

end;
Mp:=Mp+Mpre[im]-id+1;
END;
label11.caption:=inttostr(Mp);

Brd:=Mp+Md+(razg-1)*365;
label12.caption:=inttostr(Brd);
end/////////ako je razlika =1
else
begin///ako je razlika=0 ili <1
if razg=0 then
begin
IF IM=IDM THEN
BEGIN
Brd:=idd-id+1;
label12.caption:=inttostr(Brd);
END
ELSE
BEGIN
IF IDM=IM+1 THEN
BEGIN
Brd:=idd+Mpre[im]-id+1;
label12.caption:=inttostr(Brd);
END
ELSE
BEGIN
for i:=Im+1 to idm-1 do //od meseca do meseca (ne racunajuci dane u pocetnom i dane u krajnjem)
begin
if i=2 then
begin
if idg mod 4 = 0 then Md:=Md+29 else Md:=Md+Mdanas;
end
else
begin
Md:=Md+Mdanas;
end;

end;
label10.caption:=inttostr(Md+idd);
label11.caption:=inttostr(Mpre[im]-id);
Brd:=Md+idd+Mpre[im]-id+1;
label12.caption:=inttostr(Brd);//Brd je broj dana
END;

END;
end
else
begin//ako je razlika>1
////MOZES KORISTITI ZA NESTO
end;
end
END;
table1.Edit;
IF DATE>STRTODATE(DBEDIT1.TEXT) THEN
table1.fieldbyname('DoS').asinteger:=table1.fieldbyname('DoS').asinteger+strtoint(label12.caption)-1;
table1.fieldbyname('Dat').asstring:=datetostr(date);
table1.edit;
table1.post;
TABLE1.REFRESH;
close;
end;

Inace ako ti znaci nesto moje misljenje: Savkic-evo resenje je ubedljivo naj naj najbolje
Poz
Milan



[Ovu poruku je menjao milanescape dana 28.01.2007. u 15:52 GMT+1]

[Ovu poruku je menjao milanescape dana 28.01.2007. u 15:57 GMT+1]
[ Miloš Baić @ 30.01.2007. 13:26 ] @
Pozdrav,

uspeo sam, na osnovu viking13 i savkica da rešim problem izračunavanja od datuma do datuma. Hteo bih to proširiti sledećim, kad dobijem broj godina, meseci i dana hteo bih to sabrati sa već postojećim.

Dakle, ako već imam br.god = 5, br.mes = 10, br.dan = 12, a posle obračuna između dva datuma dobijem u nekim promenljivama br.god = 10, br.mes = 5, br.dan = 23, hteo bih to sabrati i dati konačan izveštaj. Nije problem sabrati nego rastaviti, kad se sabere: br.god = 15, br.mes = 15, br.dan = 35, sad to treba rastaviti na br.god = 16, br.mes = 4, br.dan = (4 ili 5)!?!

Da li je neko radio tako nešto i ako jeste, da li bi hteo na mom primeru objasniti kako to profesionalno odraditi, napominjem da sam koristio primer viking13.

Hvala unapred.
[ viking13 @ 30.01.2007. 14:38 ] @
Problem je upravo ono 4 ili 5 o kome pričaš. Mada, ako ćemo iskreno može da bude i 7. :)

Da li je ikako moguće da umesto postojećeg zbira pamtiš početni datum?

Onda veoma jednostavno uporediš sadašnji sa početnim i nema sabiranja.

Em je mnogo lakše, em dobijaš tačne vrednosti bez obzira da li je upravo počeo mart ili septembar. :)

[ Miloš Baić @ 30.01.2007. 15:29 ] @
@viking13

Ne znam da li sam te razumeo najbolje, ali treba mi da kad na osnovu tvoje procedure dobijem tačan broj god, mes, dana to saberem sa već postojećim vrednostima.

Razumeo sam te, da uzmem prvi datum na osnovu kojeg sam dobio te vrednosti, pa onda to odradim sa recimo današnjim datumom i dobijem ukupan zbir!?!
Ako je tako, ne mogu to, jer ima prekida u datumu. Recimo, od 15.02.1978 - 22.05.1990., pa prekid, te onda od 10.10.2000. do 25.03.2006. Dakle, treba mi tačna razlika prva dva datuma, odnosno već imam tu razliku kao promenljive (br.god = 5, br.mes = 10, br.dan = 12, npr.) pa razlika druga dva, te sabrati te dve razlike i dobiti konačan zbir!?!

Ne znam da li sam bio jasan!?!
[ savkic @ 30.01.2007. 15:54 ] @

> Dakle, ako već imam br.god = 5, br.mes = 10, br.dan = 12, a posle obračuna između dva datuma dobijem u nekim promenljivama
> br.god = 10, br.mes = 5, br.dan = 23, hteo bih to sabrati i dati konačan izveštaj. Nije problem sabrati nego rastaviti, kad se
> sabere: br.god = 15, br.mes = 15, br.dan = 35, sad to treba rastaviti na br.god = 16, br.mes = 4, br.dan = (4 ili 5)!?!

Sabiranje staža, rekao bih. Elem ne znam postoji li neki pravilnik o tome, ako tražiš čisto rešenje, najbolje da konsultuješ nekog iskusnog knjigovođu ili penzionu službu. Kada dobiješ tačne informacije, lako je. Kreneš od broja dana i deliš sa 30 (31) i dobiješ broj koji dodaš na postojeći iznos meseci a ostak ti je broj dana. Dalje mesece deliš sa 12, cele godine dodaješ u godine a resto su meseci.
[ viking13 @ 30.01.2007. 16:17 ] @
Citat:
loshmiscg: @viking13

Ne znam da li sam te razumeo najbolje, ali treba mi da kad na osnovu tvoje procedure dobijem tačan broj god, mes, dana to saberem sa već postojećim vrednostima.

Razumeo sam te, da uzmem prvi datum na osnovu kojeg sam dobio te vrednosti, pa onda to odradim sa recimo današnjim datumom i dobijem ukupan zbir!?!
Ako je tako, ne mogu to, jer ima prekida u datumu. Recimo, od 15.02.1978 - 22.05.1990., pa prekid, te onda od 10.10.2000. do 25.03.2006. Dakle, treba mi tačna razlika prva dva datuma, odnosno već imam tu razliku kao promenljive (br.god = 5, br.mes = 10, br.dan = 12, npr.) pa razlika druga dva, te sabrati te dve razlike i dobiti konačan zbir!?!

Ne znam da li sam bio jasan!?!


Sad kad mi je savkic otvorio oči sve mi je jasno i jasno mi je da ti moja ideja ne pomaže.

Kad saznaš tačne informacije javi se da nađemo najbolje rešenje.

Ako se za mesec uzima fiksni broj dana (recimo 30), onda ti ni moja početna funkcija nije dobra za tu svrhu. Jer će ti dati više dana za prelaz iz februara u mart, nego kad je u pitanju prelaz sa avgusta na septembar.
[ Whois @ 30.01.2007. 16:39 ] @
ako imas intervale koji su tdatetime tipa:
int1
int2
int3
int4

razliku nemoj da konvertujes nego je prosto oduzmi posto je tdatetime realni tip
znaci:

raz1:=abs(int1-int2);
raz2:=abs(int3-int4);
...

ukupno:=raz1+raz2+raz3....


pa onda koristis vikingovu funkciju za prikaz. Mozes da racunas od danasnjeg dana a mozes i od nekog drugog, mada mislim da treba da se racuna od int1 posto je to verovatno neki radni staz ili tako nesto

od danasnjeg dana:

DMYBetween(date, date+ukupno, Days, Months, Years)

a od int1:

DMYBetween(int1, int1+ukupno, Days, Months, Years)
[ Miloš Baić @ 30.01.2007. 18:43 ] @
Code:
...
uses
  DateUtils;

procedure DMYBetween(ANow, AThen: TDate; var Days, Months, Years: Integer);
begin
  Years := YearsBetween(ANow, AThen);
  AThen := IncYear(AThen, Years);
  Months := MonthsBetween(ANow, AThen);
  AThen := IncMonth(AThen, Months);
  Days := DaysBetween(ANow, AThen);
end;

procedure TForm1.Button1Click(Sender: TObject);
var d,m,g,Days,Months,Years,br_mes,br_god,god_zbir,dan_ostatak,mes_ostatak : integer;
    ANow, AThen: TDate;
begin
try
 d:= 25;//radni staz donet  (broj dana)
 m:= 8;//radni staz donet  (broj meseci)
 g:= 15;//radni staz donet  (broj godina)
 ANow:= Now;
 AThen:= StrToDate('26.06.2000');//postavka datuma
 DMYBetween(ANow,AThen,Days, Months, Years);

 br_mes:= (d + Days) div 30;//broj meseci
 dan_ostatak:= (d + Days) - (br_mes * 30);//ostatak
 br_god:= (m + Months + br_mes) div 12;//broj godina
 mes_ostatak:= (m + Months + br_mes) - (br_god * 12);//ostatak
 god_zbir:= (g + Years + br_god);//zbir godine
finally
  ShowMessage('Radni staz donet - ' +'broj dana: '+ IntToStr(d) + ', broj meseci: '+ IntToStr(m) + ', broj godina: '+ IntToStr(g) + ';'
            + #13#13 + 'Od ' + DateToStr(AThen) + ' do ' + DateToStr(Now)+ ' ima: ' + IntToStr(Days) + ' dana; ' + IntToStr(Months) + ' meseci; ' + IntToStr(Years) + ' godina;'
            + #13#13 +'Ukupan radni staz iznosi: '
            + #13#13 +'Broj dana: '+ IntToStr(dan_ostatak)
            + #13#13 +'Brojmeseci: '+IntToStr(mes_ostatak)
            + #13#13 +'Broj godina: '+ IntToStr(god_zbir));
 end;
end;
...


Možemo početi odavde!?!
[ goranvuc @ 30.01.2007. 18:55 ] @
Milose, evo ti opet nesto u VB-u, pa ces se valjda snaci ;)

Code:

'*****************************************************************************
'* FUNKCIJA KOJA VRACA godinu, mesec i broj dana razlike izmedju dva datuma
'*****************************************************************************
Public Function Razlika_Datuma(ByVal OdDatuma As Date, _
                               ByVal DoDatuma As Date, _
                               ImaGodina As Integer, _
                               ImaMeseci As Long, _
                               ImaDana As Long)

   If DoDatuma < OdDatuma Then
      ImaGodina = 0
      ImaMeseci = 0
      ImaDana = 0
      Exit Function
   End If
                               
   DoDatuma = DateAdd("d", 1, DoDatuma)
   ImaGodina = DateDiff("yyyy", OdDatuma, DoDatuma)
   
   If ImaGodina > 0 Then
    If Month(DoDatuma) <= Month(OdDatuma) Then
       If Month(DoDatuma) < Month(OdDatuma) Then
          ImaGodina = ImaGodina - 1
       Else
         If Day(DoDatuma) < Day(OdDatuma) Then
            ImaGodina = ImaGodina - 1
         End If
       End If
    End If
   End If
   
   OdDatuma = DateAdd("yyyy", ImaGodina, OdDatuma) 'Dodajem broj godina
   
   ImaMeseci = DateDiff("m", OdDatuma, DoDatuma)
   
   If Day(OdDatuma) > Day(DoDatuma) And ImaMeseci <> 0 Then
      ImaMeseci = ImaMeseci - 1
   End If
   
   OdDatuma = DateAdd("m", ImaMeseci, OdDatuma) 'Dodajem broj meseci
   
   ImaDana = DateDiff("d", OdDatuma, DoDatuma)
   
End Function

Duuuuugo koristim ovu funkciju.
[ Whois @ 30.01.2007. 19:00 ] @
a ti bi tako, pa onda probaj ovo:

Code:

begin
try
 d:= 25;//radni staz donet  (broj dana)
 m:= 8;//radni staz donet  (broj meseci)
 g:= 15;//radni staz donet  (broj godina)
 ANow:= Now;
 AThen:= StrToDate('26.06.2000');//postavka datuma
 DMYBetween(ANow,AThen,Days, Months, Years);

 dmybetween(anow,incyear(incmonth(incday(Anow,d+days),m+months,g+years),dan_ostatak, br_mes, br_god);

 finally
  ShowMessage('Radni staz donet - ' +'broj dana: '+ IntToStr(d) + ', broj meseci: '+ IntToStr(m) + ', broj godina: '+ IntToStr(g) + ';'
            + #13#13 + 'Od ' + DateToStr(AThen) + ' do ' + DateToStr(Now)+ ' ima: ' + IntToStr(Days) + ' dana; ' + IntToStr(Months) + ' meseci; ' + IntToStr(Years) + ' godina;'
            + #13#13 +'Ukupan radni staz iznosi: '
            + #13#13 +'Broj dana: '+ IntToStr(dan_ostatak)
            + #13#13 +'Brojmeseci: '+IntToStr(br_mes)
            + #13#13 +'Broj godina: '+ IntToStr(br_god));
 end;
end;
[ Miloš Baić @ 30.01.2007. 19:49 ] @
Hvala na odgovoru.

@Whois
Jesi siguran da je ovo korektno:
Citat:
dmybetween(anow,incyear(incmonth(incday(Anow,d+days),m+months,g+years),dan_ostatak, br_mes, br_god);

Ne moram onako kako sam napisao, ako imate kvalitetnija rešenja, a imate verovatno, rado ću ih usvojiti.

PozZ

[Ovu poruku je menjao loshmiscg dana 30.01.2007. u 21:02 GMT+1]
[ viking13 @ 30.01.2007. 20:10 ] @
Pažljivo ovo opet pročitajte:

Citat:
savkic
Sabiranje staža, rekao bih. Elem ne znam postoji li neki pravilnik o tome, ako tražiš čisto rešenje, najbolje da konsultuješ nekog iskusnog knjigovođu ili penzionu službu. Kada dobiješ tačne informacije, lako je.


Igor je ovde pokrenuo jedno veoma važno pitanje koje nema veze sa programiranjem.

Dok ovo ne rešiš, svaka dalje diskusija je suvišna.
[ Miloš Baić @ 30.01.2007. 20:43 ] @
@viking13
Ok, trudim se da pažljivo pročitam svaki post.

Shvatam da tu ima, možda, zakonskih caka, etc., ali u ovom momentu meni treba samo ovo, rekao bih čisto rešenje, odnosno to su informacije koje imam:

Hipotetički, lice se zapošljava u neku ustanovu, recimo, ta ustanova zahteva od njega broj god, mes, dana radnog staža, ukupan koji je odradio - nebitni su datumi zasnivanja i prekida, firme gde je radio, koji donosi u ustanovu po zasnivanju radnog odnosa. Mi, ustanova, memorišemo te cifre i datum zasnivanja radnog odnosa. Teti iz kadrovske službe treba da, u svom programu, kad vrši pregled podataka o zaposlenom licu vidi donesen radni staž i datum zaposlenja u njihovoj instituciji. Trenutno joj ne treba ništa više nego radni staž (broj god, mes, dana) od dana zasnivanja radnog odnosa lica u toj instituciji do danas, plus staž sa kojim je lice došlo u instituciju, tako da dobijemo ukupan zbir.

BTW, raspitaću se malo, ukoliko ima nekih caka još na koje bih treba obratiti pažnju, javiću vam te ćemo korigovati, ali trenutno na ovome se zadržavam.

Hvala svima na diskusiji.

[ milanescape @ 31.01.2007. 01:46 ] @
Radni staz izracunavas tako sto izracunas broj dana od prvog datuma prve sledece godine (ne one u kojoj je prvi datum) do poslednjeg datuma pretposlednje godine (do 12-og meseca)-->d.Zatim izracunas koliko je bilo prestupnih godina u tom intervalu-->ne ukljucujuci prvu i poslednju-->n. Izracunas razliku d-n. Izracunas koliko je bili dana u prvoj godini (to je lako)-->d1, a zatim koliko je bilo dana u poslednjoj godini-->d2. (bilo da su prva i poslednja prestupne ili ne) ==> RS=d-n+d1+d2 na kraju sve podelis sa 365.
RS=(d-n+d1+d2)/365. Radni staz mozes pretstaviti u obliku decimalnog broja ili kao ceo broj i ostatak dana(ili meseci i dana). Broj dana se uglavnom u svim izracunavanjima vezuje za 30 . Ako sabiras vise intervala radnog staza onda ih sabiras kao decimalne brojeve (pojedinacno) i tek na kraju sve pretvaras u godine mesece i dane. U principu-ako su kratki intervali tipa od 02.02.2004 do 03.03.2004 onda pojedinacno racunas broj dana. Na kraju sve delis sa 365. Npr 4,53g RS : 4 g, 1:12=0,53:x==>6,36 mes==>6 m ---e sad moras da upotrebis 30 dana. 1:30=0,36:x ==> 10,8 dana.

Procedura koju saljem bi trebalo da radi-ali proveri. Nema bas neke veze sa ovim objasnjenjem. Koristio sam je ranije-i tad je to moglo tako. Moraces da ispravis deo oko konvertovanja dana (pod uslovom da radi- stvarno nisam stigao da proverim). Potrebna su ti dva edita, button i label, tabela sa poljima od i do, source. Petljom u edite (ili dbedite) iz tabele smestas datume(od-do). Labela pokazuje rezultat. Rezultat cuvas u posebnoj promenljivoj kojoj dodajes svaku novu vrednost (dane). na kraju delis sa 365 i pretvaras u G,M,D.



procedure BrojDana(s1, s2:string; var s: string);
var
datum1, datum2: TDateTime;
posebnodana,ukupdana,dana:real;
dan,prvidanuprvgod,zavrsnidanuzavrgod,
godina,ukupgodina,prvagodina,zavrsnagodina,
ukupmeseci,mesec,prvimesuprvgod,zavrsnimesuzavrsgod:integer;
var DanaUMesecu: array [1..12] of integer;

begin
dana:=0;
ukupgodina:=0;
ukupdana:=0;
posebnodana:=0;
ukupmeseci:=0;

DanaUMesecu[1]:=31;
DanaUMesecu[2]:=28;
DanaUMesecu[3]:=31;
DanaUMesecu[4]:=30;
DanaUMesecu[5]:=31;
DanaUMesecu[6]:=30;
DanaUMesecu[7]:=31;
DanaUMesecu[8]:=31;
DanaUMesecu[9]:=30;
DanaUMesecu[10]:=31;
DanaUMesecu[11]:=30;
DanaUMesecu[12]:=31;

datum1 :=strtodate(s1);
datum2 :=strtodate(s2);

dana :=datum2 - datum1; //ukupan broj dana -sluzi samo za poredjenje sa ukupdana ako ti je potrebno

//za godine koje nisu pocetna i zavrsna
prvagodina:=strtoint(s1[7]+s1[8]+s1[9]+s1[10]);
zavrsnagodina:=strtoint(s2[7]+s2[8]+s2[9]+s2[10]);
//za prvu godinu za broj meseci (i dana)-->posto nema puni broj godina
prvimesuprvgod:=strtoint(s1[4]+s1[5]);
zavrsnimesuzavrsgod:=strtoint(s2[4]+s2[5]);
//za preostali broj dana-->u prvom mesecu prve godine i u zavrsnom mesecu zavrsne godine
prvidanuprvgod:=strtoint(s1[1]+s1[2]);
zavrsnidanuzavrgod:=strtoint(s2[1]+s2[2]);

if zavrsnagodina-prvagodina<=1 then//ako su godine jedna do druge ili je ista godina
begin

if zavrsnagodina-prvagodina=0 then//ako je ista godina
begin
ukupgodina:=0;
if zavrsnimesuzavrsgod-prvimesuprvgod<=1 then//ako su dani u dva meseca koji su jedan do drugog ili su isti
begin

ukupmeseci:=ukupmeseci+0;
ukupdana:=ukupdana+datum2 - datum1;
posebnodana:=posebnodana+ukupdana;


end
else
begin
for mesec:=prvimesuprvgod+1 to zavrsnimesuzavrsgod-1 do
begin
ukupmeseci:=ukupmeseci+1;
if ((mesec=2)and (prvagodina mod 4 = 0)) then ukupdana:=ukupdana+29
else ukupdana:=ukupdana+DanaUMesecu[mesec];
end;
ukupdana:=ukupdana+DanaUMesecu[prvimesuprvgod]-prvidanuprvgod+zavrsnidanuzavrgod;
posebnodana:=DanaUMesecu[prvimesuprvgod]-prvidanuprvgod+zavrsnidanuzavrgod;
end;
end
else
begin
if zavrsnagodina-prvagodina=1 then//ako su godine jedna do druge
begin
ukupgodina:=0;
for mesec:=prvimesuprvgod+1 to 12 do
begin
ukupmeseci:=ukupmeseci+1;
if ((mesec=2)and (prvagodina mod 4 = 0)) then ukupdana:=ukupdana+29
else ukupdana:=ukupdana+DanaUMesecu[mesec];
end ;

//za zavrsnu godinu za broj meseci (i dana)-->posto nema puni broj godina

for mesec:=1 to zavrsnimesuzavrsgod-1 do
begin
ukupmeseci:=ukupmeseci+1;
if ((mesec=2)and (prvagodina mod 4 = 0)) then ukupdana:=ukupdana+29
else ukupdana:=ukupdana+DanaUMesecu[mesec];
end ;
posebnodana:=DanaUMesecu[prvimesuprvgod]-prvidanuprvgod;
posebnodana:=posebnodana+zavrsnidanuzavrgod-1;

ukupdana:=ukupdana+DanaUMesecu[prvimesuprvgod]-prvidanuprvgod;
ukupdana:=ukupdana+zavrsnidanuzavrgod-1;
end

end

end
else
begin//***************************
for godina:=prvagodina+1 to zavrsnagodina-1 do
begin
if godina mod 4 =0 then ukupdana:=ukupdana+366 else ukupdana:=ukupdana+365;//koliko dana u godinama izmedju prve (prvog datuma) i poslednje(poslednjeg datuma)
ukupgodina:=ukupgodina+1;
end;


for mesec:=prvimesuprvgod+1 to 12 do
begin
ukupmeseci:=ukupmeseci+1;
if ((mesec=2)and (prvagodina mod 4 = 0)) then ukupdana:=ukupdana+29
else ukupdana:=ukupdana+DanaUMesecu[mesec];
end ;


for mesec:=1 to zavrsnimesuzavrsgod-1 do
begin
ukupmeseci:=ukupmeseci+1;
if ((mesec=2)and (prvagodina mod 4 = 0)) then ukupdana:=ukupdana+29
else ukupdana:=ukupdana+DanaUMesecu[mesec];
end ;



posebnodana:=DanaUMesecu[prvimesuprvgod]-prvidanuprvgod;
posebnodana:=posebnodana+zavrsnidanuzavrgod-1;

ukupdana:=ukupdana+DanaUMesecu[prvimesuprvgod]-prvidanuprvgod;
ukupdana:=ukupdana+zavrsnidanuzavrgod-1;

end;//***************************

//ovo je varijanta gde se gleda 30 dana u mesecu (i standardnih 28 u februaru)-to moras proveriti!!!!
{if zavrsnimesuzavrsgod<>3 then
begin
if posebnodana>=30 then
begin
posebnodana:=posebnodana-30;
ukupmeseci:=ukupmeseci+1;
end;
end
else
begin

if posebnodana>=28 then
begin
posebnodana:=posebnodana-28;
ukupmeseci:=ukupmeseci+1;
end;

end;}
//ovo je varijanta gde se gleda poslednji mesec (broj dana u poslednjem mesecu)
if posebnodana>=DanaUMesecu[zavrsnimesuzavrsgod] then
begin
posebnodana:=posebnodana-DanaUMesecu[zavrsnimesuzavrsgod];
ukupmeseci:=ukupmeseci+1;
end;

{//ovo je varijanta gde se gleda prvi mesec (broj dana u prvom mesecu)
if posebnodana>=DanaUMesecu[prvidanuprvgod] then
begin
posebnodana:=posebnodana-DanaUMesecu[prvidanuprvgod];
ukupmeseci:=ukupmeseci+1;
end;}
if ukupmeseci>=12 then
begin
ukupgodina:=ukupgodina+1;
ukupmeseci:=ukupmeseci-12;
end;


s:=inttostr(ukupgodina)+ ' godina '+inttostr(ukupmeseci)+ ' meseci '+floattostr(posebnodana)+ ' dana';

end;


procedure TForm1.ButtonStazClick(Sender: TObject);
var t:string;
begin
BrojDana(editdat1.text,editdat2.text,t);//ili dbedit1.text, dbedit2.text
label1.caption:=t;//pokazuje rezultat
end;
[ mojeKorIme @ 31.01.2007. 06:53 ] @
Nisam imao vremena da citam sve...Zelio bih da ti skrenem paznju da ima i prestupna godina. Pa ako to nisi
predvidio kompletiraj kod. pozz.
[ viking13 @ 31.01.2007. 09:34 ] @
Citat:
loshmiscg
Dakle, ako već imam br.god = 5, br.mes = 10, br.dan = 12, a posle obračuna između dva datuma dobijem u nekim promenljivama br.god = 10, br.mes = 5, br.dan = 23, hteo bih to sabrati i dati konačan izveštaj. Nije problem sabrati nego rastaviti, kad se sabere: br.god = 15, br.mes = 15, br.dan = 35, sad to treba rastaviti na br.god = 16, br.mes = 4, br.dan = (4 ili 5)!?!

Teti iz kadrovske službe treba da, u svom programu, kad vrši pregled podataka o zaposlenom licu vidi donesen radni staž i datum zaposlenja u njihovoj instituciji. Trenutno joj ne treba ništa više nego radni staž (broj god, mes, dana) od dana zasnivanja radnog odnosa lica u toj instituciji do danas, plus staž sa kojim je lice došlo u instituciju, tako da dobijemo ukupan zbir.


Što se tiče prebacivanja zbira dana u mesec + broj dana, ja lično mislim da treba uzeti u obzir broj dana u prethodnom mesecu od tekućeg.

Za mesece i godine nema dileme.

U skladu sa ovim i tvojim kodom sledeće 3 linije rade čitav posao:

Code:

 DMYBetween(ANow, AThen, Days, Months, Years);
 AThen :=  IncYear(IncMonth(IncDay(ANow, -Days-d), -Months-m), -Years-y);
 DMYBetween(ANow, AThen, Days, Months, Years);


Znači tekući datum umanjiš za dobijeni broj godina, meseci i dana i vidiš kolika je razlika sa sadašnjim datumom (da bi ti dane računao u odnosu na prethodni mesec).

-off topic-
Ja samo ne mogu da shvatim zašto ljudi vole da komplikuju i da izmišljaju toplu vodu. Bolje imati 2000 linija koda nego 3, jer to pokazuje da si više radio?
[ milanescape @ 31.01.2007. 12:42 ] @
"Ja samo ne mogu da shvatim zašto ljudi vole da komplikuju i da izmišljaju toplu vodu. Bolje imati 2000 linija koda nego 3, jer to pokazuje da si više radio? "

Vise radio!!!! JEL TO NEKI KOMPLEKS? STA?

Ja stvarno (DAKLE STVARNO) ne razumem ljude koji sa "premalo reci" previse pametuju !!!!
Zasto ne pimeniti te tri linije koda u resiti coveku problem???!!!. Voleo bih da vidim to resenje bez dodatne korekcije. Ja licno mislim da problem moze da se resi sa par linija koda (ne vise od 10) ali me mrzi da radim nesto sto sam ranije vec odradio (na ovaj ili onaj nacin).

"ja lično mislim da treba uzeti u obzir broj dana u prethodnom mesecu od tekućeg."

Nema sta tu da se misli. Postoji tri nacina racunanja radnog staza [TACNIJE RACUNANJA RAZLIKE IZMEDJU DVA DATUMA] (sve sam ih naveo). Trenutno se RS izracunava SIGURNO tako sto se izracuna broj PUNIH GODINA broj PUNIH MESECI i preostali deo dana se pretvara u mesec ako je dana>30. Gde god se obratis za pomoc reci ce ti da nisu sigurni kako se to radi. Ali zato postoji matematicki postupak koji je napravljen mnogo pre nego je neko ovde uopste saznao za Delphi.

Dakle kome treba ovo je sigurno ispravno:
Izracunas koliko je bilo dana u prvoj godini d1
Izracunas koliko je bilo dana u poslednjoj godini d2
Izracunas broj punih godina i pretvoris u dane d (izmedju prve i poslednje godine)
Izracunas broj prestupnih godina n
RS=(d1+d2+d-n)/365
Moze i ovako ako neko zeli RS=(d1+d2+d+n)/366 (n je broj godina koje nisu prestupne)

Sadasnji postupak (validan) se svodi na ovaj primer: 4,53g RS :==> 4 g, 1:12=0,53:x==>6,36 mes==>6 m 1:30=0,36:x ==> 10,8 dana==>10 dana (ovo pretvoriti *U STO MANJE KODA*)

Ovo sve naravno moze da se skrati, malo koriguje postupak, ... ali okreni obrni sve se uvek svodi na ovo. Da li ce se to uraditi na ovaj ili onaj nacin svejedno je. Naravno bolje je koristiti vec definisane procedure ali I "bolje je bilo kakvo resenje danas nego super resenje sutra"
[ milanescape @ 31.01.2007. 12:48 ] @
VISE VREMENSKIH INTERVALA SABIRAS ili kao BROJ DANA ili kao BROJ GODINA U OBLIKU DECIMALNOG ZAPISA.
KRAJNJI POSTUPAK JE ISTI.
Pozzzz
[ Miloš Baić @ 31.01.2007. 12:50 ] @
OK, momci, polako ...
Verovatno ste obojiaca u pravu. Treba zajedno da nađemo relevantno rešenje, ne da se prepiremo, te u tom duhu nastavimo.

Polako nadolazimo do rešenja. Naime, procedura:
Code:

procedure DMYBetween(ANow, AThen: TDate; var Days, Months, Years: Integer);
begin
  Years := YearsBetween(ANow, AThen);
  AThen := IncYear(AThen, Years);
  Months := MonthsBetween(ANow, AThen);
  AThen := IncMonth(AThen, Months);
  Days := DaysBetween(ANow, AThen);
end;

ako je ANow = 31.12.2006 a AThen = 30.11.2006, za Days daje 1 a Months 1!?!
To je ok, ali šta kad se staž broji i taj 30.11.2006 kao radni, odnosno, rezultat koji mi treba u ovom slučaju je 1 mesec i 2 dana (32 dana).
Npr. ako je lice radilo samo jedan dan, od 30.11.2006 do 30.11.2006, dakle samo sedmočasovno vreme, recimo, treba rezultat da bude 1 dan?
Moglo bi možda ovde:
Code:

procedure TForm1.Button2Click(Sender: TObject);
var d,m,g,Days,Months,Years: integer;
    ANow, AThen: TDate;
begin
 d:= 0;//radni staz donet  (broj dana)
 m:= 0;//radni staz donet  (broj meseci)
 g:= 0;//radni staz donet  (broj godina)
 ANow:= StrToDate('31.12.2006');//postavka datuma
 AThen:= StrToDate('30.11.2006');//postavka datuma
 DMYBetween(ANow, AThen, Days, Months, Years);
 AThen :=  IncYear(IncMonth(IncDay(ANow, -Days-d), -Months-m), -Years-g);
 DMYBetween(ANow, AThen, Days, Months, Years);
 ShowMessage('Od ' + DateToStr(AThen) + ' do ' + DateToStr(ANow)+ ' ima: ' + IntToStr(Days) + ' dana; ' + 
                      IntToStr(Months) + ' meseci; ' + IntToStr(Years) + ' godina;');
end;

se to moglo korigovati!?!

@milanescape
I tvoj primer daje isti rezultat kao što sam gore naveo.

[Ovu poruku je menjao loshmiscg dana 31.01.2007. u 14:04 GMT+1]
[ viking13 @ 31.01.2007. 13:42 ] @
Da se na početku razumemo, ne želim da se objašnjavam ni sa kim, niti da se inatim.

Citat:
milanescape: "Bolje imati 2000 linija koda nego 3, jer to pokazuje da si više radio? "

Vise radio!!!! JEL TO NEKI KOMPLEKS? STA?


Na kraju rečenice se nalazi UPITNIK, a to obično znači da je rečenica PITANJE! Znači, to nije moja tvrdnja nego pitanje.

Zamolio bih te da sledeći put prvo pročitaš šta sam napisao, da shvatiš šta sam hteo da kažem, pa tek onda da mi odgovoriš. Najljubaznije te to molim, a ako to ne želiš, onda je bolje da mi ne odgovaraš. Biće manje nepotrebih objašnjenja, kao što je ovo.

Citat:
milanescape:
Zasto ne pimeniti te tri linije koda u resiti coveku problem???!!!. Voleo bih da vidim to resenje bez dodatne korekcije. Ja licno mislim da problem moze da se resi sa par linija koda (ne vise od 10) ali me mrzi da radim nesto sto sam ranije vec odradio (na ovaj ili onaj nacin).


Poenta i jeste u tome da je moje rešenje NAJKRAĆE. Zato sam i pitao zašto dalje komplikovati.

Citat:
milanescape:
Gde god se obratis za pomoc reci ce ti da nisu sigurni kako se to radi.


E vidiš to i jeste najveći problem. Ni teta iz kadrovske kod mene u firmi nije sigurna kako se to radi.
[ viking13 @ 31.01.2007. 13:54 ] @
Citat:
loshmiscg: OK, momci, polako ...
ako je ANow = 31.12.2006 a AThen = 30.11.2006, za Days daje 1 a Months 1!?!
To je ok, ali šta kad se staž broji i taj 30.11.2006 kao radni, odnosno, rezultat koji mi treba u ovom slučaju je 1 mesec i 2 dana (32 dana).
Npr. ako je lice radilo samo jedan dan, od 30.11.2006 do 30.11.2006, dakle samo sedmočasovno vreme, recimo, treba rezultat da bude 1 dan?


Ako ti je to jedini problem u životu ti si srećan čovek. :)

DaysBetween računa samo ceo broj dana između dva datuma.

Znači rešenje je krajnje trivijalno:

Code:

procedure DMYBetween(ANow, AThen: TDate; var Days, Months, Years: Integer);
begin
  Years := YearsBetween(ANow, AThen);
  AThen := IncYear(AThen, Years);
  Months := MonthsBetween(ANow, AThen);
  AThen := IncMonth(AThen, Months);
  Days := DaysBetween(ANow, AThen) + 1;
end;
[ Miloš Baić @ 31.01.2007. 14:56 ] @
U ovom slučaju, za datum AThen = 01.01.2007 a za ANow = 10.01.2007 rezultat je 11 dana, a to nije tačno.
A ako u ovom delu:
Code:
Days := DaysBetween(ANow, AThen)+1;

izbacimo +1, rezultat je 9, što opet nije korektno.
Tačan rezultat treba ispisati 10.
[ viking13 @ 31.01.2007. 15:27 ] @
Citat:
loshmiscg: ako je ANow = 31.12.2006 a AThen = 30.11.2006, za Days daje 1 a Months 1!?!
To je ok, ali šta kad se staž broji i taj 30.11.2006 kao radni, odnosno, rezultat koji mi treba u ovom slučaju je 1 mesec i 2 dana (32 dana).


Na osnovu ovoga sam shvatio da želiš da ti DMYBetween vrati m = 1, d = 2. Ako pozoveš funkciju videćeš da ona stvarno vraća to što si tražio.

Problem je što u kodu koji je koristi 2 puta imaš DMYBetween. Pa samim tim imaš dva puta korekciju i odatle ti dan viška.

Vrati DMYBetween na staro, a korekciju uradi ovde.

Code:

 DMYBetween(ANow, AThen, Days, Months, Years);
 inc(Days);
 AThen :=  IncYear(IncMonth(IncDay(ANow, -Days-d), -Months-m), -Years-g);
 DMYBetween(ANow, AThen, Days, Months, Years);


Jel sad sve ok? :)
[ Miloš Baić @ 31.01.2007. 16:21 ] @
Mislim da je to to:

Za period ANow = 01.01.2007 i AThen = 01.01.2007 prikaže 1; - OK
Za period ANow = 01.01.2007 i AThen = 10.01.2007 prikaže 10; - OK
Za period ANow = 01.01.2007 i AThen = 01.01.2006 prikaže za dane 2 a za godinu 1; ???
[ milanescape @ 31.01.2007. 17:05 ] @
Ok. Necemo se prepirati. Ja samo ne razumem ljude koji zarad, pojma nemam cega, provociraju. "...Bolje imati 2000 linija koda nego 3, jer to pokazuje da si više radio? " Upitnik na kraju recenice ne ublazava ovo prethodno.
No uopste nije bitno. I ko je uopste ovde poredio duzinu koda. Nisam tvrdio da su tvoja resenja losa. Cak nisam tvrdio ni da je moja procedura potpuno ispravna jer nisam stigao da je proverim. Ja sam ranije radio program koji racuna broj godina radnog staza i to je procedura koja je nastala od ove-zato sam poslao ovo. Trenutno Cd na kojem se nalazi SIGURNO POTPUNO ISPRAVNA procedura nije kod mene inece bih proceduru poslao. Program je do PROSLE godine radio i niko se nije nesto bunio. Prosle godine po naredjenju "odozgo" dobili su nove programe za to. Moje misljenje je stvarno takvo da ako je coveku nesto hitno (a nekad moze biti), bolje mu pomoci koliko mozes, makar pomoc bila i losija nego mu uopste ne pomagati.
Jos na pocetku, rekao sam da je Savkic ponudio super resenje. Ako problem bolje sagledamo, na njegov kod (broj dana) dodas kod koji izracunava broj prestupnih godina i resio si gotovo ceo problem. Problem bi se sveo na RS=(d-n)/365 gde je n br.prest.god. Ono sto sam objasnio u vezi RS je na osnovu onoga sto sigurno znam.

No ukljucio sam se ne zbog "prethodnog" vec zbog ovog:

Matematicki to izgleda ovako (ALI OVDE NEMA NAGADJANJA NITI PRETPOSTAVKI-->100% JE TACNO):


ODUZIMANJE:
yyyy.mm.dd

|-->Ako je broj dana manji nego u staroj godini DODAJE SE BROJ DANA IZ PRETHODNOG MESECA
| (tacan broj dana prth. meseca,dakle ne 30)
|
2007.07.22
-2005.03.28
___________

==>

2007. 06. 22+30
-2005. 03. 28
___________________
2 g 3 m 24 d (ovo je metod koji se koristi godinama a smatra se ispravnim!)

SABIRANJE:
Ako ima vise ovakvih intervala:

g m d ===========>6 g 5 m + 57 dana (sad se koristi ono 30 dana)==> 6g 6m 27 dana
2 3 24
+ 3 2 21
+ 1 0 12
____________

Kod se moze smestiti u par redova-->ko ima vremena da pise.

Usput resenje ti je OK
Poz

Za Milosa: u radni staz ulazi uvek i prvi i poslednji upisani dan-to je sigurno. Nisam ostalo procitao-moguce je da ste sve priveli kraju. U svakom slucaju sve naj sa tim programom.
Poz

Ovu poruku je menjao milanescape dana 31.01.2007. u 18:19 GMT+1
]



[Ovu poruku je menjao milanescape dana 31.01.2007. u 21:52 GMT+1]
[ viking13 @ 31.01.2007. 17:20 ] @
Citat:
loshmiscg: Mislim da je to to:

Za period ANow = 01.01.2007 i AThen = 01.01.2007 prikaže 1; - OK
Za period ANow = 01.01.2007 i AThen = 10.01.2007 prikaže 10; - OK
Za period ANow = 01.01.2007 i AThen = 01.01.2006 prikaže za dane 2 a za godinu 1; ???


Malo prepravljena funkcija:

Code:

procedure DMYBetween(ANow, AThen: TDate; var Days, Months, Years: Integer);
begin
  AThen := IncDay(AThen, -1);
  Years := YearsBetween(ANow, AThen);
  AThen := IncYear(AThen, Years);
  Months := MonthsBetween(ANow, AThen);
  AThen := IncMonth(AThen, Months);
  Days := DaysBetween(ANow, AThen);
  dec(Days);
end;


Za period ANow = 01.01.2007 i AThen = 01.01.2007 vraća 0, 0, 0
Za period ANow = 01.01.2007 i AThen = 10.01.2007 vraća 9, 0, 0
Za period ANow = 01.01.2007 i AThen = 01.01.2006 vraća 0, 0, 1

Ovo su realne razlike, što znači da funkcija konačno radi kako treba.

E sad, treba dodati jedan dan za tekući radni staž (da bi se računao i taj prvi dan, a ne samo razlika).

Posle ovog koda:

Code:

 DMYBetween(ANow, AThen, Days, Months, Years);
 inc(Days);
 AThen :=  IncYear(IncMonth(IncDay(ANow, -Days-d), -Months-m), -Years-g);
 DMYBetween(ANow, AThen, Days, Months, Years);


Za period ANow = 01.01.2007 i AThen = 01.01.2007 dobićeš 1, 0, 0
Za period ANow = 01.01.2007 i AThen = 10.01.2007 dobićeš 10, 0, 0
Za period ANow = 01.01.2007 i AThen = 01.01.2006 dobićeš 1, 0, 1

Razlika jeste tačno godinu dana, ali ako se računa i prvi dan to je onda jedan dan više.

Za period ANow = 31.12.2006 i AThen = 01.01.2006 dobićeš 0, 0, 1 odnosno tačno godinu dana.
[ viking13 @ 31.01.2007. 17:59 ] @
Pošto vidim da si spustio loptu, red je da i ja to uradim. :)

Ako si se osetio prozvanim, ja ti se izvinjavam.

Što se tiče provociranja, evo ga savkic ziv i zdrav ovde, pa nek proba da se seti da li sam ja ikada provocirao bilo koga na yu.prog.delphi.

Što se tiče tvog koda, array DanaUMesecu mi neverovatno bode oči. Ali i sam kažeš da je procedura stara, tako da je moguće da si je pravio i pre nego što je napravljen DateUtils unit.

Citat:

Moje misljenje je stvarno takvo da ako je coveku nesto hitno (a nekad moze biti), bolje mu pomoci koliko mozes, makar pomoc bila i losija nego mu uopste ne pomagati.


Zato sam i napisao proceduru da bi pomogao čoveku.

U želji da čovek što pre dobije rešenje sam i počeo da brljam, al sam sve ispeglao na kraju. :)

Citat:

ODUZIMANJE:
yyyy.mm.dd

|-->Ako je broj dana manji nego u staroj godini DODAJE SE BROJ DANA IZ PRETHODNOG MESECA
| (tacan broj dana prth. meseca,dakle ne 30)
|
2007.07.22
-2005.03.28
___________

==>

2007. 06. 22+31
-2005. 03. 28
___________________
2 g 3 m 25 d (ovo je metod koji se koristi godinama a smatra se ispravnim!)


Apsolutno se slažem sa tobom, sem po pitanju rezultata. :)

Test datum ti je 2007.07.22, što znači da je prethodni mesec jun koji ima 30 dana, a ne 31.

Znači pravi rezultat dobijen ovim metodom je 2 g 3 m i 24 d.

DMYBetween kao rezultat daje takođe 2 g 3 m i 24 d.

Citat:

Za Milosa: u radni staz ulazi uvek i prvi i poslednji upisani dan-to je sigurno. Nisam ostalo procitao-moguce je da ste sve priveli kraju. U svakom slucaju sve naj sa tim programom.


Obzirom na test rezultate, ima kompletno rešenje sa sve uključenim tim prvim danom.
[ milanescape @ 31.01.2007. 20:28 ] @
Ma ok je. Nisam zlopamtilo.
Procedura je napravljena pre 6 god, otprilike. Nije bio u pitanju DateUtils vec skoro isti problem o kojem smo diskutovali u ovoj temi-masa pribliznih vrednosti i ni na jedno da se oslonis a kratak rok za izradu-nema vremena za eksperimentisanje. E onda sam odlucio da proceduru napravim sam, sto inace uvek uradim kad me iznervira neka od ponudjenih proc. ili funkc. Slicno sam uradio i sa onim kodom za tzv "zastitu progr.". Glupo jeste i staromodno (j-ga), ali ja sam onda sigurniji u rezultat i to je to. Inace promenljive u proceduri su bile krace tipa g,m,d,,pd.zd.. pa sam ih ja na brzinu (replace) sinoc izmenjao i poslao-samo zbog razumljivosti-sto opet naravno ne moze da smanji kod niti da ga ulepsa jer je takav kakav je-inace je napravljen brzo i nikad vise nisam stigao ni da ga pregledam ni da ga proverim. U stvari da ne davim previse, kod sam inace poslao usput. Prevashodni cilj mi je bio da objasnim kako se racuna rad. staz.

>"Test datum ti je 2007.07.22, što znači da je prethodni mesec jun koji ima 30 dana, a ne 31."

Da.Ok. Ovo je bio previd- (cilj mi je bio da uzmem za primer mesec koji ima 31 a ne 30 dana i u brzini sam uzeo pogresan)- u pravu si, jun ima 30 dana.

>"DMYBetween kao rezultat daje takođe 2 g 3 m i 24 d."
...
>"Obzirom na test rezultate, ima kompletno rešenje sa sve uključenim tim prvim danom."

Ok ti je kod, i dobar.
Ali moras priznati-svi na pocetku tvrde da "to" moze u dva tri koraka i na kraju kad stvarno "stavis karte na sto" i stvarno sagledas problem, uvek ispadne makar duplo. A realno, za filovanje koda nikad nema vremena.

Nije mi bio cilj da se prepiremo-inace nisam taj tip i stvarno verujem da si ok programer
Izvinjenje svima koji nisu duzni da citaju "nepotrebno"

& naravno izmenicu ovo zbog onih koji ce ovo nekada iskoristiti

2007.07.22
-2005.03.28
___________
==>
2007. 06. 22+30
-2005. 03. 28
_____________
2 g 3 m 24 d

g m d ===========>6 g 5 m + 57 dana (sad se koristi ono 30 dana)==> 6g 6m 27 dana
2 3 24
+ 3 2 21
+ 1 0 12
_______

& poz

[Ovu poruku je menjao milanescape dana 31.01.2007. u 22:04 GMT+1]
[ viking13 @ 31.01.2007. 22:41 ] @
Citat:

Ali moras priznati-svi na pocetku tvrde da "to" moze u dva tri koraka i na kraju kad stvarno "stavis karte na sto" i stvarno sagledas problem, uvek ispadne makar duplo. A realno, za filovanje koda nikad nema vremena.


Čim se spomene datum, ja prvo ukucam uses DateUtils, pa tek onda počnem da razmišljam. :)

Cilj mi je bio da ljudima koji ne koriste taj unit skrenem pažnju na njega.

Za funkciju tipa izračunaj razliku dva datuma (i predstavi je kako god ti padne na pamet), i ma kako da je odradiš ne može da bude mnogo koda. Posebno ako koristiš DateUtils.


--off topic--
Moj biviš direktor mi je ispričao jednu fantastičnu priču vezanu za količinu koda.

U zemlji Srbiji pre ne znam ni ja koliko godina neko "pametan" je smislio da i programeri treba da imaju normu. Kako programeru odrediti normu, pa prema broju linija koda!?

Šta misliš šta je bilo prvo što su programeri zahvaćeni time uradili?

Napravili program koji generiše X (broj propisan normom) linija koda. :)

A onda lepo objasnili nadređenom: "Ja sam normu ispunio, sad me pusti da radim."
[ Miloš Baić @ 31.01.2007. 23:32 ] @
Pozdrav dobri ljudi,

želim prvo da Vam se zahvalim, svima, jer ste mi u najkraćem roku pomogli rešiti problem.

@viking13
Da, tvoja prerađena procedura i drugi deo koda koji je koristi urodile su plodom. Probao sam na par primera, datuma, ali moram još malo je istestirati, pre puštanja u rad, pa ako budem imao još neko pitanje postaviću ga već.

Sve najbolje,
Miloš.
[ inherited @ 02.02.2007. 17:37 ] @
Da se malo nadovezem, na osnovu ovih primera kako bi mogao od danasnjeg datuma odrediti datum za n meseci?
Unese se datum u jedan maskedit a u edit broj meseci pa u trecem editu dobijemo datum.
[ savkic @ 02.02.2007. 17:57 ] @
> Da se malo nadovezem, na osnovu ovih primera kako bi mogao od danasnjeg datuma odrediti datum za n meseci?
> Unese se datum u jedan maskedit a u edit broj meseci pa u trecem editu dobijemo datum.

IncMonth?
[ Almedin @ 02.02.2007. 19:02 ] @
Nekada sam radio program koji je racunao upravo staz na osnovu perioda, evo kod u Clipper-u, Nisam imao potrebe raditi ga u Delphi-u, konvertovanje se moze uraditi za par minuta. Tada kada sam program koristio, provjeravao sam sa podacima iz Penzijskog osiguranja i bilo je sve u redu.

Code:

primjer upotrebe

na pocetku se 'ukupno' inicijalizuje nulama

AddDatSub(od1, do1, ukupno)
AddDatSub(od2, do2, ukupno)

sada 'ukupno' sadrzava vrijeme (staz)

===============
FUNCTION AddDatSub(dStart, dEnd, aTime)
PRIVATE aTmp[3]
aTmp[1] = YEAR(dEnd) - YEAR(dStart)
aTmp[2] = MONTH(dEnd) - MONTH(dStart)
aTmp[3] = DAY(dEnd) - DAY(dStart)

WHILE aTmp[3] < 0
aTmp[2]--
aTmp[3] = aTmp[3] + 30
END

WHILE aTmp[2] < 0
aTmp[1]--
aTmp[2] = aTmp[2] + 12
END

aTime[1] := aTime[1] + aTmp[1]
aTime[2] := aTime[2] + aTmp[2]
aTime[3] := aTime[3] + aTmp[3]

AdjustTime(aTime)

FUNCTION AdjustTime(aTime)
* aTime[1] - godine
* aTime[2] - mjeseci
* aTime[3] - dani

IF aTime[3] > 29
aTime[2] = aTime[2] + INT(aTime[3]/30)
aTime[3] = aTime[3] - INT(aTime[3]/30) * 30
END IF

IF aTime[2] > 11
aTime[1] = aTime[1] + INT(aTime[2]/12)
aTime[2] = aTime[2] - INT(aTime[2]/12) * 12
END IF
[ Miloš Baić @ 03.02.2007. 00:05 ] @
Code:
...
var
  Datum : TDateTime;
begin
  Datum := StrToDate('03.02.2007');//postavka datuma
  Datum := IncMonth(Datum, 5); //funkcija koja prikazuje datum za postavljeni  broj meseci, ovde za 5
  ShowMessage('Datum = ' + DateToStr(Datum)); // rezultat 03.07.2007
end;