I know, a bit late.

# Challenge

Your challenge is, given a date, output if it's not an Advent Sunday, or the Advent Sunday of the year.

# Rules

• The $$\4^\text{th}\$$ Advent is determined by the Sunday before Christmas day (the $$\25^\text{th}\$$ of December). The $$\3^\text{rd}\$$ Advent is the Sunday before the $$\4^\text{th}\$$ Advent, and so on until the $$\1^\text{st}\$$ Advent.
• If Christmas Day falls on a Sunday, then the Sunday before is still the $$\4^\text{th}\$$ Advent.
• Input will consist of day, month and year, as an iterable with any order, or a string, or 3 separate integers.
• Input will be a valid date, numerically and also calendrically.
• Output should be falsey (0 or Boolean False) if the date is not an Advent Sunday, or else an integer denoting which Advent Sunday it is.
• This is , so the shortest answer wins.

# Examples

[In]: [2, 12, 2021]
[Out]: 0

[In]: [6, 5, 2023]
[Out]: False

[In]: [12, 12, 2021]
[Out]: 3

[In]: [30, 11, 1997]
[Out]: 1

[In]: [25, 12, 2011]
[Out]: false

[In]: [21, 12, 3000]
[Out]: 4


Good Luck!

• May we take input as 3 integers instead of a collection? Dec 27, 2021 at 18:21
• @chunes yes, 'll add that in Dec 27, 2021 at 18:32

# Excel, 71 66 Bytes

Saved 5 bytes thanks to Taylor Raine

Aside: At the time of posting, this answer has the smallest byte count. That is baffling. Score one for Excel's date handling, I guess.

=LET(a,4-(INT(("12/23/"&YEAR(A1))/7)*7+1-A1)/7,(LEN(a)=1)*(a<5)*a)


Input is in cell A1. Output is wherever the formula is. Returns a number 1-4 for advent Sundays and a 0 for all other dates.

