>The application has to determine how many occurrences of a given day of the week occurred in a given calendar month.
>
>For example- How many Mondays (or any other specified day of the week) were there in February, 2016?
>I can see how to get the answer by looping through all the days in the month in question, but is there a slicker way?
Something I slapped together... There is likely an easier way than I've got here (e.g. something like how Zeller's Congruence can be used to compute day of week).
main point of interest is function DowCnt1().
LOCAL bPass
bPass = .T.
DO Test0 WITH m.bPass
IF m.bPass THEN
DO Test1 WITH m.bPass
ENDIF
IF m.bPass THEN
DO Test2 WITH m.bPass
ENDIF
RETURN
PROCEDURE Test0( bPass )
LOCAL nDOW,nYr,nMo, bOK, nFail, ;
dRef,dF0
nFail = 0
FOR nDOW = 1 TO 7
FOR nYr = 1900 TO 2100
FOR nMo = 1 TO 12
bOK = .T.
dRef = DATE(m.nYr,m.nMo,1)
dF0 = BF_BegDowMonth(m.nYr,m.nMo,m.nDOW)
bFail = .F.
IF MONTH(m.dF0)<>MONTH(m.dRef) OR YEAR(m.dF0)<>YEAR(m.dRef) THEN
bFail = .T.
ELSE
IF DOW(m.dF0)<>m.nDOW THEN
bFail = .T.
ELSE
IF (m.dF0 - m.dRef) >= 7 THEN
bFail = .T.
ENDIF
ENDIF
ENDIF
IF m.bFail THEN
nFail = m.nFail + 1
? m.nDOW, m.nYr, m.nMo
ENDIF
ENDFOR
ENDFOR
ENDFOR
? "Test 0:", IIF(m.nFail==0,"PASS","FAIL")
ENDPROC
PROCEDURE Test1( bPass )
LOCAL nDOW,nYr,nMo, bOK, nFail, ;
dRef,dF0
nFail = 0
FOR nDOW = 1 TO 7
FOR nYr = 1900 TO 2100
FOR nMo = 1 TO 12
bOK = .T.
dRef = DATE(m.nYr,m.nMo,1)
dF0 = BegDowMonth(m.nYr,m.nMo,m.nDOW)
bFail = .F.
IF MONTH(m.dF0)<>MONTH(m.dRef) OR YEAR(m.dF0)<>YEAR(m.dRef) THEN
bFail = .T.
ELSE
IF DOW(m.dF0)<>m.nDOW THEN
bFail = .T.
ELSE
IF (m.dF0 - m.dRef) >= 7 THEN
bFail = .T.
ENDIF
ENDIF
ENDIF
IF m.bFail THEN
nFail = m.nFail + 1
? m.nDOW, m.nYr, m.nMo
ENDIF
ENDFOR
ENDFOR
ENDFOR
? "Test 1:", IIF(m.nFail==0,"PASS","FAIL")
ENDPROC
PROCEDURE Test2( bPass )
LOCAL nDOW,nYr,nMo, bOK, nFail, ;
dRef,dF0
nFail = 0
FOR nDOW = 1 TO 7
FOR nYr = 1900 TO 2100
FOR nMo = 1 TO 12
bOK = .T.
nC0 = BF_DowCnt(m.nYr,m.nMo,m.nDOW)
nC1 = DowCnt1(m.nYr,m.nMo,m.nDOW)
bFail = .F.
IF m.nC0 <> m.nC1 THEN
bFail = .T.
ENDIF
IF m.bFail THEN
nFail = m.nFail + 1
? m.nDOW, m.nYr, m.nMo, nC0,m.nC1
ENDIF
ENDFOR
ENDFOR
ENDFOR
? "Test 2:", IIF(m.nFail==0,"PASS","FAIL")
ENDPROC
FUNCTION BF_BegDowMonth(nYr,nMo,nDOW)
LOCAL dDt,dRet,I
dRet = {}
dDt = DATE(m.nYr,m.nMo,1)
FOR I=1 TO 8
IF DOW(m.dDt)==m.nDOW THEN
dRet = m.dDt
EXIT
ENDIF
dDt = m.dDt + 1
ENDFOR
RETURN m.dRet
ENDFUNC
FUNCTION BF_DowCnt(nYr,nMo,nDOW)
LOCAL dDt,nCnt
nCnt = 0
dDt = DATE(m.nYr,m.nMo,1)
DO WHILE MONTH(m.dDt)==m.nMo AND YEAR(m.dDt)==m.nYr
IF DOW(m.dDt)==m.nDOW THEN
nCnt = m.nCnt + 1
ENDIF
dDt = m.dDt + 1
ENDDO
RETURN m.nCnt
ENDFUNC
FUNCTION DowCnt1(nYr,nMo,nDOW)
LOCAL d0,d1, dN
d0 = BegDoWMonth(m.nYr,m.nMo,m.nDOW)
dN = GOMONTH(DATE(m.nYr,m.nMo,1),1)
d1 = BegDoWMonth(YEAR(m.dN),MONTH(m.dN),m.nDOW)
RETURN INT( ( m.d1 - m.d0 ) / 7)
ENDFUNC
FUNCTION BegDowMonth(nYr,nMo,nDOW)
LOCAL dDt,dRet
dDt = DATE(m.nYr,m.nMo,1)
dRet = m.dDt - DOW(m.dDt) + m.nDOW
IF MONTH(m.dRet) <> m.nMo THEN
dRet = m.dRet + 7
ENDIF
RETURN m.dRet
ENDFUNC