Contar meses entre dos fechas

395 views
Skip to first unread message

Dsanchez

unread,
Apr 20, 2017, 1:49:15 PM4/20/17
to publice...@googlegroups.com
Hola que tal grupo,

Deseo calcular cuantos meses hay entre dos fecha tengo creo que la subió Victor pero no me da 12 meses sino 11. ejemplo:


f1 = CTOD('01/01/2016')
f2 = CTOD('31/12/2016')
local objMeses as object
objMeses = ContarMeses(f1, f2)

?objMeses.mm   &&& resultado me da 11 meses pero si ya es 31 de diciembre deberia calcular los doce meses.

Saludes

Dsanchez

PD:  adjunto txt funcion que subió Victor.

ContarMeses.txt

Marcelo Barberis

unread,
Apr 20, 2017, 2:18:52 PM4/20/17
to publicesvfoxpro
hola amigo mira te paso unas funciones que uso para calcular cuantos meses existen entre dos fechas

*!* Diferencia entre dos fechas en años, meses y días: Calcula la cantidad de años, meses y días entre dos expresiones de tipo Date pasadas como parámetros.
*!* (esta función utiliza la UDF DiasDelMes()).
*!* Diferencia_AMD(DATE(2000,3,1), DATE())

FUNCTION Diferencia_AMD(tdIni, tdFin)
  LOCAL ldAux, lnAnio, lnMes, lnDia, lcRet
  *--- Fecha inicial siempre menor
  IF tdIni > tdFin
    ldAux = tdIni
    tdIni = tdFin
    tdFin = ldAux
  ENDIF
  lnAnio = YEAR(tdFin) - YEAR(tdIni)
  ldAux = GOMONTH(tdIni, 12 * lnAnio)
  *--- No cumplio el año aun
  IF ldAux > tdFin
    lnAnio = lnAnio - 1
  ENDIF
  lnMes = MONTH(tdFin) - MONTH(tdIni)
  IF lnMes < 0
    lnMes = lnMes + 12
  ENDIF
  lnDia = DAY(tdFin) - DAY(tdIni)
  IF lnDia < 0
    lnDia = lnDia + DiasDelMes(tdIni)
  ENDIF
  *--- Si el dia es mayor, no cumplio el mes
  IF (DAY(tdFin) < DAY(tdIni))
    IF lnMes = 0
      lnMes = 11
    ELSE
      lnMes = lnMes - 1
    ENDIF
  ENDIF
  lcRet = ALLTRIM(STR(lnAnio))+ " años, " + ;
    ALLTRIM(STR(lnMes))+ " meses y " + ;
    ALLTRIM(STR(lnDia))+ " días"
  RETURN lcRet
ENDFUNC 
*!* -----------------------------
*? DifMes(DATE(2004,3,31))

*--
* FUNCTION DifMes(tdIni, tdFin)
*--
* Calcula los meses completos:
* tdIni = Fecha Inicial
* tdFin = Fecha a la cual se calcula la diferencia.
* Por omisión toma la fecha actual.
* Fecha inicial siempre menor (tdini siempre menor)
*--
FUNCTION DifMes(tdIni, tdFin)
LOCAL lnAnio, lnMes
IF EMPTY(tdFin)
tdFin = DATE()
ENDIF
IF tdFin < tdIni
RETURN .NULL. && Fecha Inicial menor que Fecha Final
ENDIF
*-- Calculo los años
lnAnio = YEAR(tdFin) - YEAR(tdIni)
IF GOMONTH(tdIni, 12 * lnAnio) > tdFin
lnAnio = lnAnio - 1
ENDIF
*-- Calculo los meses
lnMes = MONTH(tdFin) - MONTH(tdIni)
IF lnMes < 0
lnMes = lnMes + 12
ENDIF
* Si el dia es mayor, no cumplio el mes
IF (DAY(tdFin) < DAY(tdIni))
IF lnMes = 0
lnMes = 11
ELSE
lnMes = lnMes - 1
ENDIF
ENDIF
RETURN lnMes + (lnAnio * 12)
ENDFUNC
*--
*? DiasDelMes(DATE(2004,2,1))
FUNCTION DiasDelMes(tdFecha)
  LOCAL ld
  ld = GOMONTH(tdFecha,1)
*  MESSAGEBOX(VARTYPE(ld))
  RETURN DAY(ld - DAY(ld))
ENDFUNC 

Espero te sirva y si te ayuda bien nomas


--
Marcelo Barberis Gutierrez
Sistemas Informaticos
Villa Montes - Bolivia
Telef.: +591-76830544

Dsanchez

unread,
Apr 20, 2017, 3:07:16 PM4/20/17
to publice...@googlegroups.com