LET(a,4-(INT(("12/23/"&YEAR(A1))/7)*7+1-A1)/7


The first part calculates which advent Sunday an input is and does most of the heavy lifting.

• ("12/23/"&YEAR(A1)) finds Christmas Eve Eve (CEE) in the year of the input. We find Eve Eve hear because it saves us some extra bytes of adjustment later.
• INT(~/7)*7 takes that date, divides by 7 (b/c 7 days per week), rounds it down, then multiplies it by 7. This finds the Saturday before CEE. If CEE is a Saturday, then it returns that date.
• (INT(~/7)*7+1-A2)/7 adds one to get Sunday, subtracts the input, and divides by 7 to get the number of weeks between the input and the Sunday before Christmas. This may not be a whole number.
• 4-(~) subtracts that result from 4 to invert the result. I.E., the Sunday before Christmas needs to be the 4th Sunday, not the 1 week before.
LET(a,~,(LEN(a)=1)*(a<5)*a)


Now that the heavy lifting is out of the way, we can examine the results. Note that using TRUE and FALSE values in math will treat TRUE = 1 and FALSE = 0. By multiplying various statements that will evaluate to either TRUE or FALSE, we can filter out undesirable results.

• (LEN(a)=1) filters out any non-integers as well as negative integers. This removes every non-Sunday in the advent calendar and all dates before the first Sunday. This does not filter out the 0th Sunday but the end result will still be 0 so it works.
• (a<5) filters out Sundays after the 4th Sunday.
• (~)*(~)*a returns the value if it has passed both those filters. Otherwise, it returns 0.

In this screenshot, I have added a column to return the value of a since that's so much of the calculation. I have also extended the data beyond the samples above to show some edge cases. • Wow. Another spreadsheet fan. Dec 29, 2021 at 17:31
• I'm just realising now that THIS IS SO UNDERRATED. Excel beat Mathematica!!! Dec 30, 2021 at 7:55
• You can get this down to 66 bytes if you use some implicit date conversion and Boolean multiplication as =LET(a,4-(INT(("12/23/"&YEAR(A1))/7)*7+1-A1)/7,(a<5)*(LEN(a)=1)*a) - but this will change the falsey output to be 0 rather than false Jan 5, 2022 at 17:54
• @TaylorRaine This is great! I haven't golfed in a while so the refresher course on Excel tricks is fantastic. I welcome your comments. I don't think I even knew about implicit date conversion. Jan 5, 2022 at 18:39

# Factor + calendar.holidays.us, 85 bytes

[ <date> dup christmas-day 4 [ dup last-sunday ] times 0 5 narray reverse nip index ]


Takes input as three integers in <year> <month> <day> order. The last-sunday word postdates build 1525, the one TIO uses, so here's a screenshot of running the above code in build 2101's listener: ## Explanation

                             ! 2021 12 12
<date>                       ! 2021-12-12
dup                          ! 2021-12-12 2021-12-12
christmas-day                ! 2021-12-12 2021-12-25
4 [ dup last-sunday ] times  ! 2021-12-12 2021-12-25 2021-12-19 2021-12-12 2021-12-5 2021-11-28
0 5 narray                   ! 2021-12-12 2021-12-25 { 2021-12-19 2021-12-12 2021-12-5 2021-11-28 0 }
reverse                      ! 2021-12-12 2021-12-25 { 0 2021-11-28 2021-12-5 2021-12-12 2021-12-19 }
nip                          ! 2021-12-12 { 0 2021-11-28 2021-12-5 2021-12-12 2021-12-19 }
index                        ! 3


# JavaScript (Node.js), 78 bytes

(y,m,d)=>/Su/.test(c=new Date(y,m-1,d))*'01234'[(c-new Date(y,9,51))/6048e5|0]


Try it online!

Falsy may be 0 or NaN. Add 2 bytes (append |0) to always get 0. User must run this program with computer configured to UTC timezone or any other timezone that: 1. No DST shift during Nov 20 to Dec 31, 2. Name of timezone (in system language) does not contain substring "Su" (case sensitive).

new Date(y,9,51) is Nov 20 in JavaScript.

# Python3, 152 bytes:

from datetime import*
t=lambda x:0if x>=date(x.year,12,25)else 1+t(x+timedelta(days=7))
f=lambda x:(s:=date(*x)).weekday()==6and(0<(j:=(5-t(s)))<5)and j


Try it online!

# Retina 0.8.2, 116 bytes

3=
;
\d+
$*_ ((_*)\2\2\2_*);((_*)\4\4\4_*)$4$3$2$1$1$1$1$1 \G_{7} -_{12}- ____ -_{11}-_{26} ^(_{7}){1,4}$|.+
$#1  Try it online! Link includes test cases. Takes input in ISO date format. Explanation: 3= ;  Separate the year from the century. \d+$*_


Convert to unary.

((_*)\2\2\2_*);((_*)\4\4\4_*)
$4$3$2$1$1$1$1$1
\G_{7}



Perform Zeller's congruence on the 25th of December of the input year.

-_{12}-
____
-_{11}-_{26}



Add this to the day of the month, adding an extra 4 for December or subtracting 26 for November 26 or later. Other months get ignored and fail to match the next stage at all.

^(_{7}){1,4}$|.+$#1


Count the number of whole weeks, but the result must be an integer between 1 and 4 inclusive.

# C (gcc), 215 202 192 bytes

#import<time.h>
i;*t;*l;f(d,m,y){5[t=calloc(9,8)]=y-1900;t=m-1;t=d;l=mktime(t);i=6[t=gmtime(&l)];y=t;t=11;t=25;l=mktime(t);d=7[t=gmtime(&l)]-y;m=4-d/7-!t;i=i|!d|m<1|m>4?0:m;}


Try it online!

Saved 13 bytes thanks to ceilingcat!!!

Inputs the day, month and year as separate parameters.
Returns which Advent Sunday it is or $$\0\$$ otherwise.

# Wolfram Language (Mathematica),  88  79 bytes

Input format should be {year, month, day}.

Ramp[4-DayCount[#,{#&@@#,12,24},s=Sunday]]Boole[DayName@#==s&&Rest@#!={12,25}]&


Try it online!

Output:

0
0
3
1
0
4


79 bytes - Thanks to @att

• 79 bytes
– att
Dec 28, 2021 at 2:56

# Python 3.8 (pre-release), 114 bytes

lambda a,b,c:(y:=int((c+10.5)/7))%5+y//5 if date(a,b,c).weekday()==6 and[b,c]!=[12,25]else 0
from datetime import*


Try it online!

• Welcome to Code Golf, and nice first answer! Dec 28, 2021 at 13:23
• You can make it 112 bytes by removing the space in 5 if and 6 and[b,c] Dec 28, 2021 at 21:56

# Python 3.8,  128  116 bytes

lambda q:max(x*(date(*q)==(M:=date(q,11,27))+timedelta(7*x+~M.weekday()))for x in(1,2,3,4))
from datetime import*


Try it online!

# Perl 5, 144 bytes

sub{$_=join$",map{@t=gmtime$_*604800+3e5;19000100+$t*1e4+$t*100+$t}1..6e4;pop=~/..../;/ $&$'( $&\d+)+/;$_=6-$&=~y///c/9;/^[1-4]$/?\$_:0}


Try it online!