Page 1 of 2
¿ Como sumar fechas para obtener resultado exacto?
Posted: Fri Jan 22, 2010 11:33 pm
by Loren
compañeros:
Tengo una fecha de partida (dFechaActual) y un get donde el usuario teclea un nº de meses. (Nmeses)
Con estos 2 datos tengo que sumar y obtener la fecha final. Esto es facil pero no exacto:
dFechaFinal=(Nmesesx30 )+dFechaActual ---> como NO todos los meses tienen 30 días, el resultado final es aprox. pero no exacto.
¿ Como se calcularía el exacto ?
Mil gracias.
LORENZO
Re: ¿ Como sumar fechas para obtener resultado exacto?
Posted: Sat Jan 23, 2010 5:29 am
by Manuel Valdenebro
Utilizo para eso dos funciones:
1) Una adaptación de la antigua Nanforum (da problemas en Febrero)
2) Una función propia que intenta solucionar el tema de Febrero.
Te icluyo las dos para que la adaptes a tus necesidades:
/*
* File......: MADD.PRG
* Author....: Jo W. French dba Practical Computing
* Nanforum Toolkit
* Añade meses a una fecha
* dFecha la fecha inicial
* nMeses numero de meses
*/
FUNCTION ADI_MES( dFecha, nMeses )
LOCAL nAdjDay, dTemp, i
// si dFecha no es tipo fecha
IF(VALTYPE(dFecha) != 'D', dFecha := DATE(), )
// si nMeses no es tipo numérico
IF(VALTYPE(nMeses) != 'N', nMeses := 0, )
nAdjDay := DAY( dFecha ) - 1 // dia del mes menos uno
dTemp := dFecha - nAdjDay // primero de mes
/* Work with 1st of months.*/
FOR i := 1 TO ABS(nMeses)
dTemp += IF( nMeses > 0, 31, -1 )
dTemp += 1 - DAY( dTemp )
NEXT
dTemp := MIN( (dTemp + nAdjday), (dTemp += 31 - DAY( dTemp + 31 )))
RETURN dTemp
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//////////////////////////////////////////////////
/// M.Valdenebro 2006
/// Añade meses a una fecha
/// lSuma suma / .f. resta el mes
/////////////////////////////////////////////////
FUNCTION ADI_CSB ( dFecha, nMeses, nFinMes, nFinFeb, lSuma )
LOCAL nAdjDay, dTemp, i
DEFAULT lSuma := .t.
// si dFecha no es tipo fecha
IF(VALTYPE(dFecha) != 'D', dFecha := DATE(), )
// si nMeses no es tipo numérico
IF(VALTYPE(nFinMes) != 'N', nFinMes := 0, )
nAdjDay := DAY( dFecha ) - 1 // numero de dias menos UNO
dTemp := dFecha - nAdjDay // primero de mes
FOR i := 1 TO ABS(nMeses)
IF lSuma
dTemp += 31 // se va a una fecha del mes siguiente
dTemp += 1 - DAY( dTemp )
ELSE
dTemp -= 31 // se va a una fecha del mes siguiente
dTemp -= 1 - DAY( dTemp )
ENDI
NEXT
dTemp := MIN( (dTemp + nAdjday), (dTemp += 31 - DAY( dTemp + 31 )))
IF MONTH ( dFecha ) = 2 // si es febrero
IF DAY ( dFecha ) > 27 // si el dia es superior al dia 27
IF MONTH (dTemp) = 2 // si el nuevo mes es febrero
dTemp := EOM( dTemp)
ELSE // si el nuevo mes no es febrero
IF nFinFeb = 0 // Si era dia 31 en un mes 31
dTemp := EOM( dTemp)
ELSE
dTemp := EOM( dTemp) - nFinFeb
ENDI
ENDI
ENDI
ELSE
// meses de 31 dias
IF MONTH (dFecha) = 3 .or. MONTH (dFecha) = 5 .or. ;
MONTH (dFecha) = 7 .or. MONTH (dFecha) = 8 .or. ;
MONTH (dFecha) = 10 .or. MONTH (dFecha) = 12
IF DAY ( dFecha ) = 31
dTemp := EOM( dTemp)
ENDI
// meses de 30 dias
ELSEIF MONTH ( dFecha ) <> 1 // no es Enero
IF DAY ( dFecha ) = 30
IF nFinMes = 0 // Si era dia 31 en un mes 31
dTemp := EOM( dTemp)
ENDI
ENDI
ENDI
ENDI
RETURN dTemp
Re: ¿ Como sumar fechas para obtener resultado exacto?
Posted: Sat Jan 23, 2010 10:03 am
by Loren
Mil gracias...
lo adaptaré a mis necesiddades.
Un saludo.
Re: ¿ Como sumar fechas para obtener resultado exacto?
Posted: Sun Jan 24, 2010 9:11 am
by dobfivewin
Hola estimado
Otra funcion para que veas, No es exatamente lo que necesitas pero puede ayudar
Saludos
Code: Select all
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* F U N C I O N: Tiempo(<fFechaIni> [, <fFechaFin>] [, <nRegresa>] [, cSeparador]) -> cTiempo
* DESCRIPCION : Investiga los Años, Meses y Días transcurridos desde la fecha <fFechaIni> y la fecha <fFechaFin>
* PARAMETROS : <fFechaIni> -> Primera fecha a tratar.
* <fFechaFin> -> Segunda Fecha a tratar. Si se omite este parámetro, se tomará la fecha actual con DATE().
* <nRegresa> -> Indica que tipo de dato se está solicitando:
* 1 = Años
* 2 = Años y Meses
* 3 = Años, Meses y Días
* <cSeparador> -> Caracter a utilizar como separador entre los Años, Meses y Días. Por default será: '.'
* R E G R E S A: <cTiempo> -> Cadena de caracteres con los Años, Meses y Días transcurridos
* desde la fecha <fFechaIni> hasta la fecha <fFechaFin>
* E J E M P L O: ? Tiempo( CTOD('17/07/1971'), CTOD('06/07/2001'), 1) ) -> '29' // Años
* ? Tiempo( CTOD('23/03/1972'), CTOD('06/07/2001'), 2) ) -> '29.3' // Años.Meses
* ? Tiempo( CTOD('03/04/1960'), CTOD('06/07/2001'), 3) ) -> '41.3.3' // Años.Meses.Días
*
FUNCTION Tiempo(fFechaIni, fFechaFin, nRegresa, cSeparador)
LOCAL cAnos, cMese, cDias, cTiempo
LOCAL nAnos, nMese, nDias, nDiaUltimo, fAux , aa,mm
DEFAULT fFechaFin := DATE()
DEFAULT nRegresa := 1
DEFAULT cSeparador:= '.'
If EMPTY(fFechaIni)
RETURN('')
EndIf
nDias := fFechaFin - fFechaIni
// AÑOS...
nAnos := INT(nDias / 365)
// MESES...
fAux := CTOD( STR(DAY(fFechaIni)) + '/' + STR(MONTH(fFechaIni)) + '/' + STR(YEAR(fFechaFin) - 1,4))
nMese := INT((fFechaFin - fAux) / 30.42)
nMese := IF(nMese >= 12, nMese - 12, nMese)
// DIAS...
mm := If(MONTH(fFechaFin) - 1 < 1 , 12 , MONTH(fFechaFin) - 1 )
aa := If(MONTH(fFechaFin) - 1 < 1 , YEAR(fFechaFin)-1 , YEAR(fFechaFin) )
fAux := CTOD( STR(DAY(fFechaIni)) + '/' + ; // Dia de Fecha DESDE
STRzero(mm,2) + '/' + ; // Mes de Fecha HASTA - 1
STR(aa, 4)) // Año de Fecha HASTA
* fAux := CTOD( STR(DAY(fFechaIni)) + '/' + ; // Dia de Fecha DESDE
* STR(MONTH(fFechaFin) - 1) + '/' + ; // Mes de Fecha HASTA - 1
* STR(YEAR(fFechaFin), 4)) // Año de Fecha HASTA
nDias := fFechaFin - fAux // Fecha HASTA -
nDiaUltimo := DAY( DiaUltimo(fAux) )
nDias := IF(nDias >= nDiaUltimo, nDias - nDiaUltimo, nDias)
cAnos := if( nAnos>0 , alltrim( STR(nAnos) )+ ' años' , '')
cMese := if( nMese>0 , alltrim( STR(nMese) )+ ' mes'+if(nMese>1,'es','') , '')
cDias := if( nDias>0 , alltrim( STR(nDias) )+ ' dia'+if(nDias>1,'s','') , '')
DO CASE
CASE nRegresa = 1
cTiempo := _ nRegresa = 2
cTiempo := cAnos + If(nAnos>0,cSeparador,'') + cMese
CASE nRegresa = 3
cTiempo := cAnos + If(nAnos>0,cSeparador,'') +;
cMese + If(nMese>0,cSeparador,'') + cDias
ENDCASE
RETURN(cTiempo)
*
* FIN Tiempo()
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* FUNCION : DiaUltimo( <fFecha> ) -> fFecha.
* DESCRIPCION: Sirve para averiguar el dia ultimo del mes de una fecha cualquiera.
* PARAMETROS : <fFecha>. Es la fecha que se va a tratar. Por defecto, es la fecha
* del sistema.
* REGRESA : <fFecha>. Es la fecha que corresponde al dia ultimo del mes de la
* fecha mandada como parámetro.
*
FUNCTION DiaUltimo(fFecha)
LOCAL fFechaAux // Fecha con el día primero del mes mandado en fFecha.
LOCAL nMes, nAno
If VALTYPE(fFecha) <> 'D'
fFecha := DATE()
EndIf
// Se calcula el día primero del mes siguiente de la fecha pasada.
nMes := IF(MONTH(fFecha) = 12, 1, MONTH(fFecha) + 1)
nAno := YEAR(fFecha) + IF(nMes = 1, 1, 0)
fFechaAux := CTOD('01/' + alltrim( STR(nMes) ) + '/' +;
alltrim( STR(nAno) ))
RETURN fFechaAux-1 // Al dia primero del mes siguiente se le resta un dia.
*
* FIN DiaUltimo()
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Re: ¿ Como sumar fechas para obtener resultado exacto?
Posted: Mon Jan 25, 2010 11:27 pm
by jcenteno
Loren,
Esto debe ser lo que buscas:
AddMonth( <dDate>, <nMonths> ) --> dNewDate
Arguments:
<dDate>
A Date value, except for an empty date, can be passed.
<nMonths>
An integer numeric value specifying the number of months to add to <dDate>. If <nMonths> is a negative value, it is subtracted from <dDate>. Return
The function returns the modified date, or an empty date on error.
Saludos,
Jairo
Re: ¿ Como sumar fechas para obtener resultado exacto?
Posted: Tue Jan 26, 2010 5:23 am
by Manuel Valdenebro
jcenteno wrote:Loren,
Esto debe ser lo que buscas:
AddMonth( <dDate>, <nMonths> ) --> dNewDate
Esto no funciona siempre. Si tu tienes un cliente al que le adeudas un recibo los dias 30 de cada mes, cuando llegue el mes de Febrero lo adeudará el dia 28 de Febrero y a partir de esta fecha, siempre lo adeudara los dias 28 de cada mes, no los dias 30. Igual ocurre si el contrato comienza el dia 31 de Enero (vencimiento dia ultimo de cada mes), cuando pase Febrero, ya cambiara y los siguientes vencimientos los pondrá el dia 28 ó 29, dependiendo si Febrero es bisiesto.
Re: ¿ Como sumar fechas para obtener resultado exacto?
Posted: Sat Nov 19, 2016 2:40 pm
by jesusdelamora
FALTO
SET DATE BRIT
Re: ¿ Como sumar fechas para obtener resultado exacto?
Posted: Sat Nov 19, 2016 2:41 pm
by jesusdelamora
FALTO
SET DATE BRIT
Re: ¿ Como sumar fechas para obtener resultado exacto?
Posted: Mon Nov 21, 2016 12:17 am
by FranciscoA
Hola, dale un vistazo. Puede ser que ahi encuentres lo que necesitas.
http://fivetechsupport.com/forums/viewt ... 8bb#p86705
Saludos.
Re: ¿ Como sumar fechas para obtener resultado exacto?
Posted: Mon Nov 21, 2016 1:33 am
by Armando
Amigos:
Hasta donde entiendo lo que Loren expone debiera ser algo parecido a esto
Fecha Inicial: 30/01/2016
Mese a aumentar: 2
Entonces
30/01/2016 + 29 días del mes de febrero + 31 días del mes de marzo
la nueva fecha sería 29/03/2016
Lorenzo, entendí bien lo que necesitas?
Saludos
Re: ¿ Como sumar fechas para obtener resultado exacto?
Posted: Mon Nov 21, 2016 2:13 am
by Armando
Lorenzo:
Si mi apreciación es correcta esta función puede serte de ayuda.
Code: Select all
STATIC FUNCTION CalFec()
LOCAL dFecIni := CTOD("28/12/2016")
LOCAL dFecFin := dFecIni
LOCAL nMeses := 2
LOCAL nVez := 0
LOCAL nAmo := 0
LOCAL nDias := 0
nMes := MONTH(dFecIni)
nAmo := YEAR(dFecIni)
FOR nVez := 1 TO nMeses
nMes++
IF nMes > 12
nAmo++
nMes := 1
ENDIF
nDias += DAYSINMONTH(MONTH(CTOD("01/" + STRZERO(nMes,2,0) + "/" + STRZERO(nAmo,4,0))))
NEXT
dFecFin := dFecIni + nDias
MsgInfo(nDias)
MsgInfo(dFecFin)
RETURN(NIL)
La hice al vuelo y en obvio de tiempo utilizo constantes para no hacer un dialogo.
Saludos
Re: ¿ Como sumar fechas para obtener resultado exacto?
Posted: Mon Nov 21, 2016 1:32 pm
by horacio
Armando, la rutina funciona siempre y cuando no calculemos años bisiestos ya que la función DAYSINMONTH no lo tiene en cuenta. Saludos
Re: ¿ Como sumar fechas para obtener resultado exacto?
Posted: Mon Nov 21, 2016 5:48 pm
by Armando
Horacio, Lorenzo y amigos del foro:
Tienes la boca llena de razón, pero el bien siempre debe triunfar sobre el mal,
basta con agregar unas líneas para determinar si el mes a agregar es Febrero
de un año bisiesto.
La rutina quedaría así, probadla y viertan sus resultados.
Code: Select all
STATIC FUNCTION CalFec()
LOCAL dFecIni := CTOD("15/01/2016")
LOCAL dFecFin := dFecIni
LOCAL nMeses := 1
LOCAL nVez := 0
LOCAL nAmo := 0
LOCAL nDias := 0
nMes := MONTH(dFecIni)
nAmo := YEAR(dFecIni)
FOR nVez := 1 TO nMeses
nMes++
IF nMes > 12
nAmo++
nMes := 1
ENDIF
nDias += DAYSINMONTH(MONTH(CTOD("01/" + STRZERO(nMes,2,0) + "/" + STRZERO(nAmo,4,0))))
// Determinamos si el mes es FEBRERO de un año BISIESTO, Incrementamos los días
IF nMes == 2
IF MOD(nAmo,400) == 0
nDias++
ELSE
IF MOD(nAmo,4) == 0
IF MOD(nAmo,100) > 0
nDias++
ENDIF
ENDIF
ENDIF
ENDIF
NEXT
dFecFin := dFecIni + nDias
MsgInfo(nDias)
MsgInfo(dFecFin)
RETURN(NIL)
Seguramente el código se puede simplificar, sobre todo en los IFs, pero por
claridad y fácil entendimiento los escribí así.
Saludos
Re: ¿ Como sumar fechas para obtener resultado exacto?
Posted: Mon Nov 21, 2016 9:30 pm
by Armando
Amigos del foro:
Ya entrado en gastos
, aquí dejo esta pequeña función
para determinar si el año es bisiesto.
Lorenzo, Horacio, con esta función podemos sustituir los IFs, del ejemplo
incluido en mi post anterior.
Code: Select all
/*
IsLeap : Función para determinar si el año es bisiesto (.T.)
o no (.F.)
Recibe : El año a determinar
Parámetros : nAmo = El año a determinar si es bisiesto o no
Devuelve : (.T.) en caso se ser bisiesto o (.F.) en caso contrario
Fecha : 11/Jul/2004
Autor : Armando Estrada Bucio
Compañia : SOI, s.a. de c.v.
Copyright : El código es libre solo pido no remover estas líneas
*/
FUNCTION IsLeap(nAmo)
RETURN( ((nAmo % 4) == 0 .AND.;
(nAmo % 100) <> 0) .OR.;
((nAmo % 400) == 0) )
Espero les sea de utilidad.
Saludos
Re: ¿ Como sumar fechas para obtener resultado exacto?
Posted: Tue Nov 22, 2016 1:19 pm
by horacio
Muchas gracias Armando, funciona perfectamente. El bien a triunfado sobre el mal una vez mas ...
Saludos