Find the last Sunday of each month
You are encouraged to solve this task according to the task description, using any language you may know.
Write a program or a script that returns the last Sundays of each month of a given year. The year may be given through any simple input method in your language (command line, std in, etc.).
Example of an expected output:
./last_sundays 2013 2013-01-27 2013-02-24 2013-03-31 2013-04-28 2013-05-26 2013-06-30 2013-07-28 2013-08-25 2013-09-29 2013-10-27 2013-11-24 2013-12-29
REXX
This REXX example is an exact replication of the Rosetta Code
- find last Fridays of each month for any year
except for the innards of the first DO loop. <lang rexx>/*REXX program displays dates of last Sundays of each month for any year*/ parse arg yyyy
do j=1 for 12 _ = lastDOW('Sunday', j, yyyy) say right(_,4)'-'right(j,2,0)"-"left(word(_,2),2) end /*j*/
exit /*stick a fork in it, we're done.*/
/*┌────────────────────────────────────────────────---─────────────────┐
│ 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. │ └───────────────────────────────────────────────────---──────────────┘*/
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" !=" JAnuary February MARch APril MAY JUNe JULy AUgust September",
" October November December"
upper $ ! /*uppercase strings*/ if dow== then call .er "wasn't specified",1 if arg()>3 then call .er 'arguments specified',4
do j=1 for 3 /*any plural args ?*/ if words(arg(j))>1 then call .er 'is illegal:',j end
dw=pos(' 'dow,$) /*find day-of-week*/ if dw==0 then call .er 'is invalid:',1 if dw\==lastpos(' 'dow,$) then call .er 'is ambigious:',1
if datatype(mm,'month') then /*if MM is alpha...*/
do m=pos(' 'mm,!) /*maybe its good...*/ if m==0 then call .er 'is invalid:',1 if m\==lastpos(' 'mm,!) then call .er 'is ambigious:',2 mm=wordpos(word(substr(!,m),1),!)-1 /*now, use true Mon*/ end
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 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 negative:",3 if yy>9999 then call .er "can't be > 9999:",3
tdow=wordpos(word(substr($,dw),1),$)-1 /*target DOW, 0──►6*/
/*day# of last dom.*/
_=date('B',right(yy+(mm=12),4)right(mm//12+1,2,0)"01",'S')-1 ?=_//7 /*calc. DOW, 0──►6*/ if ?\==tdow then _=_-?-7+tdow+7*(?>tdow) /*not DOW? Adjust.*/ return date('weekday',_,"B") date(,_,'B') /*return the answer*/
.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; exit 13 /*... then exit. */</lang>
output when using the default input (the current year, 2013):
2013-01-27 2013-02-24 2013-03-31 2013-04-28 2013-05-26 2013-06-30 2013-07-28 2013-08-25 2013-09-29 2013-10-27 2013-11-24 2013-12-29