17
\$\begingroup\$

Introduction

Often, people refer to dates as the "second Friday in August, 2018" or the "fourth Sunday in March, 2012". But it's hard to tell what date that is! Your task to is to write a program that receives a year, a month, a day of the week, and an integer, and output that date.

Challenge

  • For input, you will get a year, a month, a day of week, and a number.

  • You can take input in any reasonable format, like using a string for the day of week or using a zero indexed weekday, or even take the year and month in a single string. Do explain your input format in your answer, though.

  • The integer that tells you which day of week in the month to target will be an integer from 1-5. The integer will never refer to a day of week that does not exist(e.g. the fifth Friday of February 2019, which doesn't exist).

  • Years will always be positive.

  • Your output can be in any reasonable format, including printing your final date. However, please explain your output format un your answer.

  • Providing the year and month in the output is optional. Also, you may assume the date is valid.

Example Input and Output

Consider this input, with the format being taking in the year as a 4 digit number, month as an integer, day of week as string, and the ordinal number as an integer:

2019, 3, Saturday, 2
2019, 12, Sunday, 1
2019, 9 Saturday, 1

Output:

March 9
December 1
September 7

This is , so shortest answer wins.

\$\endgroup\$
  • 1
    \$\begingroup\$ I thought I might be able to use GNU date, but amusingly, the parser has an... interesting interpretation here. \$\endgroup\$ – Doorknob Jan 1 at 20:44
  • \$\begingroup\$ May week number be 0-indexed? \$\endgroup\$ – Jo King Jan 2 at 1:52
  • \$\begingroup\$ Sure, if it suits your program \$\endgroup\$ – Embodiment of Ignorance Jan 2 at 2:12
  • \$\begingroup\$ Suggested test case: 2018, 12, Sunday 1 \$\endgroup\$ – Adám Jan 2 at 10:55
  • \$\begingroup\$ Suggested test case: the first Saturday in September 2019 \$\endgroup\$ – Shaggy Jan 2 at 12:07

16 Answers 16

4
\$\begingroup\$

MediaWiki Template, 19 bytes

{{#time:r|{{{1}}}}}

This is a MediaWiki Template ParserFunctions port of this PHP answer

Note: #time use PHP strtotime internally.


Sample Input

{{#time:r|second saturday of March 2019}}

Sample Output

Sat, 09 Mar 2019 00:00:00 +0000

\$\endgroup\$
3
\$\begingroup\$

Japt, 19 15 bytes

Input is: year, 0-based index of month, 0-based index of day of the week (0 is Sunday) & n.

_XµW¶Ze}f@ÐUVYÄ

Try it

                    :Implicit input of U=year, V=month, W=weekday & X=n
       }f           :Output the first element generated by the right function that returns
                    : falsey (0) when passed through the left function
         @          :Right function. Y=0-based index of current iteration
          ÐUVYÄ     :  new Date(U,V,Y+1)
_                   :Left function. Z=date being passed
 Xµ                 :  Decrement X by
   W¶               :   Test W for equality with
     Ze             :    Z.getDay()
\$\endgroup\$
2
\$\begingroup\$

C# (Visual C# Interactive Compiler), 59 bytes

(y,m,d,w)=>1+(d-(int)new DateTime(y,m,1).DayOfWeek+7)%7+7*w

Try it online!

-27 bytes thanks to @EmbodimentOfIgnorance!

Less golfed code...

// y: year
// m: month
// d: day of week (0 is Sunday)
// w: week number (0 based)
(y,m,d,w)=>
  // start on the first day of the month
  1+
  // determine the number of days to
  // the first occurrence of the
  // requested weekday
  (d-(int)new DateTime(y,m,1).DayOfWeek+7)%7+
  // add the number of requested weeks
  7*w

The return value is an integer for the day of the month of the requested date.

\$\endgroup\$
  • \$\begingroup\$ If you only return the day of the month, which is allowed, you can golf this down to 59 bytes \$\endgroup\$ – Embodiment of Ignorance Jan 2 at 3:04
  • \$\begingroup\$ Thanks for the tip again - (that's 2x today ;) I will update my answers. \$\endgroup\$ – dana Jan 2 at 4:14
2
\$\begingroup\$

SmileBASIC, 58 51 48 46 45 bytes

READ N,M$DTREAD M$OUT,,D,W?(5-W+D*2)MOD 7+N*7

Input is in the form: week,year/month/weekday

  • week: week number, 0-indexed
  • year: year, 4 digits
  • month: month (1-indexed), 2 digits 0-padded
  • weekday: day of the week (1-indexed, 1=Sunday), 2 digits 0-padded

Output is the day of the month, 0 indexed.
The 2nd Saturday in March 2019 would be 1,2019/03/078 (March 9th)

Ungolfed

READ WEEK,M$
DTREAD M$ OUT ,,D,W
'Functions in SB can output multiple values using OUT.
'In this case, we don't need the first 2 values, so no variables are given.

PRINT (5-W+ D*2) MOD 7 +WEEK*7

Explanation

The input form was specifically chosen so that the year/month/weekday could be passed directly to DTREAD, which is a function which parses a YYYY/MM/DD string and returns the year/month/day as numbers, as well as calculating the day of the week.

However, notice that, where DTREAD expects the day of the month, we're giving it the day of the week instead. This complicates things, but also means that there are fewer input values and we don't need to add /01 to the end of the date string.

DTREAD outputs W and D.
W is the weekday, and D is the day-of-the-week of the Wth day of the month.
(So, if you input 7 as the weekday, D will be 7 and W will be whatever day-of-the-week the 7th day of the month is)

The expression (5-W+D*2)MOD 7 is used to get the 1st occurrence of the input weekday, as a 0-indexed day of the month. (I figured this one out mostly through trial and error)

After that, the program just adds WEEK*7.


I really wish there were separate words for "day of the week" and "day of the month".

\$\endgroup\$
2
\$\begingroup\$

Perl 6, 52 48 bytes

{1+($^c+4-Date.new($^a,$^b,1).daycount)%7+$^d*7}

Try it online!

Anonymous code block that takes input as year, month, day of week (Sunday is 0) and week number (0 indexed). Output is a date object.

Old Explanation:

{                                                  } # Anonymous code block
 (   Date.new(         ))   # Create a new date with
              $^a,$^b,1     # With year, month and the first day
  $_=                       # Save in the variable $_
                         +  # Add to this
                           $^c+4                     # The given day plus 4
                          (     -.daycount)          # The number of days since 17 Nov, 1858
                                           %7        # Modulo 7 to get the correct day
                                             +$^d*7  # Plus the 7 times the number of weeks
\$\endgroup\$
  • \$\begingroup\$ I think the week number needs to be 1-indexed \$\endgroup\$ – 12Me21 Jan 2 at 1:37
  • \$\begingroup\$ @12Me21 The question says that input is flexible, but I've asked whether we an take week number as 0 indexed \$\endgroup\$ – Jo King Jan 2 at 1:55
  • \$\begingroup\$ This doesn't seem to work for other months. I think you need $^c+4-$!.daycount. \$\endgroup\$ – nwellnhof Jan 2 at 2:24
  • \$\begingroup\$ @nwellnhof Ah, I should have thought of that instead of trial and error, lol. Should be fixed now \$\endgroup\$ – Jo King Jan 2 at 3:00
1
\$\begingroup\$

MATL, 28 27 bytes

'1 'ihYO31:q+t8XOi=!A)i)1XO

This uses three inputs:

  • String with month and year: 'March 2019'
  • String with three letters, first capitalized, indicating day of the week: 'Sat'
  • Number: 2.

Output is a string with day, year and month separated with dashes: 09-Mar-2019.

Try it online!

Explanation

Consider inputs 'March 2019', 'Sat', 2.

'1 '    % Push this string
        % STACK: '1 '
ih      % Input string: month and year. Concatenate
        % STACK: '1 March 2019'
YO      % Convert to serial date number
        % STACK: 737485
31:q+   % Create vector [0 1 2 ... 30] and add element-wise
        % STACK: [737485 737486 737487 ... 737515]
t8XO    % Duplicate. Convert to date format 'ddd': day of week in three letters. Gives
        % a 2D char array
        % STACK: [737485 737486 737487 ... 737515], ['Fri'; 'Sat'; 'Sun'; ...; 'Sun']
i=      % Input string: day of week in three letters. Compare element-wise with broadcast
        % STACK: [737485 737486 737487 ... 737515],
        % [0 0 0; 0 0 0; ...; 1 1 1; 0 0 0; ... 1 1 1; ...]
!A      % True for rows containing only 1
        % STACK: [737485 737486 737487 ... 737515], [0 0 ... 1 ... 0 ... 1 ...]
)       % Index: uses the second vector as a mask into the first
        % STACK: [737486 737493 737500 737507 737514]
i)      % Input number. Index
        % STACK: 737493
