Newsgroup: it.comp.lang.delphi
Titolo: gg mm aa trascorsi effettivi da calendario Help

Stavo preparando del codice che mi calcolasse i gg mm aa trascorsi tra due 
date inserite dall'utente.
Il calcolo deve essere fatto come da calendario: non si assume che i mesi 
siano tutti da 30gg!
Sotto riporto il codice.. se metto come date: 20/2/1990 - 19/2/1991 mi da' 
un anno esatto, ed e' corretto.
Se inserisco 20/2/1990 - 19/3/1991 dovrebbe dare un anno ed un mese se non 
erro, invece da' un anno
e 28 gg???
Il problema e' chiaramente nel modo di calcolo dei giorni "residui" e quando 
aumentare di un mese.
unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;
type
  TForm1 = class(TForm)
    GroupBox1: TGroupBox;
    Label1: TLabel;
    Edit1: TEdit;
    Label2: TLabel;
    Edit2: TEdit;
    GroupBox2: TGroupBox;
    Label3: TLabel;
    Label4: TLabel;
    Edit3: TEdit;
    Edit4: TEdit;
    Button1: TButton;
    Label5: TLabel;
    Label6: TLabel;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
    n: Word;
    function IsLeapAnno(Anno: Word): Boolean;
    function DaysThisMonth(Mese, Anno: Word): Word;
    function DayInYears(AnnoIniziale, AnnoFinale: Word): DWord;
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
implementation
{$R *.DFM}
function TForm1.IsLeapAnno(Anno: Word): Boolean; // Anni bisestili
begin
  Result := (Anno mod 4 = 0)  { Annos divisible by 4 are... }
    and ((Anno mod 100 <> 0) { ...except century Annos... }
    or (Anno mod 400 = 0)); { ...unless it's divisible by 400 }
end;
function TForm1.DaysThisMonth(Mese, Anno: Word): Word;
const
  DaysPerMonth: array[1..12] of Word =
    (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); { usual numbers of 
days }
begin
   Result := DaysPerMonth[Mese]; { normally, just return number }
   if (Mese = 2) and IsLeapAnno(Anno) then
      Inc(Result); { plus 1 in leap February }
end;
function TForm1.DayInYears(AnnoIniziale, AnnoFinale: Word): DWord;
var St, St2: String; gg: TDate;
begin
Result:=0;
St:='1/1/'+IntToStr(AnnoIniziale);
St2:='31/12/'+IntToStr(AnnoFinale);
gg:=StrToDate(St)-StrToDate(St2);
Result:=Trunc(gg);
end;
procedure TForm1.Button1Click(Sender: TObject);
var Anni, Mesi, Giorni, Anno, Mese, Giorno, Anno2, Mese2, Giorno2, Residui,
    GiorniPrimoMese, GiorniUltimoMese, MesiPrimaData, MesiSecData,
    ggTotUltMese: Word;
    DataIni, DataFinale: TDate;
begin
// Dati iniziali
if (Edit1.Text='') Or (Edit2.Text='') then exit;
Giorni:=0; Mesi:=0; Anni:=0;
DataIni:=StrToDate(Edit1.Text);
DecodeDate(DataIni,Anno,Mese,Giorno);
n:=DaysThisMonth(Mese,Anno);
GiorniPrimoMese:=n-Giorno+1;
//
DataFinale:=StrToDate(Edit2.Text);
DecodeDate(DataFinale,Anno2,Mese2,Giorno2);
GiorniUltimoMese:=Giorno2;
//
MesiPrimaData:=12-Mese;
MesiSecData:=Mese2-1;
//
ggTotUltMese:=DaysThisMonth(Mese2,Anno2);
// Calcolo
if Anno=Anno2 then
   begin
   if Mese2=Mese then
      Giorni:=Giorno2-Giorno+1
   else
      begin
      Residui:=GiorniPrimoMese+GiorniUltimoMese;
      n:=Residui Div ggTotUltMese;
      if n>=1 then
         begin
         Inc(Mesi,n);
         Giorni:=Residui Mod ggTotUltMese;
         end
      else
         Giorni:=Residui;
      end;
   end
else // Se gli anni sono differenti
   begin
   // Anni e Mesi
   Anni:=Anno2-Anno-1;
   // Mesi residui
   Residui:=MesiPrimaData+MesiSecData;
   n:=Residui Div 12;
   if n>=1 then
      begin
      Inc(Anni,n);
      Mesi:=Residui Mod 12;
      end
   else
      Mesi:=Residui;
   // Giorni e correzioni
   // gg. residui
   Residui:=GiorniPrimoMese+GiorniUltimoMese;
   n:=Residui Div ggTotUltMese;
   if n>=1 then
      begin
      Inc(Mesi,n);
      n:=Mesi div 12;
      if n>=1 then
         begin
         Inc(Anni,n);
         Mesi:=Mesi Mod 12;
         end;
      Giorni:=Residui Mod ggTotUltMese;
      end
   else
      Giorni:=Residui;
   end;
//
Label5.Caption:='Anni: '+IntToStr(Anni)+' - '+'Mesi: '+IntToStr(Mesi)+
                ' - '+'Giorni: '+IntToStr(Giorni);
end;
procedure TForm1.Button2Click(Sender: TObject);
var n: Integer;
begin
for n:=0 to Pred(ComponentCount) do
   if Components[n] is TEdit then
      TEdit(Components[n]).Text:='';
Label5.Caption:='0';
end;

 aumentare di un mese.
Scusa ma che versione di delphi stai usando?
Io la 6, e ci sono delle ottime funzioni nella DateUtils quali
DaysBetween
MonthsBetween
YearsBetween
WeeksBetween
DaySpan
Perche' reinventare la ruota? 
;-)
-- 
Morde. 
ICLDweb: 
http://www2.samatel.com/icld/

 quando aumentare di un mese.
