Orlando FMC Posted May 18, 2012 Report Share Posted May 18, 2012 Mestres, Alguem tem uma função que calcule o tempo entre datas (idade, por exemplo), retornando Anos, Meses e Dias? Orlando F Martins da Costa Windows 7 - FW [x]Harbour 11.10 - WorkShop 4.5 - PellesC orlandofmc@yahoo.com.br Belo Horizonte - MG Editado por - orlandof on 18/05/2012 20:34:22 Editado por - orlandof on 18/05/2012 22:25:41 Quote Link to comment Share on other sites More sharing options...
Orlando FMC Posted May 18, 2012 Author Report Share Posted May 18, 2012 Mestres, Alguem tem uma função que calcule o tempo entre datas (idade, por exemplo), retornando Anos, Meses e Dias? Orlando F Martins da Costa Windows 7 - FW [x]Harbour 11.10 - WorkShop 4.5 - PellesC orlandofmc@yahoo.com.br Belo Horizonte - MG Editado por - orlandof on 18/05/2012 20:34:22 Editado por - orlandof on 18/05/2012 22:25:41 Quote Link to comment Share on other sites More sharing options...
Theotokos Posted May 18, 2012 Report Share Posted May 18, 2012 alguem aqui no forum que postou mas não lembro então os créditos ao criador... function calcdias(dataini, datafim) dias :=day(datafim) -day(dataini)+1 meses:=month(datafim)-month(dataini) anos :=year(datafim) -year(dataini) if dias<0 meses:=meses-1 dias :=dias+val(substr('31'+iif((year(datafim)-iif(month(datafim)=1,1,0))%4=0,'29','28')+'31303130313130313031',iif(month(datafim)=1,12,month(datafim)-1)*2-1,2)) endif if meses<0 anos :=anos-1 meses:=meses+12 endif if dias=val(substr('31'+iif(year(datafim)%4=0,'29','28')+'31303130313130313031',month(datafim)*2-1,2)) dias :=0 meses:=meses+1 if meses=12 meses:=0 anos :=anos+1 endif endif cStr := StrZero(Anos,2) + ' ano(s) ' + StrZero(Meses,2) + ' mes(es) ' + StrZero(Dias,2) + " dia(s)" return cStr id=code>id=code> Quote Link to comment Share on other sites More sharing options...
Orlando FMC Posted May 18, 2012 Author Report Share Posted May 18, 2012 Obrigado Rone. Estou testando aqui. Numa primeira tentativa, gostei dos resultados, mas, o retorno foi o mesmo, em situações diferentes, como no exemplo a seguir: 31/12/2011 a 18/05/2012 resultou 00 anos 04 meses 18 dias 01/01/2012 a 18/05/2012 resultou 00 anos 04 meses 18 dias Orlando F Martins da Costa Windows 7 - FW [x]Harbour 11.10 - WorkShop 4.5 - PellesC orlandofmc@yahoo.com.br Belo Horizonte - MG Editado por - orlandof on 18/05/2012 22:28:10 Editado por - orlandof on 20/05/2012 12:50:27 Quote Link to comment Share on other sites More sharing options...
Ariston Santos Posted May 19, 2012 Report Share Posted May 19, 2012 Olá. Eu uso esta para mostrar status de vencimento de contas a receber **+-+**+-+**+-+**+-+**+-+**+-+**+-+**+-+**+-+**+-+**+-+**+-+**+-+**+-+**+-+** FUNCTION CalcAtraso(d_Ini, d_Fim) LOCAL cAtraso := "", nAns := 0, nMes := 0, nDia := 0, lAtraso := .T. DEFAULT d_Ini := CTOD("01/01/2012") DEFAULT d_Fim := DATE() IF EMPTY(DTOS(d_Ini)) RETURN ("Indefinido") ENDIF IF d_Fim > d_Ini mTotDia := d_Fim - d_Ini ELSE mTotDia := d_Ini - d_Fim lAtraso := .F. ENDIF IF mTotDia > 0 IF mTotDia > 30 ; nMes := INT(mTotDia/30) ; ENDIF IF nMes > 0; mTotDia -= (nMes * 30) ; ENDIF nDia := mTotDia IF nAns > 0 cAtraso += ALLTRIM(STR(nAns))+IIF(nAns = 1, " ano ", " anos ") ENDIF IF nMes > 0 IF ! EMPTY(cAtraso) ; cAtraso += ", " ; ENDIF cAtraso += ALLTRIM(STR(nMes))+IIF(nMes = 1, " mês ", " meses ") ENDIF IF nDia > 0 IF ! EMPTY(cAtraso) ; cAtraso += " e " ; ENDIF cAtraso += ALLTRIM(STR(nDia))+IIF(nDia = 1, " dia", " dias") ENDIF IF ! lAtraso ; cAtraso := "Daqui à "+cAtraso ; ENDIF ELSE cAtraso := "Vencendo hoje" ENDIF RETURN( cAtraso ) **+-+**+-+**+-+**+-+**+-+**+-+**+-+**+-+**+-+**+-+**+-+**+-+**+-+**+-+**+-+** id=code>id=code> Conheça Pacote Fivewin em http://www.arsoft-ap.com.br Quote Link to comment Share on other sites More sharing options...
Orlando FMC Posted May 23, 2012 Author Report Share Posted May 23, 2012 Obrigado, Ariston. Estou usando a função abaixo, com resultados satisfatórios, apesar de, assim como a função enviada pelo Rone - de autoria não identificada - é imprecisa em alguns casos, no cálculo do nº de dias - às vezes, dá diferença de 1 ou 2 dias. ================== FUNCTION FTempo( DtIni , DtFim , nFormato ) // Calcula o tempo entre datas no formato AAAAaMMmDDd // Orlando F Martins da Costa - 21/05/12 // DtIni, DtFim -> Datas de inicio e de Fim - não importa a ordem // nFormato = 0 matem os valores 0 (default) // = 1 elimina os valores zero e os espaços // = 2 elimina os valores zero mantendo os espaços // Atenção: pode ocorrer o retorno do tipo: n meses + 30 dias, já que nos cálculos não se utilizam o padrão de 30 dias para cada mês, // e sim os meses efetivamente corridos, sejam eles de 30, 31, 28 ou 29 dias. LOCAL cCENT:="on" , xx, yy LOCAL cDataIni, cDiaIni, cMesIni, cAnoIni LOCAL cDataFim, cDiaFim, cMesFim, cAnoFim LOCAL nDataIni, nDiaIni, nMesIni, nAnoIni LOCAL nDataFim, nDiaFim, nMesFim, nAnoFim LOCAL cAnos, cMeses, cDias LOCAL nAnos, nMeses, nDias:=0 LOCAL cTempo:="dd/mm/aaaa" IF VALTYPE(nFormato) = "U" ; nFormato := 0 ; ENDIF IF DAY(DtIni) = 0 ; DtIni = DATE() ; ENDIF IF DAY(DtFim) = 0 ; DtFim = DATE() ; ENDIF IF LEN(DTOC(DATE())) = 8 ; cCENT="off" ; ENDIF SET CENT ON // LEN(DTOC(DATE())) = 10 // inversão - Inverte caso DtIni seja maior que DtFim xx=DtIni ; yy=DtFim IF XX > YY ; DtIni = YY ; DtFim = XX ; ENDIF // cDataIni=DTOC(DtIni) ; cDataFim=DTOC(DtFim) cDiaIni =SUBS(cDataIni,1,2) ; cMesIni=SUBS(cDataIni,4,2) ; cAnoIni=SUBS(cDataIni,7) cDiaFim =SUBS(cDataFim,1,2) ; cMesFim=SUBS(cDataFim,4,2) ; cAnoFim=SUBS(cDataFim,7) nDiaIni=VAL(cDiaIni) ; nMesIni=VAL(cMesIni) ; nAnoIni=VAL(cAnoIni) nDiaFim=VAL(cDiaFim) ; nMesFim=VAL(cMesFim) ; nAnoFim=VAL(cAnoFim) // anos nAnos = nAnoFim - nAnoIni IF nMesIni > nMesFim ; nAnos-- ; ENDIF // meses nMeses = nMesFim - nMesIni IF nDiaFim < nDiaIni ; nMeses-- ; ENDIF IF nMeses<0 ; nMeses+=12 ; ENDIF // dias - não tem precisão, variando em até 3 dias. nDiaRef=nDiaIni ; nMesRef = nMesFim ; nAnoRef = nAnoFim // referencias p/ cálculo dos dias. IF nDiaFim < nDiaRef nMesRef-- IF nMesRef = 0 nMesRef = 12 nAnoRef-- ENDIF ENDIF nDiasAcerto=0 IF nDiaRef= 30 .AND. nMesRef= 02 ; nDiasAcerto = nDiasAcerto - 1 ; ENDIF IF nDiaRef= 31 .AND. nMesRef= 02 ; nDiasAcerto = nDiasAcerto - 2 ; ENDIF DO CASE CASE nDiaRef = 31 .AND. AT(STRZERO(nMesRef,2) , " 04 06 09 11 " ) <> 0 ; nDiaRef = 01 ; nMesRef++ CASE nMesRef = 2 .AND. (nDiaRef = 30 .OR. nDiaRef = 31 ) ; nDiaRef = 01 ; nMesRef = 03 CASE nMesRef = 2 .AND. nDiaRef = 29 .AND. !AnoBissexto(nAnoRef) ; nDiaRef = 01 ; nMesRef = 03 ENDCASE cAnoRef = RIGHT(" "+ALLTRIM(STR(nAnoRef )) , 4 ) cMesRef = STRZERO( nMesRef , 2 ) cDiaRef = STRZERO( nDiaRef , 2 ) dtRef = CTOD(cDiaRef + "/" + cMesRef + "/" + cAnoRef ) // data de referencia DO CASE * CASE AT(STRZERO(nMesIni,2) , " 04 06 09 11 " ) <> 0 ; dtRef = dtRef + 1 * CASE nMesIni = 2 .AND. AnoBissexto(nAnoIni) ; dtRef = dtRef + 2 * CASE nMesIni = 2 .AND. !AnoBissexto(nAnoIni) ; dtRef = dtRef + 3 ENDCASE nDias = dtFim - dtRef + nDiasAcerto // cAnos = RIGHT(" "+ALLTRIM(STR(nAnos )),4) cMeses = STRZERO(nMeses , 2 ) cDias = STRZERO(nDias , 2 ) cTempo = cAnos+"a"+cMeses+"m"+cDias+"d" IF nFormato = 1 // = 1 elimina os valores zero e os espaços cTempo=STRTRAN(cTempo, "0000a"," ") cTempo=STRTRAN(cTempo, " 000a"," ") cTempo=STRTRAN(cTempo, " 00a"," ") cTempo=STRTRAN(cTempo, " 0a"," ") cTempo=STRTRAN(cTempo, " a"," ") cTempo=STRTRAN(cTempo,"00m"," ") cTempo=STRTRAN(cTempo,"00d"," ") cTempo=ALLTRIM(cTempo) cTempo=STRTRAN(cTempo," ","") DO WHILE LEFT(cTempo,1)="0" cTempo=SUBS(cTempo,2) ENDDO ENDIF IF nFormato = 2 // = 2 elimina os valores zero mantendo os espaços cTempo=STRTRAN(cTempo, "0000a"," ") cTempo=STRTRAN(cTempo, " 000a"," ") cTempo=STRTRAN(cTempo, " 00a"," ") cTempo=STRTRAN(cTempo, " 0a"," ") cTempo=STRTRAN(cTempo,"00m"," ") cTempo=STRTRAN(cTempo,"00d"," ") ENDIF IF cCENT="off" ; SET CENT OFF ; ENDIF RETURN cTempo Orlando F Martins da Costa Windows 7 - FW [x]Harbour 11.10 - WorkShop 4.5 - PellesC orlandofmc@yahoo.com.br Belo Horizonte - MG Quote Link to comment Share on other sites More sharing options...
vagner Posted May 24, 2012 Report Share Posted May 24, 2012 Olá, Encontrei uma função que montei uma vez /********************************************************* * Função : Ano_Mes_Dia() - Função para Calcular a Idade * Programador : vagner * Data : 23/10/2009 - 13:21:23 * Revisado em : 29/10/2009 - 22:05:46 Por : vagner * Parâmetros : * dDat1 - Primeira data * dDat2 - Segunda Data * cVari - Variável para atualizar * oObje - Objeto para atualizar **********************************************************/ Static Func Ano_Mes_Dia(dDat1,dDat2,cVari,oObje) Local nTotAnos,nTotMese,nTotDias Local nMesAnt,nAnoAnt,nDiaAnt Local dDataAnt Default dDat2 := Date() If Empty(dDat1) ; Retu(.T.) ; Endif If Empty(dDat2) ; Retu(.T.) ; Endif If dDat2 > Date() ; dDat2 := Date() ; Endif If Month(dDat2)+Day(dDat2) >= Month(dDat1)+Day(dDat1) nTotAnos := Year(dDat2) - Year(dDat1) nTotMese := Month(dDat2) - Month(dDat1) - Iif(Day(dDat2) >= Day(dDat1),0,1) Else nTotAnos := (Year(dDat2) - Year(dDat1)) - 1 nTotMese := (Month(dDat2)+12) - Month(dDat1) - Iif(Day(dDat2) >= Day(dDat1),0,1) Endif If Day(dDat2) >= Day(dDat1) nTotDias := Day(dDat2)-Day(dDat1) Else If Month(dDat2) == 1 nMesAnt := 12 nAnoAnt := Year(dDat2)-1 Else nMesAnt := Month(dDat2)-1 nAnoAnt := Year(dDat2) Endif If Day(dDat1) == 31 If nMesAnt == 2 ; nDiaAnt := Iif(Mod(nAnoAnt,4) == 0,29,28) ElseIf nMesAnt == 4 .or. nMesAnt == 6 .or. nMesAnt == 9 .or. nMesAnt == 11 ; nDiaAnt := 30 Else ; nDiaAnt := Day(dDat1) Endif ElseIf Day(dDat1) == 30 If nMesAnt == 2 ; nDiaAnt := Iif(Mod(nAnoAnt,4) == 0,29,28) Else ; nDiaAnt := Day(dDat1) Endif Endif dDataAnt := CtoD( StrZero(nDiaAnt,2,0)+"/"+ StrZero(nMesAnt,2,0)+"/"+ StrZero(nAnoAnt,4,0) ) nTotDias := dDat2 - dDataAnt Endif cVari := ( Iif(nTotAnos != 0,AllTrim(Str(nTotAnos,4,0)) + Iif(nTotAnos > 1," Anos" ," Ano")+" , ","")+Iif(nTotMese != 0,AllTrim(Str(nTotMese,2,0)) + Iif(nTotMese > 1," Meses"," Mês")+Iif(nTotDias != 0," e ",""),"")+Iif(nTotDias != 0,AllTrim(Str(nTotDias,2,0)) + Iif(nTotDias > 1," Dias" ," Dia"),Iif(nTotMese == 0,"Hoje",""))) oObje :Refresh() Retu( .T. ) id=code>id=code>Vagner Wirts "Ele não sabendo que era impossÃvel, foi lá e fez" Quote Link to comment Share on other sites More sharing options...
emotta Posted May 24, 2012 Report Share Posted May 24, 2012 Segue um código bem simples que fiz, faça mais alguns testes pra garantir. Function ContaDias() Local dData1 := CtoD("05/02/2005") Local dData2 := CtoD("02/04/2005") Local nDifAno Local nDifMes Local nDifDia //dData2++ // caso queira considerar o dia corrente. Ex: 01/01/2012 - 02/01/2012 => 2 dias. Caso queira desconsiderar comente a linha que o resultado seria 1 dia. nDifAno := Year(dData2)-Year(dData1) nDifMes := Month(dData2)-Month(dData1) nDifDia := Day(dData2)-Day(dData1) If Month(dData1) > Month(dData2) .or. (Month(dData1) == Month(dData2) .and. Day(dData1) > Day(dData2)) nDifAno-- nDifMes+=12 EndIf If Day(dData1) > Day(dData2) nDifMes-- nDifDia := Day(EoM(AddMonth(dData2,-1))) + nDifDia + 1 EndIf MsgStop(Str(nDifAno,2)+" anos "+Str(nDifMes,2)+" meses "+Str(nDifDia,6)+" dias") Return .f. // usar caso na sua versao do Harbour/xHarbour não tenha essa funcao que simplesmente retorna o ultimo dia do mes da data passada como parametro Static Function EoM(dData) Local dDatRet := dData dDatRet := AddMonth(dDatRet,1) // adiciona um mes a data dDatRet := CtoD("01/"+StrZero(Month(dDatRet),2)+"/"+Str(Year(dDatRet),4))-1 Return dDatRet Eduardo Motta emotta@gmail.com.br FWH 9.09 (original) - xHARBOUR 1.2.1 (comercial e original) - SQLRDD Quote Link to comment Share on other sites More sharing options...
vagner Posted May 25, 2012 Report Share Posted May 25, 2012 citação:Segue um código bem simples que fiz, faça mais alguns testes pra garantir. Function ContaDias() Local dData1 := CtoD("05/02/2005") Local dData2 := CtoD("02/04/2005") Local nDifAno Local nDifMes Local nDifDia //dData2++ // caso queira considerar o dia corrente. Ex: 01/01/2012 - 02/01/2012 => 2 dias. Caso queira desconsiderar comente a linha que o resultado seria 1 dia. nDifAno := Year(dData2)-Year(dData1) nDifMes := Month(dData2)-Month(dData1) nDifDia := Day(dData2)-Day(dData1) If Month(dData1) > Month(dData2) .or. (Month(dData1) == Month(dData2) .and. Day(dData1) > Day(dData2)) nDifAno-- nDifMes+=12 EndIf If Day(dData1) > Day(dData2) nDifMes-- nDifDia := Day(EoM(AddMonth(dData2,-1))) + nDifDia + 1 EndIf MsgStop(Str(nDifAno,2)+" anos "+Str(nDifMes,2)+" meses "+Str(nDifDia,6)+" dias") Return .f. // usar caso na sua versao do Harbour/xHarbour não tenha essa funcao que simplesmente retorna o ultimo dia do mes da data passada como parametro Static Function EoM(dData) Local dDatRet := dData dDatRet := AddMonth(dDatRet,1) // adiciona um mes a data dDatRet := CtoD("01/"+StrZero(Month(dDatRet),2)+"/"+Str(Year(dDatRet),4))-1 Return dDatRet Eduardo Motta emotta@gmail.com.br FWH 9.09 (original) - xHARBOUR 1.2.1 (comercial e original) - SQLRDD id=quote>id=quote>Eduardo, vc considerou os anos bissextos ? Vagner Wirts "Ele não sabendo que era impossÃvel, foi lá e fez" Quote Link to comment Share on other sites More sharing options...
emotta Posted May 25, 2012 Report Share Posted May 25, 2012 Sim Vagner, nos testes que fiz deu certo com ano normal e bisexto... Inclusive no teste que acima não deu certo usando a outra função nessa funcao que fiz resultou certo. 31/12/2011 a 18/05/2012 resultou 00 anos 04 meses 18 dias 01/01/2012 a 18/05/2012 resultou 00 anos 04 meses 17 dias citação: citação:Segue um código bem simples que fiz, faça mais alguns testes pra garantir. Function ContaDias() Local dData1 := CtoD("05/02/2005") Local dData2 := CtoD("02/04/2005") Local nDifAno Local nDifMes Local nDifDia //dData2++ // caso queira considerar o dia corrente. Ex: 01/01/2012 - 02/01/2012 => 2 dias. Caso queira desconsiderar comente a linha que o resultado seria 1 dia. nDifAno := Year(dData2)-Year(dData1) nDifMes := Month(dData2)-Month(dData1) nDifDia := Day(dData2)-Day(dData1) If Month(dData1) > Month(dData2) .or. (Month(dData1) == Month(dData2) .and. Day(dData1) > Day(dData2)) nDifAno-- nDifMes+=12 EndIf If Day(dData1) > Day(dData2) nDifMes-- nDifDia := Day(EoM(AddMonth(dData2,-1))) + nDifDia + 1 EndIf MsgStop(Str(nDifAno,2)+" anos "+Str(nDifMes,2)+" meses "+Str(nDifDia,6)+" dias") Return .f. // usar caso na sua versao do Harbour/xHarbour não tenha essa funcao que simplesmente retorna o ultimo dia do mes da data passada como parametro Static Function EoM(dData) Local dDatRet := dData dDatRet := AddMonth(dDatRet,1) // adiciona um mes a data dDatRet := CtoD("01/"+StrZero(Month(dDatRet),2)+"/"+Str(Year(dDatRet),4))-1 Return dDatRet Eduardo Motta emotta@gmail.com.br FWH 9.09 (original) - xHARBOUR 1.2.1 (comercial e original) - SQLRDD id=quote>id=quote>Eduardo, vc considerou os anos bissextos ? Vagner Wirts "Ele não sabendo que era impossÃvel, foi lá e fez" id=quote>id=quote>Eduardo Motta emotta@gmail.com.br FWH 9.09 (original) - xHARBOUR 1.2.1 (comercial e original) - SQLRDD Editado por - emotta on 25/05/2012 16:41:26 Quote Link to comment Share on other sites More sharing options...
vagner Posted May 25, 2012 Report Share Posted May 25, 2012 citação:Sim Vagner, nos testes que fiz deu certo com ano normal e bisexto... Inclusive no teste que acima não deu certo usando a outra função nessa funcao que fiz resultou certo. 31/12/2011 a 18/05/2012 resultou 00 anos 04 meses 18 dias 01/01/2012 a 18/05/2012 resultou 00 anos 04 meses 17 dias id=quote>id=quote>Olá, faça o teste também com 31/12/2010 a 18/05/2011 verá que retornará 00 anos 04 meses 18 dias Vagner Wirts "Ele não sabendo que era impossÃvel, foi lá e fez" Quote Link to comment Share on other sites More sharing options...
emotta Posted May 25, 2012 Report Share Posted May 25, 2012 Vagner, veja que eu previ essa situação no fonte, por isso tem a seguinte linha comentada: //dData2++ // caso queira considerar o dia corrente. Ex: 01/01/2012 - 02/01/2012 => 2 dias. Caso queira desconsiderar comente a linha que o resultado seria 1 dia. Ou seja, se deseja CONSIDERAR o dia atual para efeito de diferenca de dias então é só tirar o comentario da linha e deixar: dData2++ A questão ai é conceito, 01/01/2012 - 02/03/2012 deve dar 2 meses e 1 dia ou 2 meses e dois dias. Se desejar 2 meses e 1 dia comente o dData2++ e se desejar que o resultado seja 2 meses e 2 dias (porque conta o dia da data2) então é só deixar dData2++. Isso nao tem relação com ser ou não bisexto, pelo menos não vi isso. O fonte da funcao achei mais limpo e pratico. abraços citação: citação:Sim Vagner, nos testes que fiz deu certo com ano normal e bisexto... Inclusive no teste que acima não deu certo usando a outra função nessa funcao que fiz resultou certo. 31/12/2011 a 18/05/2012 resultou 00 anos 04 meses 18 dias 01/01/2012 a 18/05/2012 resultou 00 anos 04 meses 17 dias id=quote>id=quote>Olá, faça o teste também com 31/12/2010 a 18/05/2011 verá que retornará 00 anos 04 meses 18 dias Vagner Wirts "Ele não sabendo que era impossÃvel, foi lá e fez" id=quote>id=quote>Eduardo Motta emotta@gmail.com.br FWH 9.09 (original) - xHARBOUR 1.2.1 (comercial e original) - SQLRDD Quote Link to comment Share on other sites More sharing options...
emotta Posted May 26, 2012 Report Share Posted May 26, 2012 Vagner o resultado da diferença de 31/12/2011 a 18/05/2012 e 31/12/2010 a 18/05/2011 tem que ser o mesmo meu amigo... Independende de ser ano bisexto ou não... Teste correto com ano bisexto: 20/02/2011 - 10/03/2011 => 19 dias 20/02/2012 - 10/03/2012 => 20 Dias Neste exemplo ele começa a contar a partir do dia 20. Caso não queira contar o primeiro dia tem que tirar o comentario do dData2++ Abraço, citação: citação:Sim Vagner, nos testes que fiz deu certo com ano normal e bisexto... Inclusive no teste que acima não deu certo usando a outra função nessa funcao que fiz resultou certo. 31/12/2011 a 18/05/2012 resultou 00 anos 04 meses 18 dias 01/01/2012 a 18/05/2012 resultou 00 anos 04 meses 17 dias id=quote>id=quote>Olá, faça o teste também com 31/12/2010 a 18/05/2011 verá que retornará 00 anos 04 meses 18 dias Vagner Wirts "Ele não sabendo que era impossÃvel, foi lá e fez" id=quote>id=quote>Eduardo Motta emotta@gmail.com.br FWH 9.09 (original) - xHARBOUR 1.2.1 (comercial e original) - SQLRDD Editado por - emotta on 28/05/2012 09:30:28 Quote Link to comment Share on other sites More sharing options...
sambomb Posted May 28, 2012 Report Share Posted May 28, 2012 dDataIni := cTod("01/01/2011") dDataFim := cTod("31/12/2011") nDias := dDataFim - dDataIni i := 1 nDiaIni := Day(dDataIni) nMesIni := Month(dDataIni) nAnoIni := Year(dDataIni) While i <= nDias nDiaAnt := Day(dDataIni) nMesAnt := Month(dDataIni) nAnoAnt := Year(dDataIni) dDataIni++ If nAnoAnt != Year(dDataIni) nMes++ nAno++ elseif nMesAnt != Month(dDataIni) nMes++ end i++ end Dependendo do seu ponto de vista isso pode resolver, se dia inicial for 31/12/2011 e dia final for 01/01/2012, essa lógica vai identificar que se passaram 1 dia, virou 1 mês e virou 1 ano. Para identificar valores absolutos pode tentar fazer o seguinte. nDias := dDiaFim - dDiaIni nAno := 0 nDiasAno := (If( dDataIni < ctod("01/03/"+AllTrim(str(year(dDiaIni)))) .And. Mod( year(dDiaIni)+nAno,4) = 0, 366, 365) While nDias > nDiasAno nDias -= nDiasAno nAno++ nDiasAno := ( If( dDataIni < ctod("01/03/"+AllTrim(str(year(dDiaIni)))) .And. Mod( year(dDiaIni)+nAnoe,4) = 0, 366, 365) end id=code>id=code>Depois segue a mesma lógica para os mêses e o resto você ´pode dividir por 7 para obter semanas e depois o resto são os dias... RCA Sistemas - Itaocara - RJ Editado por - sambomb on 28/05/2012 10:23:10 Quote Link to comment Share on other sites More sharing options...
emotta Posted May 28, 2012 Report Share Posted May 28, 2012 Esse código pode ficar lento se utilizado por exemplo, em um relatório com milhares de clientes que tenham uma coluna para colocar esta descricao. Como faz o while para cada dia e vai somando então para retornar por exemplo, o tempo de 30 anos, ele faria 9000 somas. O código abaixo está limpo, prático e faz apenas alguns cálculos independente da diferenca entre as datas. (E considera corretamente ano normal ou bisexto). Function ContaDias() Local dData1 := CtoD("05/02/2005") Local dData2 := CtoD("02/04/2005") Local nDifAno Local nDifMes Local nDifDia //dData2++ // caso queira considerar o dia corrente. Ex: 01/01/2012 - 02/01/2012 => 2 dias. Caso queira desconsiderar comente a linha que o resultado seria 1 dia. nDifAno := Year(dData2)-Year(dData1) nDifMes := Month(dData2)-Month(dData1) nDifDia := Day(dData2)-Day(dData1) If Month(dData1) > Month(dData2) .or. (Month(dData1) == Month(dData2) .and. Day(dData1) > Day(dData2)) nDifAno-- nDifMes+=12 EndIf If Day(dData1) > Day(dData2) nDifMes-- nDifDia := Day(EoM(AddMonth(dData2,-1))) + nDifDia + 1 EndIf MsgStop(Str(nDifAno,2)+" anos "+Str(nDifMes,2)+" meses "+Str(nDifDia,6)+" dias") Return .f. // usar caso na sua versao do Harbour/xHarbour não tenha essa funcao que simplesmente retorna o ultimo dia do mes da data passada como parametro Static Function EoM(dData) Local dDatRet := dData dDatRet := AddMonth(dDatRet,1) // adiciona um mes a data dDatRet := CtoD("01/"+StrZero(Month(dDatRet),2)+"/"+Str(Year(dDatRet),4))-1 Return dDatRet citação: dDataIni := cTod("01/01/2011") dDataFim := cTod("31/12/2011") nDias := dDataFim - dDataIni i := 1 nDiaIni := Day(dDataIni) nMesIni := Month(dDataIni) nAnoIni := Year(dDataIni) While i <= nDias nDiaAnt := Day(dDataIni) nMesAnt := Month(dDataIni) nAnoAnt := Year(dDataIni) dDataIni++ If nAnoAnt != Year(dDataIni) nMes++ nAno++ elseif nMesAnt != Month(dDataIni) nMes++ end i++ end Dependendo do seu ponto de vista isso pode resolver, se dia inicial for 31/12/2011 e dia final for 01/01/2012, essa lógica vai identificar que se passaram 1 dia, virou 1 mês e virou 1 ano. Para identificar valores absolutos pode tentar fazer o seguinte. nDias := dDiaFim - dDiaIni nAno := 0 nDiasAno := (If( dDataIni < ctod("01/03/"+AllTrim(str(year(dDiaIni)))) .And. Mod( year(dDiaIni)+nAno,4) = 0, 366, 365) While nDias > nDiasAno nDias -= nDiasAno nAno++ nDiasAno := ( If( dDataIni < ctod("01/03/"+AllTrim(str(year(dDiaIni)))) .And. Mod( year(dDiaIni)+nAnoe,4) = 0, 366, 365) end id=code>id=code>Depois segue a mesma lógica para os mêses e o resto você ´pode dividir por 7 para obter semanas e depois o resto são os dias... RCA Sistemas - Itaocara - RJ Editado por - sambomb on 28/05/2012 10:23:10 id=quote>id=quote>Eduardo Motta emotta@gmail.com.br FWH 9.09 (original) - xHARBOUR 1.2.1 (comercial e original) - SQLRDD Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.