Hola Marcelo gracias

Pero veo que tiene el mismo problema si tu haces esto con esa función, el resultado es 11 meses y no 12 meses.

ejemplo prueba esto:  

SET CONSOLE ON
f1 = CTOD('01/01/2016')
f2 = CTOD('31/12/2016')
?Diferencia_AMD(f1, f2)         11 meses y 30 dias,  ahorita estoy en el año 2017 y quiero ver información entre ese periodo que ya transcurrió.

Saludes

Douglas


Marcelo Barberis

unread,
Apr 20, 2017, 3:08:03 PM4/20/17
to publicesvfoxpro
ok dame chance y lo veo a ver como es

Luis Maria Guayan

unread,
Apr 20, 2017, 3:38:59 PM4/20/17
to publice...@googlegroups.com

Son Once Meses y 30 días, para que te de 12 meses tiene que ser el mismo día, o si por ejemplo si tu naciste el día 25, celebras tu cumpleaños el día 24?

;-)


Luis María Guayán
Tucumán, Argentina
_______________________________
Comunidad Visual FoxPro en Español
http://comunidadvfp.blogspot.com

Dsanchez

unread,
Apr 20, 2017, 3:41:48 PM4/20/17
to publice...@googlegroups.com
Asi es LMG,

Pero el punto es para algo especifico un informe, que requiere que se calcule en meses, al menos que tome los 30 dias y los convierta a mes, la funcion esta bien ya vi, tu tiene razon,
el punto es que el contador me dice que hay 12 meses y no 11 ya que estamos en 2017 y el requiere calcular los 12 meses, como lo convenso o mejor dicho adaptar la funcion a meses, por eso queria una idea.

Saludes y gracias.

Foxshin

unread,
Apr 20, 2017, 5:28:15 PM4/20/17
to Comunidad de Visual Foxpro en Español

Hello :D

Pienso que se podría agregar un parámetro adicional a la función que compartio Victor para que tome en cuenta la Fecha final como un dia mas, luego tendrías que multiplicar 12 por el número de años y le agregas el número de meses, claro, ésto último por fuera de la función.

Es decir, sería algo como ésto:

LOCAL loDifFecha AS Object;
   
,lnMeses AS Integer;
   
,ldFecha1 AS Date;
   
,ldFecha2 AS Date
m
.ldFecha1 = DATE(2016,01,01)    &&CTOD('01/01/2016')
m
.ldFecha2 = DATE(2016,12,31)    &&CTOD('31/12/2016')

m
.loDifFecha = ContarMeses(m.ldFecha1, m.ldFecha2, .T.)
m
.lnMeses = (12 * m.loDifFecha.AAAA) + m.loDifFecha.MM
? m.lnMeses

RELEASE m
.loDifFecha,m.lnMeses,m.ldFecha1,m.ldFecha2

Y la funcion de Víctor con la pequeña modificación que mencioné quedaría asi:

FUNCTION ContarMeses(tdFecIni, tdFecFin AS Date, tlIncluyeFecFin) AS Object
   
    LOCAL loDifFec AS
"Empty"
    LOCAL lcDiasMes
, lnAaaaDif, lnAaaaFecFin, lnAaaaFecIni;
           
, lnDdDif, lnDdFecFin, lnDdFecIni, lnMmDif
    LOCAL lnMmFecFin
, lnMmFecIni
    LOCAL tdFecTmp
   
    lnSigno
= 1
    IF m
.tdFecIni > m.tdFecFin
        tdFecTmp
= m.tdFecIni
        tdFecIni
= m.tdFecFin
        tdFecFin
= m.tdFecTmp
        lnSigno  
= -1
    ENDIF
   