1XO     % Convert to date format 'dd-mmm-yyyy'. Implicit display
        % STACK: '09-Mar-2019'
\$\endgroup\$
1
\$\begingroup\$

Python 3, 92 82 bytes

82 bytes thanks to @Jo King

lambda y,m,d,w:z(y,m)[w-(z(y,m)[0][d]>0)][d]
from calendar import*
z=monthcalendar

Try it online!

Original version, 92 bytes

from calendar import*
def f(y,m,d,w):
 x=monthcalendar(y,m)
 if x[0][d]:w-=1
 return x[w][d]

Try it online!

Takes the year as an integer, month as a 1-indexed integer, day of the week as a 0-index integer where Monday is 0 and Sunday is 6, and week of the month as a 1-indexed integer.

How it works:

# import monthcalendar
from calendar import*
# function with 4 inputs
def f(y,m,d,w):
 # get a 2-D array representing the specified month
 # each week is represented by an array
 # and the value of each element is its date of the month
 # Monday is the 0th element of each week, Sunday is the 6th element
 # days of the first week of the month before the 1st are 0s 
 x=monthcalendar(y,m)
 # if the first week of the month includes the desired day of week
 # convert the week of month to 0-index so that it takes into account the first week
 if x[0][d]:w-=1
 # return the weekday of the week number specified
 return x[w][d]
