Jump to content
Fivewin Brasil

Função AddMonth (BUG?)


Manoel Marinho

Recommended Posts

Alguém poderia testar esse código com clipper/xharbour e informando a data 31/01 de qualquer ano ?

Nos meus testes a data resultante é sempre 15/02/1449 !!!

function main()

mdata=ctod(" / / ")

while .t.

cls

@ 0,0 say "Data:" get mdata

read

if empty(mdata)

exit

enddo

@ 2,0 say addmonth(mdata,10)

inkey(0)

enddo

return

/***

*

* Date.prg

*

* Sample user-defined functions for manipulating dates

*

* Copyright © 1993-1995, Computer Associates International Inc.

* All rights reserved.

*

* NOTE: compile with /a /m /n /w

*

*/

/***

*

* Mdy( ) --> cDate

*

* Convert a date to a string in the format "month dd, yyyy".

*

* Parameter:

* dDate - Date value to convert to a string

*

* Returns: The date value in "long," string form

*

*/

FUNCTION Mdy( dDate )

LOCAL cYear

// Handle SET CENTURY

IF SUBSTR( SET( _SET_DATEFORMAT ), -4 ) == "YYYY"

cYear := STR( YEAR( dDate ))

ELSE

cYear := " " + SUBSTR( STR( YEAR( dDate )), 4, 2 )

ENDIF

RETURN ( CMONTH( dDate ) + " " + LTRIM( STR( DAY( dDate ))) + "," + cYear )

/***

*

* Dmy( ) --> cDate

*

* Convert a date to string formatted as "dd month yyyy".

*

* Parameter:

* dDate - Date value to convert

*

* Returns: The date value in european date format

*

*/

FUNCTION Dmy( dDate )

LOCAL cYear

// Handle SET CENTURY

IF SUBSTR( SET( _SET_DATEFORMAT ), -4 ) == "YYYY"

cYear := STR( YEAR( dDate ))

ELSE

cYear := " " + SUBSTR( STR( YEAR( dDate )), 4, 2 )

ENDIF

RETURN ( LTRIM( STR( DAY( dDate ))) + " " + CMONTH( dDate ) + cYear )

/***

*

* DateAsAge( ) --> nAge

*

* Convert a date of birth to an age in years.

*

* Parameter:

* dDate - Birthdate for which to calculate the age

*

* Returns: The number of years elapsed since

*

*/

FUNCTION DateAsAge( dDate )

LOCAL nAge := 0

IF YEAR( DATE() ) > YEAR( dDate )

nAge := YEAR( DATE() ) - YEAR( dDate )

// Decrease the age by one if the date (month/day) has not yet

// occurred this year

IF ( MONTH( DATE() ) < MONTH( dDate ) .OR. ;

( MONTH( DATE() ) == MONTH( dDate ) .AND. ;

DAY( DATE() ) < DAY( dDate ) ;

))

--nAge

ENDIF

ENDIF

RETURN nAge

/***

*

* AddMonth( , ) --> dNewDate

*

* Calculate a new date by adding a number of months to a given

* date.

*

* Date validation must be done by calling program.

*

* Parameters:

* dDate - Date value to add to

* nMonths - Number of months to add to

*

* Returns: The date value representing +

*

*/

FUNCTION AddMonth( dDate, nMonths)

LOCAL nMonth

LOCAL nDay

LOCAL nYear

LOCAL nLimit

LOCAL nMonthAdd

LOCAL nYearAdd

LOCAL dNew

// Break date up into its numeric components

nMonth := MONTH( dDate )

nDay := DAY( dDate )

nYear := YEAR( dDate )

// nLimit determines the minimum number of months that will push the

// date into the next year. If the number of months added to the date

// exceeds this limit, the year must be advanced by one

nLimit := 12 - nMonth + 1

// Compute number of years to add

nYearAdd := INT( nMonths / 12 )

nMonths := nMonths % 12

IF nMonths >= nLimit

nYearAdd++

ENDIF

nYear += nYearAdd

// Compute number of months to add and normalize month

nMonthAdd := nMonths % 12

nMonth := ( nMonth + nMonthAdd ) % 12

IF nMonth = 0 // December special case

nMonth := 12

ENDIF

// Convert numeric portions to new date

dNew := NtoD( nMonth, nDay, nYear )

IF DTOC(dNew) = ' / / '

