Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Number of Mondays in a month
Message
From
19/10/2016 23:45:34
 
 
To
19/10/2016 20:31:42
General information
Forum:
Visual FoxPro
Category:
Coding, syntax & commands
Miscellaneous
Thread ID:
01642129
Message ID:
01642130
Views:
114
>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.

                * Test "brute-force" fisrt day month with given DOW
                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  && Test0

*-------------------------------------------------------------------------------

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.

                * Test "brute-force" fisrt day month with given DOW
                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  && Test1

*-------------------------------------------------------------------------------

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  && Test2

*-------------------------------------------------------------------------------

FUNCTION BF_BegDowMonth(nYr,nMo,nDOW)
    * A "brute-forcce" method of getting first day of a month that has a gven
    * day of week.
    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  && BF_BegDowMonth

*-------------------------------------------------------------------------------

FUNCTION BF_DowCnt(nYr,nMo,nDOW)
    * "Brute-force" method of counting days in a month that match a given
    * day of week.
    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  && BF_DowCnt

*-------------------------------------------------------------------------------

FUNCTION DowCnt1(nYr,nMo,nDOW)
    * A slightly more involved method (which should be a tad faster than the
    * "brute force" method of counting days in a month that match a given
    * day of week.
    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  && DowCnt1

*-------------------------------------------------------------------------------

FUNCTION BegDowMonth(nYr,nMo,nDOW)
    * A slightly more involved method of getting the first day of a month that
    * has a gven day of week.
    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  && BegDowMonth
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform