What week is it?
MATL, 50 bytes
Thanks to @Neil and @NickClifford for pointing out a mistake, now corrected
ZO1)TThXJYOXIGYO&:8XO!s310=sJ4B-YOIq&:8XO!s310=sX\
Try it online! Or verify all test cases.
Explanation
This uses the three date/time conversion functions that there are in MATL:
XO
: convert date and time to string format;YO
: convert date and time to serial date number;ZO
: convert date and time to vector of components.
Determining if week "0" should become 52 or 53 was costly, because MATL cannot define callable functions to reuse the 8XO!s310=s
part. Reusing by means of loop with a branch only saves one byte, and complicates the explanation, so probably not worth it.
Also, something could be gained inputting the date as a [year, month, day] array; but the I would not use all three date functions :-)
Consider input '17MAY2017'
as an example.
% Implicit input
% STACK: '17MAY2017'
ZO % Convert to date vector
% STACK: [2017 5 17]
1) % Get first entry: year
% STACK: 2017
TTh % Append [1 1]
% STACK: [2017 1 1]
XJ % Copy to clipboard J
YO % Convert to date number
% STACK: 736696
XI % Copy to clipboard I
GYO % Push input again. Convert to date number
% STACK: [736696 736832]
&: % Binary range
% STACK: [736696 736697 736698 ... 736832]
8XO % Convert to date string with format 'ddd': day of week
% STACK: ['Sun'; 'Mon'; 'Tue'; ... ; 'Wed']
!s % Sum of each row (chars are interpreted as code points)
% STACK: [310 298 302 ... 288]
310= % Compare with 310 (sum of 'Sun')
% STACK: [1 0 0 ... 0]
s % Sum of array. If is 0, it needs to be transformed into 52 or 53,
% depending on the number of Sundays the previous year contains.
% STACK: 20
J % Paste from clipboard J
% STACK: 20, [2017 1 1]
4B- % Push [1 0 0] and subtract element-wise
% STACK: 20, [2016 1 1]
YO % COnvert to date number
% STACK: 20, 736330
I % Paste from clipboard I
% STACK: 20, 736330, 736696
q % Subtract 1
% STACK: 20, 736330, 736695
&: % Binary range
% STACK: 20, [736330 736331 736332 ... 736695]
8XO % Convert to date string with format 'ddd': day of week
% STACK: 20, ['Fri'; 'Sat'; 'Sun'; ... ; 'Sat']
!s % Sum of each row (chars are interpreted as code points)
% STACK: 20, [289 296 310 ... 296]
310= % Compare with 310 (sum of 'Sun')
% STACK: 20, [0 0 1 ... 0]
s % Sum of array
% STACK: 20, 52
X\ % 1-based modulo
% STACK: 20
% Implicit display
JavaScript (ES6), 82 80 bytes
Takes input as (year,month,day)
.
let f =
(y,m,d)=>-~((((x=new Date(y,m-1,d))-new Date(y,0,1))/864e5+372-x.getDay())/7%53)
console.log(f(2017, 5,17)) // 20
console.log(f(2013, 1, 3)) // 53
console.log(f(2017, 1, 1)) // 1
console.log(f(1901, 5,17)) // 19
console.log(f(2100,12,31)) // 52
console.log(f(2015, 7, 7)) // 27
JavaScript (Firefox 34+), 70 bytes
with(new Date())y.value=getFullYear(),m.value=getMonth()+1,d.value=getDate()+1
f=
(y,m,d)=>new Date(y,--m,d-new Date(y,m,d).getDay()).toLocaleFormat`%U`
<div oninput=w.value=f(y.value,m.value,d.value)><input id=y type=number><input id=m type=number min=1 max=12><input id=d type=number min=1 max=31><input id=w readonly placeholder=Output>
Works by finding the first day of the week containing the given date, then finding that day's week number (which is never zero).