nMonth := (nMonth + 1) % 12

nDay := 1

nYear := nYear + INT((nMonth + 1) / 12)

dNew := NtoD(nMonth,nDay,nYear) - 1

ENDIF

RETURN ( dNew )

/***

*

* DateAsArray( dDate ) --> aDate

*

* Convert a date to an array of year, month, and day

*

* Parameter:

* dDate - Date value to convert into array form

*

* Returns: The date in the format { nYear, nMonth, nDay }

* If the parameter is invalid, an empty array ({}) is returned

*

*/

FUNCTION DateAsArray( dDate )

LOCAL aDate := {}

IF VALTYPE( dDate ) == "D"

aDate := { YEAR( dDate ), MONTH( dDate ), DAY( dDate ) }

ENDIF

RETURN aDate

/***

*

* ArrayAsDate( aDate ) --> dDate

*

* Convert an array of year, month, and day to a date value

*

* Parameter:

* aDate - Array holding a date in the form { nYear, nMonth, nDay }

*

* Returns: aDate in date value form

*

*/

FUNCTION ArrayAsDate( aDate )

RETURN NtoD( aDate[2], aDate[3], aDate[1] )

/***

*

* DateIsLeap( ) --> lLeap

*

* Determine if the year of a supplied date is a leap year

*

*/

FUNCTION DateIsleap( dDate )

LOCAL nYear := YEAR( dDate )

RETURN (( nYear % 4 ) == 0 ) .AND. ;

((( nYear % 100 ) != 0 ) .OR. ;

(( nYear % 400 ) == 0) )

/***

*

* NtoD( nMonth, nDay, nYear ) --> dNew

*

* Convert a date passed as separate numeric parameters to a date value

*

*/

FUNCTION NtoD( nMonth, nDay, nYear )

LOCAL cSavDateFormat := SET( _SET_DATEFORMAT, "MM/DD/YYYY" )

LOCAL dDate

dDate := CTOD( TRANSFORM( nMonth, "99/" ) + ;

TRANSFORM( nDay, "99/" ) + ;

TRANSFORM( nYear, "9999" ) )

SET( _SET_DATEFORMAT, cSavDateFormat )

RETURN ( dDate )

Link to comment
Share on other sites

Alguém poderia testar esse código com clipper/xharbour e informando a data 31/01 de qualquer ano ?

Nos meus testes a data resultante é sempre 15/02/1449 !!!

function main()

mdata=ctod(" / / ")

while .t.

cls

@ 0,0 say "Data:" get mdata

read

if empty(mdata)

exit

enddo

@ 2,0 say addmonth(mdata,10)

inkey(0)

enddo

return

/***

*

* Date.prg

*

* Sample user-defined functions for manipulating dates

*

* Copyright © 1993-1995, Computer Associates International Inc.

* All rights reserved.

*

* NOTE: compile with /a /m /n /w

*

*/

/***

*

* Mdy( ) --> cDate

*

* Convert a date to a string in the format "month dd, yyyy".

*

* Parameter:

* dDate - Date value to convert to a string

*

* Returns: The date value in "long," string form

*

*/

FUNCTION Mdy( dDate )

LOCAL cYear

// Handle SET CENTURY

IF SUBSTR( SET( _SET_DATEFORMAT ), -4 ) == "YYYY"

cYear := STR( YEAR( dDate ))

ELSE

cYear := " " + SUBSTR( STR( YEAR( dDate )), 4, 2 )

ENDIF

RETURN ( CMONTH( dDate ) + " " + LTRIM( STR( DAY( dDate ))) + "," + cYear )

/***

*

* Dmy( ) --> cDate

*

* Convert a date to string formatted as "dd month yyyy".

*

* Parameter:

* dDate - Date value to convert

*

* Returns: The date value in european date format

*

*/

FUNCTION Dmy( dDate )

LOCAL cYear

// Handle SET CENTURY

IF SUBSTR( SET( _SET_DATEFORMAT ), -4 ) == "YYYY"

cYear := STR( YEAR( dDate ))

ELSE

cYear := " " + SUBSTR( STR( YEAR( dDate )), 4, 2 )

ENDIF

RETURN ( LTRIM( STR( DAY( dDate ))) + " " + CMONTH( dDate ) + cYear )

