Jump to content
Fivewin Brasil

Tempo entre datas


Orlando FMC

Recommended Posts

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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>

Perfil.jpg

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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>

ariston_forum.jpg

Conheça Pacote Fivewin em http://www.arsoft-ap.com.br

Link to comment
Share on other sites

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

Link to comment
Share on other sites

Olá,

Encontrei uma função que montei uma vez icon_smile.gif


/*********************************************************

* 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

bgprofilea.jpg

"Ele não sabendo que era impossível, foi lá e fez"

Link to comment
Share on other sites

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

AJbJ

Link to comment
Share on other sites

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

AJbJ


id=quote>id=quote>

Eduardo, vc considerou os anos bissextos ?

Vagner Wirts

bgprofilea.jpg

"Ele não sabendo que era impossível, foi lá e fez"

Link to comment
Share on other sites

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

AJbJ


id=quote>id=quote>

Eduardo, vc considerou os anos bissextos ?

Vagner Wirts

bgprofilea.jpg

"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

AJbJ

Editado por - emotta on 25/05/2012 16:41:26

Link to comment
Share on other sites

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

icon_smile_wink.gif

Vagner Wirts

bgprofilea.jpg

"Ele não sabendo que era impossível, foi lá e fez"

Link to comment
Share on other sites

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

icon_smile_wink.gif

Vagner Wirts

bgprofilea.jpg

"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

AJbJ

Link to comment
Share on other sites

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

icon_smile_wink.gif

Vagner Wirts

bgprofilea.jpg

"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

AJbJ

Editado por - emotta on 28/05/2012 09:30:28

Link to comment
Share on other sites


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...

sambomb.jpg

RCA Sistemas - Itaocara - RJ

Editado por - sambomb on 28/05/2012 10:23:10

Link to comment
Share on other sites

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...

sambomb.jpg

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

AJbJ

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...