/* A couple of reusable calendar functions */
FUNCTION LastDayOfMonth RETURNS DATE
(idtDate AS DATE):
DEF VAR iDaysInMonth AS INTEGER NO-UNDO EXTENT 12 INITIAL
[31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31].
DEF VAR dtLastDayOfMonth AS DATE NO-UNDO. /* returned */
/* Mostly, this will do it */
ASSIGN
dtLastDayofMonth = DATE (MONTH(idtDate),
iDaysInMonth[MONTH(idtDate)],
YEAR(idtDate)
) NO-ERROR.
IF ERROR-STATUS:NUM-MESSAGES > 0 THEN /* Tried to assign Feb 29 in non leap year */
dtLastDayofMonth = DATE (2, 28, YEAR(idtDate)).
RETURN dtLastDayOfMonth.
END FUNCTION.
FUNCTION AddMonths RETURNS DATE
(idtDate AS DATE, iMonths AS INTEGER):
DEF VAR dtNewDate AS DATE NO-UNDO. /* Returned */
DEF VAR iTotalMonths AS INTEGER NO-UNDO.
DEF VAR iYY AS INTEGER NO-UNDO.
DEF VAR iMM AS INTEGER NO-UNDO.
DEF VAR iDD AS INTEGER NO-UNDO.
/* All we are doing is adding in base 12 */
iTotalMonths = YEAR(idtDate) * 12 + MONTH(idtDate) + iMonths
.
/* Work out the new Year, Month, Day */
ASSIGN
iYY = TRUNCATE (iTotalMonths / 12, 0) /* Year = TotalMonths DIV 12 */
iMM = iTotalMonths MOD 12 /* Months = remainder */
iDD = DAY(idtDate)
.
/* Modulus gives 0 ... 11, we want 1 ... 12 */
IF iMM = 0 THEN
ASSIGN
iYY = iYY - 1
iMM = 12
.
/* Try the date - if it doesn't work, day in old month > # of days in new month */
ASSIGN dtNewDate = DATE(iMM, iDD, iYY) NO-ERROR.
IF ERROR-STATUS:NUM-MESSAGES > 0 THEN /* round to last day of month */
dtNewDate = LastDayOfMonth(DATE(iMM, 1, iYY)).
RETURN dtNewDate.
END FUNCTION.
/* Now your particular requirements */
DEF VAR dtTest AS DATE NO-UNDO INITIAL 2/6/07 .
DEF VAR dtFirstOfNewMonth AS DATE NO-UNDO.
dtFirstOfNewMonth = addMonths(DATE(MONTH(dtTest), 1, YEAR(dtTest)),
-2).
MESSAGE dtFirstOfNewMonth SKIP LastDayOfMonth(dtFirstOfNewMonth)
VIEW-AS ALERT-BOX INFO BUTTONS OK.