Forse non ho capito bene il problema
Bye,
Raktzo

Ma...hai provato con DDelta:=DFinale-DIniziale e poi DecodeDate?
Bye,
Raktzo

 ;-)
Perché anche Borland ha programmatori estrosi ;-)
MonthsBetween fa uno strano calcolo approssimato, le cui 
motivazioni sinceramente non le ho capite.  Non ho capito perché 
considerare i giorni lunghi mediamente 30.4375 giorni.  E' una 
sciocchezza e introduce, volontariamente, possibili bug.  La 
lunghezza in giorni dei mesi è conosciuta a priori, in relazione 
all'anno, quindi non capisco perché non sfruttare un'informazione 
certa, per una incerta.  Di fatto, alla fine si ottiene un 
risultato sbagliato:
MonthsBetween(EncodeDate(2005,02,01),
               EncodeDate(2005,03,01)) = 0 (!).

 ha scritto nel messaggio 
news:11l6ywe1jskau.grjd3ho6v0vb$.dlg@40tude.net...


 Un anno o 365 giorni? Ci sono anni con 366 giorni
Un anno (non ha importanza i gg) in quanto il calcolo deve essere effettivo 
da calendario, quindi un anno dopo, allo stesso mese e un giorno prima una 
certa data dovrebbe darmi un anno o sbaglio?
Inserendo le date della prima riga e usando la funzione in D6 che da' gli: 
anni, mesi e gg trascorsi tra 2 date cosa ottenete??
Grazie, Giorgio 

 anni, mesi e gg trascorsi tra 2 date cosa ottenete??
[...]
uses
   DateUtils;
procedure TForm1.Button1Click(Sender: TObject);
var
   d1, d2: TDateTime;
begin
   d1 := StrToDate('20/2/1990');
   d2 := StrToDate('19/2/1991');
   ShowMessageFmt('anni=%d'#13#10'mesi=%d'#13#10'giorni=%d',
      [YearsBetween(d1, d2),
       MonthsBetween(d1, d2),
       DaysBetween(d1, d2)]);
end;
output:
anni=0
mesi=11
giorni=364

 oggi ordino D 2005! non ne posso piu'.
Caspita con D3 sei un po' troppo indietro: stai per fare un balzo
iperspaziale :-)
ciao!


 mesi siano tutti da 30gg!
Ho una unit da qualche parte che si occupa di queste cose.
Appena possibile la posto sul sito del NG.
-- 
ACSH
[D4]
Chi fa da se', fatica il doppio 

 ciao!
Speriamo di non cadere in un buco nero di nome "porting", ciao ;-))
Giorgio 

Ti ringrazio Andrea ma vedo che quelle funzioni forse non mi sarebbero di 
grande aiuto nel calcolo degli anni, mesi e gg effettivi da calendario.
Grazie lo stesso a tutti.
"Andrea Laforgia" <x...@xx.xx> ha scritto nel messaggio 
news:aFuBe.18925$b93....@tornado.fastwebnet.it...



Fatto.
Provatela e riferite eventuali bug.


 ha scritto nel messaggio 
news:WnTBe.73810$h5.30...@news3.tin.it...