* Ésta línea es la que se aumenta a la funcion original (Junto con el parámetro tlIncluyeFecFin *
    m
.tdFecFin = m.tdFecFin + IIF(VARTYPE(tlIncluyeFecFin)='L' AND tlIncluyeFecFin,1,0)
   
    lnAaaaFecIni
= YEAR(m.tdFecIni)
    lnMmFecIni    
= MONTH(m.tdFecIni)
    lnDdFecIni    
= DAY(m.tdFecIni)
   
    lnAaaaFecFin
= YEAR(m.tdFecFin)
    lnMmFecFin    
= MONTH(m.tdFecFin)
    lnDdFecFin    
= DAY(m.tdFecFin)
   
    lcDiasMes    
= "31 31 "                             ;
                 
+ IIF(DAY(GOMONTH(DATE(YEAR(m.tdFecFin), 1, 31), 1)) = 29, "29 ", "28 ") ;
                 
+ "31 30 31 30 31 31 30 31 30 31"
   
    lnMmFecFin    
= m.lnMmFecFin - IIF(m.lnDdFecFin < m.lnDdFecIni, 1, 0)
   
    lnDdDif        
= m.lnDdFecFin                         ;
               
+ IIF(m.lnDdFecFin < m.lnDdFecIni, VAL(GETWORDNUM(m.lcDiasMes, m.lnMmFecFin + 1)), 0) - m.lnDdFecIni
    lnMmDif        
= m.lnMmFecFin + IIF(m.lnMmFecFin < m.lnMmFecIni, 12, 0) - m.lnMmFecIni
    lnAaaaDif  
= m.lnAaaaFecFin - IIF(m.lnMmFecFin < m.lnMmFecIni, 1, 0) - m.lnAaaaFecIni
   
    loDifFec    
= CREATEOBJECT("Empty")
    ADDPROPERTY
(m.loDifFec, "Aaaa", m.lnAaaaDif * m.lnSigno)
    ADDPROPERTY
(m.loDifFec, "Mm", m.lnMmDif * m.lnSigno)
    ADDPROPERTY
(m.loDifFec, "Dd", m.lnDdDif * m.lnSigno)
   
    RETURN
(m.loDifFec)
ENDFUNC

No lo he probado, pero debería funcionar, en todo caso ya lo pruebas y nos cuentas.

Saludos

Bytes ^_^

Jose Antonio Blasco

unread,
Apr 21, 2017, 3:46:00 AM4/21/17
to Comunidad de Visual Foxpro en Español
Perdonar que intervenga, pero yo no modificaría la rutina pues sus calculos son correctos. 
Lo que haría es tener en cuenta la problemática de cada situación.  ¿No es posible solucionarlo añadiendo un día directamente a la fecha final ?.

Un saludo.


Jose A. Blasco
Zaragoza - España
Visual FoxPro 9 SP2

Luis Maria Guayan

unread,
Apr 21, 2017, 8:00:48 AM4/21/17
to publice...@googlegroups.com

Yo creo que ya que se modifica la función se debería tomar Fecha-Hora para si si completar el periodo desde la 00:00:00 horas del día inicial, hasta las 23:59:59 del día final

Luis María Guayán
Tucumán, Argentina
_______________________________
Comunidad Visual FoxPro en Español
http://comunidadvfp.blogspot.com

Fidel Charny

unread,
Apr 21, 2017, 9:45:02 AM4/21/17
to Comunidad de Visual Foxpro en Español
Y si no que use las manos:

(Ojo con lo' dedo' !)
Viernes!
Auto Generated Inline Image 1
Auto Generated Inline Image 2

Carlos Miguel FARIAS

unread,
Apr 21, 2017, 10:27:50 AM4/21/17
to Grupo Fox
Ideal para rascarse

Carlos Hidalgo

unread,
Apr 21, 2017, 2:57:39 PM4/21/17
to publice...@googlegroups.com
Me recuerda al de las horas de 70 minutos...
Feliz Viernes

Foxshin

unread,
Apr 21, 2017, 5:50:47 PM4/21/17
to Comunidad de Visual Foxpro en Español
Hello :D

Es cierto lo que dice José Antonio, también se puede añadir un día a la fecha final antes de enviarla a la funcion, asi no se tendría que modificar nada en la función, pero claro, eso ya dependería del caso específico, lo que hice fue hacerle una pequeña modificación de manera que si no se le envia el tercer parámetro, entonces la función calculará igual como fue diseñada inicialmente.

A veces cuando uno hace rangos, y por eso digo "a veces", se requiere que se considere también el número final, en este caso con las fechas.

Lo que indica el maestro Luis Maria también podría ser factible, añadirle a la función tambien la cuenta de las horas, minutos y segundos para que sea aún más preciso, pero esa ya es otra modificación que seguramente alguien por ahi tal vez ya tenga hecha y pueda compatir. :D

SET FRIDAY ON
Sí, lo de las horas de 70 minutos fue una pasada total, pero hay cada gustito...
SET FRIDAY OFF

Saludos

Bytes ^_^

Dsanchez

unread,
Apr 22, 2017, 11:26:56 AM4/22/17
to publice...@googlegroups.com
Hola eso haré, ya me dieron una idea eso queria, Voto por lo que dice LMG, si ya se pasa de la hora o si el dia siguiente ya transcurrio que retorne los doce meses.

Con lo que dice Fidel y Carlos, ya le puse un textbox al contador para que digite los doce meses manualmente, a la mierda la autormatización.

Saludes

DSanchez
Reply all
Reply to author
Forward
0 new messages