\$\endgroup\$
1
\$\begingroup\$

R, 72 69 bytes

function(y,m,d,n,D=as.Date(paste0(y,-m,-1))+0:31)D[weekdays(D)==d][n]

Try it online!

Taking input as :

  • Year number
  • Month number (1-12)
  • Weekday string in the current locale (TIO requires english name with capital letter)
  • Ordinal number (1-indexed)
\$\endgroup\$
0
\$\begingroup\$

PHP, 46, 43, 31 bytes

<?=date(d,strtotime($argv[1]));

Try it online!

The program receives as input a string like "second saturday of March 2019"

The program prints the day number.

-12 bytes thanks to Shaggy.

\$\endgroup\$
  • 1
    \$\begingroup\$ 31 bytes \$\endgroup\$ – Shaggy Jan 1 at 23:42
  • \$\begingroup\$ Also, I don't think you need the of in the input. \$\endgroup\$ – Shaggy Jan 1 at 23:58
  • \$\begingroup\$ @Shaggy, I think these are details. There may be many options. \$\endgroup\$ – Кирилл Малышев Jan 2 at 0:00
0
\$\begingroup\$

Groovy, 46 bytes

{y,m,d,w->r=new Date(y,m,7*w)
r-(r.day+7-d)%7}

Try it online!

Input as years since 1900, 0-indexed month, 0-indexed day (Sunday being 0) and week number

\$\endgroup\$
0
\$\begingroup\$

Scala, 86 bytes

(y,m,d,w)=>{var r=new java.util.Date(y,m,7*w)
r.setDate(r.getDate-(r.getDay+7-d)%7)
r}

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Red, 64 60 bytes

func[y m d n][a: to-date[1 m y]d - a/10 - 7 % 7 +(n * 7)+ a]

Try it online!

Takes the year, the month and the weekday as numbers, 1-indexed, Monday is the first day of the week.

\$\endgroup\$
  • \$\begingroup\$ huh, to-date is a thing. maybe this would be useful in the christmase eve format challenge \$\endgroup\$ – ASCII-only Jan 2 at 9:18
  • \$\begingroup\$ @ASCII-only We used now for that challenge \$\endgroup\$ – Galen Ivanov Jan 2 at 9:21
  • 1
    \$\begingroup\$ yeah, but i was thinking of alternative methods (namely, the <repeat " Eve" date2-date1 times> method iirc) \$\endgroup\$ – ASCII-only Jan 2 at 9:21
  • \$\begingroup\$ @ASCII-only >> 25-Dec-2019 - 1-1-2019 == 358 \$\endgroup\$ – Galen Ivanov Jan 2 at 9:24
0
\$\begingroup\$

APL (Dyalog Unicode), 36 bytesSBCS

Full program. Prompts for [year,month] (January is 1), then for day (Sunday is 0), then for n (first is 1).

