Last Friday of each month: Difference between revisions

Content added Content deleted
m (→‎{{header|D}}: less confusing)
m (→‎{{header|REXX}}: removed ''height'' from ''style'', added whitespace, changed comments. -- ~~~~)
Line 715: Line 715:
=={{header|REXX}}==
=={{header|REXX}}==
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.
<lang rexx>/*REXX program displays dates of last Fridays of each month for any year*/
<lang rexx>
/*REXX program displays dates of last Fridays of each month for any 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)
end
end /*j*/
exit /*stick a fork in it, we're done.*/
exit


/*┌────────────────────────────────────────────────---─────────────────┐
/* ┌─────────────────────────────────────────────────────────────────┐
│ lastDOW: procedure to return the date of the last day-of-week │
│ lastDOW: procedure to return the date of the last day-of-week of
of any particular month (of any particular year). │
│ any particular month of any particular year.
│ │
│ The day-of-week must be specified (it can be in any case, │
│ The day-of-week must be specified (it can be in any case,
│ (lower-/mixed-/upper-case) as an English name of spelled day
│ (lower-/mixed-/upper-case) as an English name of the spelled day │
│ of the week, with a minimum length that causes no ambiguity. │
│ of the week, with a minimum length that causes no ambiguity.
│ I.E.: W for Wednesday, Sa for Saturday, Su for Sunday │
│ I.E.: W for Wednesday, Sa for Saturday, Su for Sunday ...
│ │
│ The month can be specified as an integer 1 ──> 12 │
│ The month can be specified as an integer 1 ──► 12
│ 1=January 2=February 3=March ... 12=December │
│ 1=January 2=February 3=March ... 12=December
│ or the English name of the month, with a minimum length that │
│ or the English name of the month, with a minimum length that
│ causes no ambiguity. I.E.: Jun for June, D for December.│
│ causes no ambiguity. I.E.: Jun for June, D for December.
│ If omitted [or an asterisk(*)], the current month is used. │
│ If omitted [or an asterisk(*)], the current month is used.
│ │
│ The year is specified as an integer or just the last two digits │
│ 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 │
│ (two digit years are assumed to be in the current century, and
│ there is no windowing for a two-digit year). │
│ there is no windowing for a two-digit year).
│ If omitted [or an asterisk(*)], the current year is used. │
│ If omitted [or an asterisk(*)], the current year is used.
│ Years < 100 must be specified with (at least 2) leading zeroes.│
│ Years < 100 must be specified with (at least 2) leading zeroes.│
│ │
│ Method used: find the "day number" of the 1st of the next month,│
│ Method used: find the "day number" of the 1st of the next month,
│ then subtract 1 (this gives the "day number" of the last day of │
│ then subtract one (this gives the "day number" of the last day of │
│ the month, bypassing the leapday mess). The last day-of-week │
│ the month, bypassing the leapday mess). The last day-of-week is
is then obtained straightforwardly, or via subtraction. │
│ then obtained straightforwardly, or via subtraction.
└───────────────────────────────────────────────────---──────────────┘*/
└─────────────────────────────────────────────────────────────────┘ */


lastdow: procedure; arg dow .,mm .,yy . /*dow = day of week*/
lastdow: procedure; arg dow .,mm .,yy . /*DOW = day of week*/
parse arg a.1,a.2,a.3 /*orig args, errmsg*/
parse arg a.1,a.2,a.3 /*orig args, errmsg*/
if mm=='' | mm=='*' then mm=left(date('U'),2) /*use default month*/
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 yy=='' | yy=='*' then yy=left(date('S'),4) /*use default year */
if length(yy)==2 then yy=left(date('S'),2)yy /*append century. */
if length(yy)==2 then yy=left(date('S'),2)yy /*append century. */
/*Note mandatory leading blank in strings below.*/
/*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"
" October November December"
upper $ ! /*uppercase strings*/
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,'month') then /*if MM is alpha...*/
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

if \datatype(mm,'W') then call .er "isn't an integer:",2
if \datatype(mm,'W') then call .er "isn't an integer:",2
if \datatype(yy,'W') then call .er "isn't an integer:",3
if \datatype(yy,'W') then call .er "isn't an integer:",3
if mm<1 | mm>12 then call .er "isn't in range 1-->12:",2
if mm<1 | mm>12 then call .er "isn't in range 1──►12:",2
if yy=0 then call .er "can't be 0 (zero):",3
if yy=0 then call .er "can't be 0 (zero):",3
if yy<0 then call .er "can't be negative:",3
if yy<0 then call .er "can't be negative:",3
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,*/
.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 /*... and then exit.*/
say; exit 13 /*... then exit. */</lang>
'''output''' when using the following input: <tt> 2012 </tt> or <tt> 12 </tt>
</lang>
<pre style="overflow:scroll">
Output when an input of <tt> 2012 </tt> or <tt> 12 </tt> is used:
<pre style="height:20ex;overflow:scroll">
Friday 27 Jan 2012
Friday 27 Jan 2012
Friday 24 Feb 2012
Friday 24 Feb 2012