/***

*

* DateAsAge( ) --> nAge

*

* Convert a date of birth to an age in years.

*

* Parameter:

* dDate - Birthdate for which to calculate the age

*

* Returns: The number of years elapsed since

*

*/

FUNCTION DateAsAge( dDate )

LOCAL nAge := 0

IF YEAR( DATE() ) > YEAR( dDate )

nAge := YEAR( DATE() ) - YEAR( dDate )

// Decrease the age by one if the date (month/day) has not yet

// occurred this year

IF ( MONTH( DATE() ) < MONTH( dDate ) .OR. ;

( MONTH( DATE() ) == MONTH( dDate ) .AND. ;

DAY( DATE() ) < DAY( dDate ) ;

))

--nAge

ENDIF

ENDIF

RETURN nAge

/***

*

* AddMonth( , ) --> dNewDate

*

* Calculate a new date by adding a number of months to a given

* date.

*

* Date validation must be done by calling program.

*

* Parameters:

* dDate - Date value to add to

* nMonths - Number of months to add to

*

* Returns: The date value representing +

*

*/

FUNCTION AddMonth( dDate, nMonths)

LOCAL nMonth

LOCAL nDay

LOCAL nYear

LOCAL nLimit

LOCAL nMonthAdd

LOCAL nYearAdd

LOCAL dNew

// Break date up into its numeric components

nMonth := MONTH( dDate )

nDay := DAY( dDate )

nYear := YEAR( dDate )

// nLimit determines the minimum number of months that will push the

// date into the next year. If the number of months added to the date

// exceeds this limit, the year must be advanced by one

nLimit := 12 - nMonth + 1

// Compute number of years to add

nYearAdd := INT( nMonths / 12 )

nMonths := nMonths % 12

IF nMonths >= nLimit

nYearAdd++

ENDIF

nYear += nYearAdd

// Compute number of months to add and normalize month

nMonthAdd := nMonths % 12

nMonth := ( nMonth + nMonthAdd ) % 12

IF nMonth = 0 // December special case

nMonth := 12

ENDIF

// Convert numeric portions to new date

dNew := NtoD( nMonth, nDay, nYear )

IF DTOC(dNew) = ' / / '

nMonth := (nMonth + 1) % 12

nDay := 1

nYear := nYear + INT((nMonth + 1) / 12)

dNew := NtoD(nMonth,nDay,nYear) - 1

ENDIF

RETURN ( dNew )

/***

*

* DateAsArray( dDate ) --> aDate

*

* Convert a date to an array of year, month, and day

*

* Parameter:

* dDate - Date value to convert into array form

*

* Returns: The date in the format { nYear, nMonth, nDay }

* If the parameter is invalid, an empty array ({}) is returned

*

*/

FUNCTION DateAsArray( dDate )

LOCAL aDate := {}

IF VALTYPE( dDate ) == "D"

aDate := { YEAR( dDate ), MONTH( dDate ), DAY( dDate ) }

ENDIF

RETURN aDate

/***

*

* ArrayAsDate( aDate ) --> dDate

*

* Convert an array of year, month, and day to a date value

*

* Parameter:

* aDate - Array holding a date in the form { nYear, nMonth, nDay }

*

* Returns: aDate in date value form

*

*/

FUNCTION ArrayAsDate( aDate )

RETURN NtoD( aDate[2], aDate[3], aDate[1] )

/***

*

* DateIsLeap( ) --> lLeap

*

* Determine if the year of a supplied date is a leap year

*

*/

FUNCTION DateIsleap( dDate )

LOCAL nYear := YEAR( dDate )

RETURN (( nYear % 4 ) == 0 ) .AND. ;

((( nYear % 100 ) != 0 ) .OR. ;

(( nYear % 400 ) == 0) )

/***

*

* NtoD( nMonth, nDay, nYear ) --> dNew

*

* Convert a date passed as separate numeric parameters to a date value

*

*/

FUNCTION NtoD( nMonth, nDay, nYear )

LOCAL cSavDateFormat := SET( _SET_DATEFORMAT, "MM/DD/YYYY" )

LOCAL dDate

dDate := CTOD( TRANSFORM( nMonth, "99/" ) + ;

TRANSFORM( nDay, "99/" ) + ;

TRANSFORM( nYear, "9999" ) )

SET( _SET_DATEFORMAT, cSavDateFormat )

RETURN ( dDate )

Link to comment
Share on other sites