date⎕⊃d/⍨⎕=7|d←(⍳31)+days⎕⊣⎕CY'dfns'

Try it online!

⎕CY'dfns'copy in the dfns library

 discard the result of that in favour of…

 prompt console for [year,month] numbers

days[c] days[n] since 1899-12-31 of the 0th of that month

(⍳31)+ add the integers 1…31 to that

d← store in d (for day numbers)

7| division remainder when dividing by 7 (day-of-week with Sunday being 0 due to good epoch)

⎕= prompt console for day-of-week number and get mask where equal the day-of-week numbers

d/⍨ filter d with that mask

⎕⊃ prompt console for n and use that to pick from the list of day numbers

date[c] datetime stamp[n] (has trailing zeros for hours, minutes, seconds, milliseconds)


Click [c] for code and [n] for notes.

\$\endgroup\$
0
\$\begingroup\$

JavaScript (ES6), 49 48 bytes

f=
(a,d,n)=>(d+6-new Date(...a,7).getDay())%7+n*7-6
<div oninput=o.textContent=f([+y.value,+m.value],+d.value,+n.value)>Year: <input id=y type=number value=2019><br>Month: <select id=m><option value=0>Jan<option value=1>Feb<option value=2>Mar<option value=3>Apr<option value=4>May<option value=5>Jun<option value=6>Jul<option value=7>Aug<option value=8>Sep<option value=9>Oct<option value=10>Nov<option value=11>Dec</select><br>Day: <select id=d><option value=0>Sun<option value=1>Mon<option value=2>Tue<option value=3>Wed<option value=4>Thu<option value=5>Fri<option value=6>Sat</select><br>Count: <input id=n type=number value=1 min=1 max=5><pre id=o>

Takes parameters as f([year, month], day, number). Month and day of week (starting on Sunday) are zero-indexed. Edit: Saved 1 byte thanks to @Shaggy.

\$\endgroup\$
  • \$\begingroup\$ Is the day of week in the format Sunday-Saturday or Monday-Sunday? \$\endgroup\$ – Embodiment of Ignorance Jan 1 at 22:48
  • \$\begingroup\$ @EmbodimentofIgnorance Sorry, I knew I had forgotten something. (The snippet now uses select to make it easier.) \$\endgroup\$ – Neil Jan 1 at 22:51
  • \$\begingroup\$ @EmbodimentofIgnorance, Sunday is 0 in JS. \$\endgroup\$ – Shaggy Jan 1 at 22:52
  • \$\begingroup\$ Oh. I didn't know that, I'm not that familiar with Javascript. \$\endgroup\$ – Embodiment of Ignorance Jan 1 at 22:52
  • \$\begingroup\$ 48 bytes \$\endgroup\$ – Shaggy Jan 2 at 10:51
0
\$\begingroup\$

TSQL, 106 bytes

DECLARE @ datetime='2019',@m int=3,@w char(2)='saturday',@p int=2

SELECT dateadd(wk,datediff(d,x,dateadd(m,@m-1,@)-1)/7,x)+@p*7FROM(SELECT
charindex(@w,' tuwethfrsasu')/2x)x

Output:

2019-03-09 00:00:00.000

Try it out

\$\endgroup\$
0
\$\begingroup\$

Kotlin, 131 84 bytes

47 bytes thanks to ASCII-only's code and comment.

Input: year, monthNumber, weekdayNumber, weekNumber

All integers 1 to maximum on single line. Week day number is Sunday of 1 to Saturday of 7. The main program makes the year lose 1900 for Date class and month and weekday are shifted to start with zero instead of one before calling the lambda. You can enter your arguments in the input text box to try your own dates.

Output: a Date class instance. The main program displays the result like: Sat Mar 09 00:00:00 UTC 2019.

There is an expanded version with comments explaining the code for those wishing to learn more.

{y,m,d,w->val r=java.util.Date(y,m,7*w)
r.setDate(r.getDate()-(r.getDay()+7-d)%7)
r}

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ 74 - uses same method as Scala and Groovy answers \$\endgroup\$ – ASCII-only Jan 7 at 4:30
  • 1
    \$\begingroup\$ Fixed, 84 \$\endgroup\$ – ASCII-only Jan 7 at 4:35
  • 1
    \$\begingroup\$ No need for the import command anymore so that's not a problem :P \$\endgroup\$ – ASCII-only Jan 10 at 9:31

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.