Last Friday of each month: Difference between revisions

Content added Content deleted
m (→‎{{header|REXX}}: changed/added comments and whitespace, changed indentations, moved documentation for the lastDOW function to a separate window.)
Line 2,007: Line 2,007:
This REXX program will find the last day-of-week (for any day) of all the months for any year.
This REXX program will find the last day-of-week (for any day) of all the months for any year.
<br>It wasn't optimized just to find a particular day-of-week.
<br>It wasn't optimized just to find a particular day-of-week.

<lang rexx>/*REXX program displays dates of last Fridays of each month for any year*/
The documentation for the '''lastDOW''' function &nbsp; (used in the REXX program below):
<pre>
╔════════════════════════════════════════════════════════════════════╗
lastDOW: procedure to return the date of the last day─of─week of
║ any particular month of any particular year. ║
The day─of─week must be specified (it can be in any case,
(lower─/mixed─/upper─case) as an English name of the spelled day
of the week, with a minimum length that causes no ambiguity.
I.E.: W for Wednesday, Sa for Saturday, Su for Sunday ...
The month can be specified as an integer 1 ──► 12
1=January 2=February 3=March ... 12=December
or the English name of the month, with a minimum length that
causes no ambiguity. I.E.: Jun for June, D for December.
If omitted [or an asterisk(*)], the current month is used.
The year is specified as an integer or just the last two digits
(two digit years are assumed to be in the current century, and
there is no windowing for a two─digit year).
If omitted [or an asterisk(*)], the current year is used.
Years < 100 must be specified with (at least 2) leading zeroes.
Method used: find the "day number" of the 1st of the next month
then subtract one (this gives the "day number" of the last day of
the month, bypassing the leapday mess). The last day─of─week is
then obtained straightforwardly, or via subtraction.
╚════════════════════════════════════════════════════════════════════╝
</pre>
<lang rexx>/*REXX program displays the dates of the last Fridays of each month for any given year.*/
parse arg yyyy
parse arg yyyy
do j=1 for 12
do j=1 for 12
say lastDOW('Friday',j,yyyy)
say lastDOW('Friday', j, yyyy) /*find last Friday for the Jth month.*/
end /*j*/
end /*j*/
exit /*stick a fork in it, we're done.*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*┌────────────────────────────────────────────────────────────────────┐
lastDOW: procedure; arg dow .,mm .,yy .; parse arg a.1,a.2,a.3 /*DOW = day of week*/
lastDOW: procedure to return the date of the last day-of-week of
any particular month of any particular year.
if mm=='' | mm=='*' then mm=left( date('U'), 2) /*use default month*/
if yy=='' | yy=='*' then yy=left( date('S'), 4) /*use default year */
if length(yy)==2 then yy=left( date('S'), 2)yy /*append century. */
The day-of-week must be specified (it can be in any case,
/*Note mandatory leading blank in strings below*/
(lower-/mixed-/upper-case) as an English name of the spelled day
of the week, with a minimum length that causes no ambiguity.
I.E.: W for Wednesday, Sa for Saturday, Su for Sunday ...
The month can be specified as an integer 1 ──► 12
1=January 2=February 3=March ... 12=December
or the English name of the month, with a minimum length that
causes no ambiguity. I.E.: Jun for June, D for December.
If omitted [or an asterisk(*)], the current month is used.
The year is specified as an integer or just the last two digits
(two digit years are assumed to be in the current century, and
there is no windowing for a two-digit year).
If omitted [or an asterisk(*)], the current year is used.
Years < 100 must be specified with (at least 2) leading zeroes.
Method used: find the "day number" of the 1st of the next month,
then subtract one (this gives the "day number" of the last day of
the month, bypassing the leapday mess). The last day-of-week is
then obtained straightforwardly, or via subtraction.
└────────────────────────────────────────────────────────────────────┘*/
lastdow: procedure; arg dow .,mm .,yy . /*DOW = day of week*/
parse arg a.1,a.2,a.3 /*orig args, errmsg*/
if mm=='' | mm=='*' then mm=left(date('U'),2) /*use default month*/
if yy=='' | yy=='*' then yy=left(date('S'),4) /*use default year */
if length(yy)==2 then yy=left(date('S'),2)yy /*append century. */
/*Note mandatory leading blank in strings below.*/
$=" Monday TUesday Wednesday THursday Friday SAturday SUnday"
$=" Monday TUesday Wednesday THursday Friday SAturday SUnday"
!=" JAnuary February MARch APril MAY JUNe JULy AUgust September",
!=" JAnuary February MARch APril MAY JUNe JULy AUgust September October November December"
upper $ ! /*uppercase strings*/
" October November December"
upper $ ! /*uppercase strings*/
if dow=='' then call .er "wasn't specified",1
if dow=='' then call .er "wasn't specified",1
if arg()>3 then call .er 'arguments specified',4
if arg()>3 then call .er 'arguments specified',4


do j=1 for 3 /*any plural args ?*/
do j=1 for 3 /*any plural args ?*/
if words(arg(j))>1 then call .er 'is illegal:',j
if words(arg(j))>1 then call .er 'is illegal:',j
end
end


dw=pos(' 'dow,$) /*find day-of-week*/
dw=pos(' 'dow,$) /*find day-of-week*/
if dw==0 then call .er 'is invalid:',1
if dw==0 then call .er 'is invalid:',1
if dw\==lastpos(' 'dow,$) then call .er 'is ambigious:',1
if dw\==lastpos(' 'dow,$) then call .er 'is ambigious:',1


if datatype(mm,'month') then /*if MM is alpha...*/
if datatype(mm,'M') then /*is MM alphabetic?*/
do
do
m=pos(' 'mm,!) /*maybe its good...*/
m=pos(' 'mm,!) /*maybe its good...*/
if m==0 then call .er 'is invalid:',1
if m==0 then call .er 'is invalid:',1
if m\==lastpos(' 'mm,!) then call .er 'is ambigious:',2
if m\==lastpos(' 'mm,!) then call .er 'is ambigious:',2
mm=wordpos(word(substr(!,m),1),!)-1 /*now, use true Mon*/
mm=wordpos( word( substr(!, m), 1), !) - 1 /*now, use true Mon*/
end
end


Line 2,075: Line 2,078:
if yy>9999 then call .er "can't be > 9999:",3
if yy>9999 then call .er "can't be > 9999:",3


tdow=wordpos(word(substr($,dw),1),$)-1 /*target DOW, 0──►6*/
tdow=wordpos(word(substr($,dw),1),$)-1 /*target DOW, 0──►6*/
/*day# of last dom.*/
/*day# of last dom.*/
_=date('B',right(yy+(mm=12),4)right(mm//12+1,2,0)"01",'S')-1
_=date('B',right(yy+(mm=12),4)right(mm//12+1,2,0)"01",'S')-1
?=_//7 /*calc. DOW, 0──►6*/
?=_ // 7 /*calc. DOW, 0──►6*/
if ?\==tdow then _=_-?-7+tdow+7*(?>tdow) /*not DOW? Adjust.*/
if ?\==tdow then _=_ - ? - 7 + tdow + 7 * (?>tdow) /*not DOW? Adjust.*/
return date('weekday',_,"B") date(,_,'B') /*return the answer*/
return date('weekday', _, "B") date(, _, 'B') /*return the answer*/
/*──────────────────────────────────────────────────────────────────────────────────────*/

.er: arg ,_;say; say '***error!*** (in LASTDOW)';say /*tell error, and */
.er: arg ,_; say; say '***error*** (in LASTDOW)'; say /*tell error, and */
say word('day-of-week month year excess',arg(2)) arg(1) a._
say word('day-of-week month year excess',arg(2)) arg(1) a._
say; exit 13 /*... then exit. */</lang>
say; exit 13 /*... then exit. */</lang>
{{out}} when using the following input: <tt> 2012 </tt> or <tt> 12 </tt>
'''output''' &nbsp; when using the following input: &nbsp; <tt> 2012 </tt> &nbsp; &nbsp; or &nbsp; &nbsp; <tt> 12 </tt>
<pre>
<pre style="overflow:scroll">
Friday 27 Jan 2012
Friday 27 Jan 2012
Friday 24 Feb 2012
Friday 24 Feb 2012