#Include "FiveWin.Ch"

FUNCTION MAIN()

LOCAL oDlg, mData

SET DATE BRITISH

SET EPOCH TO 1950

SET CENTURY ON

mData := CTOD( " / / " )

DEFINE DIALOG oDlg;

TITLE "Testando a Data" PIXEL FROM 0, 0 TO 400, 400

oDlg:lHelpIcon := .F.

@ 1, 5 SAY "Data: " OF oDlg SIZE 12, 12

@ 1, 7 GET mData OF oDlg SIZE 50, 12 PICTURE "@D 99/99/9999"

//-> Parametros: AddMonth( dDate, nMonths, oDlg )

@ 3, 10 BUTTON "Ok" SIZE 30, 10 ACTION( AddMonth( mData, 10, oDlg ) )

@ 3, 20 BUTTON "Saida" SIZE 30, 10 ACTION( oDlg:End() ) CANCEL

ACTIVATE DIALOG oDlg CENTER

Release All

RETURN NIL

/***

*

* Date.prg

*

* Sample user-defined functions for manipulating dates

*

* Copyright © 1993-1995, Computer Associates International Inc.

* All rights reserved.

*

* NOTE: compile with /a /m /n /w

*

*/

/***

*

* Mdy( ) --> cDate

*

* Convert a date to a string in the format "month dd, yyyy".

*

* Parameter:

* dDate - Date value to convert to a string

*

* Returns: The date value in "long," string form

*

*/

FUNCTION Mdy( dDate )

LOCAL cYear

// Handle SET CENTURY

IF SUBSTR( SET( _SET_DATEFORMAT ), -4 ) == "YYYY"

cYear := STR( YEAR( dDate ))

ELSE

cYear := " " + SUBSTR( STR( YEAR( dDate )), 4, 2 )

ENDIF

RETURN ( CMONTH( dDate ) + " " + LTRIM( STR( DAY( dDate ))) + "," + cYear )

/***

*

* Dmy( ) --> cDate

*

* Convert a date to string formatted as "dd month yyyy".

*

* Parameter:

* dDate - Date value to convert

*

* Returns: The date value in european date format

*

*/

FUNCTION Dmy( dDate )

LOCAL cYear

// Handle SET CENTURY

IF SUBSTR( SET( _SET_DATEFORMAT ), -4 ) == "YYYY"

cYear := STR( YEAR( dDate ))

ELSE

cYear := " " + SUBSTR( STR( YEAR( dDate )), 4, 2 )

ENDIF

RETURN( LTRIM( STR( DAY( dDate ))) + " " + CMONTH( dDate ) + cYear )

/***

*

* DateAsAge( ) --> nAge

*

* Convert a date of birth to an age in years.

*

* Parameter:

* dDate - Birthdate for which to calculate the age

*

* Returns: The number of years elapsed since

*

*/

FUNCTION DateAsAge( dDate )

LOCAL nAge := 0

IF YEAR( DATE() ) > YEAR( dDate )

nAge := YEAR( DATE() ) - YEAR( dDate )

// Decrease the age by one if the date (month/day) has not yet

// occurred this year

IF ( MONTH( DATE() ) < MONTH( dDate ) .OR. ;

( MONTH( DATE() ) == MONTH( dDate ) .AND. ;

DAY( DATE() ) < DAY( dDate ) ;

))

--nAge

ENDIF

ENDIF

RETURN( nAge )

/***

*

* AddMonth( , ) --> dNewDate

*

* Calculate a new date by adding a number of months to a given

* date.

*

* Date validation must be done by calling program.

*

* Parameters:

* dDate - Date value to add to

* nMonths - Number of months to add to

*

* Returns: The date value representing +

*

*/

FUNCTION AddMonth( dDate, nMonths, oDlg )

LOCAL nMonth

LOCAL nDay

LOCAL nYear

LOCAL nLimit

LOCAL nMonthAdd

LOCAL nYearAdd

LOCAL dNew

// Break date up into its numeric components

nMonth := MONTH( dDate )

nDay := DAY( dDate )

nYear := YEAR( dDate )

// nLimit determines the minimum number of months that will push the

// date into the next year. If the number of months added to the date

// exceeds this limit, the year must be advanced by one

nLimit := 12 - nMonth + 1

// Compute number of years to add

nYearAdd := INT( nMonths / 12 )

nMonths := nMonths % 12

IF nMonths >= nLimit

nYearAdd++

ENDIF

nYear += nYearAdd

// Compute number of months to add and normalize month

nMonthAdd := nMonths % 12

nMonth := ( nMonth + nMonthAdd ) % 12

IF nMonth = 0 // December special case

nMonth := 12

ENDIF

// Convert numeric portions to new date

dNew := NtoD( nMonth, nDay, nYear )

IF DTOC(dNew) = ' / / '

nMonth := (nMonth + 1) % 12

nDay := 1

nYear := nYear + INT((nMonth + 1) / 12)

dNew := NtoD(nMonth,nDay,nYear) - 1

ENDIF

? [data], dDate

RETURN ( dNew )

/***

*

* DateAsArray( dDate ) --> aDate

*

* Convert a date to an array of year, month, and day

*

* Parameter:

* dDate - Date value to convert into array form

*

* Returns: The date in the format { nYear, nMonth, nDay }

* If the parameter is invalid, an empty array ({}) is returned

*

*/

FUNCTION DateAsArray( dDate )

LOCAL aDate := {}

IF VALTYPE( dDate ) == "D"

aDate := { YEAR( dDate ), MONTH( dDate ), DAY( dDate ) }

ENDIF

RETURN aDate

/***

*

* ArrayAsDate( aDate ) --> dDate

*

* Convert an array of year, month, and day to a date value

*

* Parameter:

* aDate - Array holding a date in the form { nYear, nMonth, nDay }

*

* Returns: aDate in date value form

*

*/

FUNCTION ArrayAsDate( aDate )

//

RETURN NtoD( aDate[2], aDate[3], aDate[1] )

/***

*

* DateIsLeap( ) --> lLeap

*

* Determine if the year of a supplied date is a leap year

*

*/

FUNCTION DateIsleap( dDate )

LOCAL nYear := YEAR( dDate )

RETURN (( nYear % 4 ) == 0 ) .AND. ;

((( nYear % 100 ) != 0 ) .OR. ;

(( nYear % 400 ) == 0) )

/***

*

* NtoD( nMonth, nDay, nYear ) --> dNew

*

* Convert a date passed as separate numeric parameters to a date value

*

*/

FUNCTION NtoD( nMonth, nDay, nYear )

LOCAL cSavDateFormat := SET( _SET_DATEFORMAT, "MM/DD/YYYY" )

LOCAL dDate

dDate := CTOD( TRANSFORM( nMonth, "99/" ) + ;

TRANSFORM( nDay, "99/" ) + ;

TRANSFORM( nYear, "9999" ) )

SET( _SET_DATEFORMAT, cSavDateFormat )

RETURN( dDate )

id=code>id=code>

//-> fin

João Santos - São Paulo.

kmt_karinha@pop.com.br

kapiaba@brfree.com.br

Skype: fw_kapiaba

FWH 2.7 - xHARBOUR 0.99.61 - WorkShop.Exe

Link to comment
Share on other sites

Teste esta:


////////////////////////////////////////////////////////////////////////////////

//

////////////////////////////////////////////////////////////////////////////////

function SomaMes( dData, nMeses, oDlg )

local dNovaData

local nMeses1, nDia, nAno

nMeses1:=month( dData )+nMeses

nDia:=day( dData )

nAno:=year( dData )

if nMeses<0

do while nMeses1<1

nMeses1+=12

nAno--

enddo

else

do while nMeses1>12

nMeses1-=12

nAno++

enddo

endif

dNovaData:=ctod(str(nDia,2)+'/'+str(nMeses1,2)+'/'+str(nAno,4))

do while empty(dNovaData) .or. day(dNovaData)=0

nDia--

dNovaData:=ctod( str(nDia,2)+'/'+str(nMeses1,2)+'/'+str(nAno,4) )

enddo

? [Nova data:], dNovaData

return ( dNovaData )

id=code>id=code>

toya

(Ahora en la version 5.8)

toyasis@yahoo.com.br

http://www.toyanet.com.br

FWH 2.6+PellesC+xHarbour.org 0.99 - MySql 5.0.12 Beta - SqlLib - Rpv

FW 2.4+WS 4.5+Blinker 7.0+Clipper 5.2E+Rpv

Linux 2.4.29 - Slack 10.1 - (No@Say)

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