20
\$\begingroup\$

This challenge, I hope, is simple to understand. Given a date-string (given in any format you prefer, so long as it has 4 digits of year and 2 digits of day and month), calculate the weekday for the particular date-string. You must output 7 different values, corresponding to the weekday you have calculated.

It's okay if your program only theoretically (given enough time and memory) prints the correct weekday, as long as it can calculate for years between 2000 and 2002.

If you're using a built-in, consider adding a non-built-in approach as well. Built-in solutions won't be considered for being accepted.

Make sure to account for leap years!

Test cases

Input format is DD/MM/YYYY, output is one of Su, Mo, Tu, We, Th, Fr, Sa (both can be adjusted for your choice)

Input -> Output
12/11/2001 -> Mo
29/02/2000 -> Tu
04/07/2002 -> Th
11/08/2000 -> Fr

This is , so shortest answer wins!

EDIT: When I said "No built-ins", I meant that built-ins that automatically calculate the weekday for a particular date were discouraged, not prohibited. If the built-in aids in finding the weekday, no problem, but if it directly calculates the weekday then I discourage it.

\$\endgroup\$
22
  • 2
    \$\begingroup\$ Could you please clarify whether we have to support dates outside the range 2000-2002? With the current wording, I'm not quite sure. \$\endgroup\$
    – Arnauld
    Oct 5, 2022 at 15:39
  • 2
    \$\begingroup\$ Can we take input as a builtin date object? \$\endgroup\$
    – naffetS
    Oct 5, 2022 at 18:21
  • 1
    \$\begingroup\$ @Arnauld my reading: it must theoretically be able to do so, but it's OK if memory constraints make this impossible; e.g. if you stack overflow for inputs 2003 and onward, its OK so long the algorithm for getting the weekday would have been correct given infinite memory or something. \$\endgroup\$ Oct 5, 2022 at 18:49
  • 1
    \$\begingroup\$ No @Arnauld, you dont need to \$\endgroup\$ Oct 6, 2022 at 3:46
  • 4
    \$\begingroup\$ I'm VTCing this since the built-in ban is particularly subjective here. I'd recommend just getting rid of it, and maybe encouraging not using built-ins. \$\endgroup\$ Oct 6, 2022 at 13:00

31 Answers 31

10
\$\begingroup\$

Excel (ms365), 12 bytes

=WEEKDAY(A1)

Outputs numbers [1-7] where Sunday == 1;

![enter image description here


Excel (ms365), 14 bytes

=WEEKDAY(A1,2)

Outputs numbers [1-7] where Monday == 1:

enter image description here


Excel (ms365), 15 bytes

=TEXT(A1,"ddd")

Outputs lowercase text [mo-su]:

enter image description here


Excel (ms365), 23 bytes

=PROPER(TEXT(A1,"ddd"))

Outputs text [Mo-Su] capitalizing the first letter:

enter image description here


Note: Excel will recognize the date-strings as actual dates. Therefor having date-strings and date-numbers would have the same effect.

\$\endgroup\$
8
\$\begingroup\$

R, 31 30 bytes

Edit: doesn't beat Robin Ryder's answer but at least (currently) ties it

function(s)el(as.Date(s):1)%%7

Try it online!

Semi built-in solution. Thursday is 0, and then cycles through 1-6.

\$\endgroup\$
1
7
\$\begingroup\$

05AB1E, 36 24 22 21 19 bytes

4Ö2‚I3@è³¹²23*9÷Æ7%

-12 bytes thanks to @DominicVanEssen (and @Neil) for reminding me that the challenge years are guaranteed to be 2000-2002
-2 bytes porting @Arnauld's JavaScript (top) answer, so make sure to upvote him as well!
-1 byte thanks to @DominicVanEssen again in @Arnauld's port
-2 bytes taking three loose inputs instead of a triplet

Three loose input-integers in the order yyyy,MM,dd; output is an integer where 6 = Sunday, 5 = Monday, ..., 0 = Saturday.

Try it online or verify all test cases.

Explanation:

4Ö       # Check if the (implicit) first input-year is divisible by 4
  2‚     # Pair this 0 or 1 with 2
    I    # Push the second input-month
     3@  # Check if it's >=3
       è # Use that to index into the pair
³        # Push the third input-day
 ¹       # Push the first input-year
  ²      # Push the second input-month
   23*   # Multiply the month by 23
      9÷ # Integer-divided by 9
Æ        # Reduce the entire stack by subtracting:
         #  [m%4<1,2][m>=3]-d-y-m*23//9
 7%      # Modulo-7, resulting in 6 to 0 for Sunday to Saturday

Original 36 24 bytes answer:

`UD3‹©12*+>₂*T÷®XαD4÷O7%

Try it online or verify all test cases.

Explanation:

05AB1E lacks any date builtins (except for the current year/month/day/etc.), so everything is done manually using Zeller's congruence, taken from this earlier 05AB1E answer of mine:

The formula to do this is:

$${\displaystyle h=\left(q+\left\lfloor{\frac{13(m+1)}{5}}\right\rfloor+K+\left\lfloor{\frac{K}{4}}\right\rfloor+\left\lfloor{\frac{J}{4}}\right\rfloor-2J\right){\bmod{7}}}$$

Where for the months March through December:

  • \$q\$ is the \$day\$ of the month ([1, 31])
  • \$m\$ is the 1-indexed \$month\$ ([3, 12])
  • \$K\$ is the year of the century (\$year \bmod 100\$)
  • \$J\$ is the 0-indexed century (\$\left\lfloor {\frac {year}{100}}\right\rfloor\$)

And for the months January and February:

  • \$q\$ is the \$day\$ of the month ([1, 31])
  • \$m\$ is the 1-indexed \$month + 12\$ ([13, 14])
  • \$K\$ is the year of the century for the previous year (\$(year - 1) \bmod 100\$)
  • \$J\$ is the 0-indexed century for the previous year (\$\left\lfloor {\frac {year-1}{100}}\right\rfloor\$)

Resulting in the day of the week \$h\$, where 0 = Saturday, 1 = Sunday, ..., 6 = Friday.

But, since the challenge states the year is guaranteed to be 2000-2002, we can simplify the formula to this instead:

$${\displaystyle h=\left(q+\left\lfloor{\frac{13(m+1)}{5}}\right\rfloor+K+\left\lfloor{\frac{K}{4}}\right\rfloor\right){\bmod{7}}}$$

Resulting in the day of the week \$h\$, where 0 = Friday, 1 = Saturday, ..., 6 = Thursday.

As for the actual program:

`           # Push the day, month, and year of the (implicit) input-triplet to the stack
 U          # Pop and save the year in variable `X`
  D         # Duplicate the month
   3‹       # Check if the month is below 3 (Jan. / Feb.),
            # resulting in 1 or 0 for truthy/falsey respectively
     ©      # Store this in variable `®` (without popping)
      12*   # Multiply it by 12 (either 0 or 12)
         +  # And add it to the month
            # This first part was to make Jan. / Feb. 13 and 14

>           # Month + 1
 ₂*         # Multiplied by 26
   T÷       # Integer-divided by 10
®           # Push month<3 from variable `®` again
 Xα         # Take the absolute difference with the year
D4÷         # mYear, integer-divided by 4
O           # Sum all values on the stack together
 7%         # And then take modulo-7 to complete the formula,
            # resulting in 0 to 6 for Friday to Thursday
            # (which is output implicitly as result)
\$\endgroup\$
9
  • 2
    \$\begingroup\$ As I understand it, you're only required to support dates in 2000-2002, which might let you simplify the code a bit. \$\endgroup\$
    – Neil
    Oct 5, 2022 at 17:37
  • 1
    \$\begingroup\$ Presumably this would be only 24 bytes if all the parts that aren't needed for 2000-2002 are removed...? (obviously the conversion to day names in the link is now wrong) \$\endgroup\$ Oct 9, 2022 at 10:38
  • 2
    \$\begingroup\$ In the new 22-byte version, if you use integer-divide-by-9, then I don't think you need the bitwise-negate step (I think...): you'll just map 6..0 to consecutive days instead of 0..6, which is fine. \$\endgroup\$ Oct 9, 2022 at 16:58
  • 1
    \$\begingroup\$ @Arnauld - That version comes-out particularly short in Nibbles: thank you! \$\endgroup\$ Oct 9, 2022 at 17:40
  • 1
    \$\begingroup\$ @Arnauld The current approach is actually shorter, since I can do 'reduce-by-subtraction' on the stack in a single byte. :) \$\endgroup\$ Oct 9, 2022 at 19:42
7
\$\begingroup\$

R, 30 27 bytes

-3 bytes thanks to naffetS

function(s)strftime(s,"%A")

Try it online!

3 bytes shorter than the alternate R solution.

The natural solution would be to use format(as.Date(s), "%A"), which converts s to the Date class then displays only the weekday. Luckily, the strftime is a wrapper for this, saving a few bytes.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Drat! Well done. \$\endgroup\$ Oct 5, 2022 at 14:38
  • \$\begingroup\$ function(s)strftime(s,"%A") \$\endgroup\$
    – naffetS
    May 26 at 0:34
  • \$\begingroup\$ @naffetS Nice, thanks! \$\endgroup\$ May 26 at 14:17
6
\$\begingroup\$

Red, 13 bytes

func[d][d/10]

Try it online!

Returns 1 to 7, Monday is 1

Red, 46 bytes

func[d][take/part system/locale/days/(d/10) 2]

Try it online!

Returns Mo Tu We Th Fr Sa Su

Red's date! datatype has weekday accessor that is also aliased by index 10. So for a date d we can write d/weekday or shorter d/10

\$\endgroup\$
5
\$\begingroup\$

JavaScript (ES6), 38 bytes

This is an attempt at solving the challenge without a built-in, using a formula optimized for 2000-2002.

Expects (year, month, day). Returns \$0\$ for Sunday, \$1\$ for Monday, ..., \$6\$ for Saturday.

(y,m,d)=>~((m<3?y%4<1:2)-d-y-23*m/9)%7

Try it online!

Commented

This is based on the following C code by Michael Keith and Tom Craver:

(d+=m<3?y--:y-2,23*m/9+d+4+y/4-y/100+y/400)%7

Wikipedia article

(y, m, d) =>    // y = year, m = month, d = day
~(              // take the ones' complement of:
  (             //   conditional offset:
    m < 3 ?     //     if this is January or February:
      y % 4 < 1 //       use 1 if this is 2000
                //       (which is a leap year)
                //       or 0 otherwise
    :           //     else:
      2         //       use 2
  )             //
  - d           //   subtract the non-conditional offset:
  - y           //     d + y + 23 * m / 9
  - 23 * m / 9  //
) % 7           // apply modulo 7
\$\endgroup\$
4
  • \$\begingroup\$ +1 for trying out without Built-ins, but not gonna be accepted because the shorter solution without built-ins is -2 bytes in 05AB1E \$\endgroup\$ Oct 7, 2022 at 8:55
  • \$\begingroup\$ @py3programmer The 05AB1E answer would be shorter if it was also optimized for 2000-2002. There's no way JS can compete with a golfing language. :-) \$\endgroup\$
    – Arnauld
    Oct 7, 2022 at 9:07
  • \$\begingroup\$ Eich's fault, not mine. \$\endgroup\$ Oct 7, 2022 at 9:14
  • \$\begingroup\$ @Arnauld It's optimized for 2000-2002 now. ;) But I have the feeling it might be shorter porting your top answer. 🤔 \$\endgroup\$ Oct 9, 2022 at 15:24
4
\$\begingroup\$

Bash, 14 13 bytes

date -d$1 +%u

Try it online!

Saved a byte thanks to Steffan!!!

Inputs the date as YYYY-MM-DD and returns \$1\$ for Monday, \$2\$ for Tuesday, up to \$7\$ for Sunday.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ You can remove the space between -d and $1. \$\endgroup\$
    – naffetS
    Oct 5, 2022 at 18:24
  • \$\begingroup\$ @Steffan Nice one - thanks! :D \$\endgroup\$
    – Noodle9
    Oct 5, 2022 at 18:55
4
\$\begingroup\$

JavaScript (Node.js), 16 6 bytes

Takes datetime object as input, per OP.

Takes date as YYYY-MM-DD and returns 0–6 for Thursday–Wednesday.

d=>d%7

Old solution with string input

s=>new Date(s)%7

Try it online!

\$\endgroup\$
4
\$\begingroup\$

Python 3, 49 bytes

lambda*t:date(*t).weekday()
from datetime import*

Try it online!

Represents mon-sun as 0-6

\$\endgroup\$
4
  • \$\begingroup\$ Is that 0–6 or 1–7? \$\endgroup\$
    – Adám
    Oct 6, 2022 at 7:21
  • \$\begingroup\$ @Adám [0,7) - but in all fairness I just made a typo \$\endgroup\$
    – Jitse
    Oct 6, 2022 at 7:54
  • \$\begingroup\$ Not sure if this is valid since it uses builtins \$\endgroup\$
    – mousetail
    Oct 6, 2022 at 7:57
  • \$\begingroup\$ It's valid, but it won't be considered for being accepted. \$\endgroup\$ Oct 7, 2022 at 7:24
4
\$\begingroup\$

Excel, 10 bytes

=MOD(A1,7)

Returns 0W/01/1900 where W is 06 for Saturday–Friday. Excel screenshot

\$\endgroup\$
7
  • 1
    \$\begingroup\$ @thejonymyster Thanks. Fixed. \$\endgroup\$
    – Adám
    Oct 6, 2022 at 6:36
  • \$\begingroup\$ W is Saturday-Friday (except for before 1900-03-01 when it is Sunday-Saturday as Excel has a bug and thinks 1900-02-29 was a leap day). \$\endgroup\$
    – MT0
    Oct 6, 2022 at 11:03
  • \$\begingroup\$ @MT0 Not sure what you're trying to say here, but yes, you're right. However, since mod-7 always gives a number between 0 and 6, corresponding to a date between 1899-12-31 (a.k.a 1900-01-00) and 1900-01-06, it'll never happen that W corresponds to Saturday–Friday. \$\endgroup\$
    – Adám
    Oct 6, 2022 at 13:38
  • \$\begingroup\$ Using Saturday's date =MOD(DATE(2022,10,8), 7) outputs 00/01/1900 so the initial 00 corresponds to Saturday (and not Sunday, like the answer states). \$\endgroup\$
    – MT0
    Oct 6, 2022 at 13:49
  • 1
    \$\begingroup\$ @MT0 Right, and since OP only requires that "it can calculate for years between 2000 and 2002", that bug doesn't matter. The phantom 29th Feb 1900 isn't a bug but a feature for compatibility with Lotus 1-2-3. And Lotus 1-2-3 was intentionally implemented using a simplified leap year calculation for code golf purposes. \$\endgroup\$
    – Adám
    Oct 6, 2022 at 13:57
4
\$\begingroup\$

Mathematica, 7 bytes

DayName

Mathematica (without DayName), 49 42 38 bytes

First@DateDifference[{1,1,1},#]~Mod~7&

View it on Wolfram Cloud!

Takes dates in MM/DD/YYYY format (will complain if the date happens to be parsable as DD/MM/YYYY, but it still outputs the correct answer). DayName returns the full name of the weekday. The other answer returns 0 for Monday, 1 for Tuesday, up to 6 for Sunday.

The non-DayName answer can probably still be golfed a decent amount, I'm pretty new to Mathematica.

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

APL(Dyalog Unicode), 7 bytes SBCS

Anonymous tacit prefix function taking date as YYYY MM DD.

7|1⎕DT⊂

Try it on APLgolf!

 enclose to make a scalar date

1⎕DT convert to Dyalog Day Number (days since 1899-12-31)

7| remainder when divided by 7 (gives 0–6 for Sunday–Saturday)

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

Factor, 11 bytes

day-of-week

Try it online!

Takes input as a timestamp. Outputs an integer 0-6 signifying Sunday-Saturday.

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

Nibbles, 21 20.5 16.5 15.5 bytes (31 nibbles)

Edit: -4 bytes thanks to Arnauld

%-+/*23@9+_$?-@2 2/%_3~7

Saturday is 0 ... Friday is 6.

Uses Arnauld's simplified approach.

%-+/*23@9+_$?-@2 2/%_3~7    
    *23@                     # month times 23
   /    9                    # integer-divided by 9 
  +                          # add this to 
         +_$                 # the year plus the day
 -                           # and subtract
            ?-@2             # if the month is ≤2
                 2           # 2
                             # otherwise
                   %_3       # year modulo 3
                  /   ~      # integer-divided by 2
%                      7     # finally, modulo 7

enter image description here

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

PowerShell, 16 bytes

%{date $_|% D*k}

Try it online!

Input comes from the pipeline. Straightforward:

%{date $_|% D*k}
%{             }  # % is an alias for ForEach-Object; the loop variable in the ScriptBlock "{}" is $_
  date $_         # pass the string as input to Get-Date, which will return a DateTime object
         |% D*k   # pipe the DateTime object to ForEach-Object, this time not with a ScriptBlock, but instead calls the member DayOfWeek
                  # Output is implicit

Disclaimer: This drops the Get- from Get-Date; if PS finds no other command with that name, it will try to add Get- and find the cmdlet Get-Date; don't use this in regular scripts, as the search for the command will slow it down.

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

Ruby, 22 21 bytes

Takes input as an array like [Y,M,D] and returns a number from 0 (Sunday) to 6 (Saturday).

-1 byte thanks to Dingus

->d{Time.gm(*d).wday}

Attempt This Online!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Time.gm saves a byte over Date.new (and doesn't need -rdate). \$\endgroup\$
    – Dingus
    Oct 5, 2022 at 23:02
  • \$\begingroup\$ @Dingus Nice. Thanks! \$\endgroup\$
    – Jordan
    Oct 6, 2022 at 0:05
2
\$\begingroup\$

MATL, 3 bytes

8XO

Input format is YYYY/MM/DD.

Try it online! Or verify all test cases.

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

Julia 1.0, 41 39 bytes

using Dates;!d=Dates.dayofweek(Date(d))

Try it online!

Saved 2 bytes thanks to Steffan!

Returns 1 for Monday, 2 for Tuesday, up to 7 for Sunday.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ Welcome to Code Golf! Nice answer. You can save a couple bytes by defining f as a unary operator instead: using Dates;!d=Dates.dayofweek(Date(d)) \$\endgroup\$
    – naffetS
    Oct 6, 2022 at 0:47
2
\$\begingroup\$

Vyxal, 29 21 bytes

4Ḋ2"?3≥i???23*9ḭWƒ-7%

Try it Online!

Port of 05AB1E.

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

JS, 23 13 bytes

Passed as string

s=>new Date(s).getDay()

Passed as object, per OP

d=>d.getDay()
\$\endgroup\$
1
\$\begingroup\$

Go, 96 85 bytes

import."time"
func f(d string)int{e,_:=Parse("02/01/2006",d);return int(e.Weekday())}

Attempt This Online!

Hoo ray for verbose builtins!

  • -11 bytes for returning an int (@Steffan)
\$\endgroup\$
2
  • \$\begingroup\$ You don't need the [:2] - any consistent 7 values are valid. \$\endgroup\$
    – naffetS
    Oct 5, 2022 at 18:18
  • \$\begingroup\$ It's 85 bytes to return an int: func f(d string)int{e,_:=Parse("02/01/2006",d);return int(e.Weekday())} \$\endgroup\$
    – naffetS
    Oct 5, 2022 at 18:23
1
\$\begingroup\$

Nim, 47 bytes

import times,sugar
x=>x.parse"ddMMyyyy".weekday

Try it online!

It takes the date in the format ddMMyyyy and prints the full name of the weekday.

\$\endgroup\$
1
\$\begingroup\$

PHP, 33 bytes

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

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ Welcome to Code Golf, and nice first answer! Be sure to check out our Tips for golfing in PHP page for ways you can golf your program. \$\endgroup\$
    – emanresu A
    Oct 6, 2022 at 6:09
  • 1
    \$\begingroup\$ If you don't mind using older versions of PHP (7.1 and older), you can save 2 bytes by removing the single quotes: <?=date(l,strtotime($argv[1]));. If you use the option -R, you can use the $argn variable instead of $argv[1] (php.net/manual/en/features.commandline.options.php). The final code would look like: <?=date(l,strtotime($argn)); - 5 bytes saved in total. \$\endgroup\$ Oct 6, 2022 at 9:11
1
\$\begingroup\$

APL(Dyalog Unicode) REPL, 0 bytes

Takes date as 7|1⎕DT⊂YYYY MM DD and gives 0–6 for Sunday–Saturday

Try it on TryAPL!

This abuses OP ruling that a valid input format can contain the code that solves the problem. For an explanation, see my other APL answer.

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

jq, 17 characters

strptime("%F")[6]

Input: YYYY-MM-DD
Output: 0 = Sunday .. 6 = Saturday

Sample run:

bash-5.1$ jq -R 'strptime("%F")[6]' <<< '2012-05-04'   # manatwork joined CGCC
5

Try it online! / Try all test cases online!

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

Rust + chrono, 58 21 bytes

chrono::Date::weekday

Playground

An expression that can be coerced to a fn(&Date<Utc>)->Weekday. It takes a Date object and returns Weekday, an enum with 7 possible values.

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

Java, 13 bytes

d->d.getDay()

A Function<java.util.Date, Integer>. Returns 0 for Sunday, 1 for Monday, ..., 6 for Saturday.

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

Japt, 4 bytes

Input as a string in the format yyyy-mm-dd (or any valid JavaScript date string), output as a 3 letter abbreviation.

3îÐU

Try it

3îÐU     :Implicit input of string U
3î       :Slice to length 3
  ÐU     :Construct date object from U

Note: This is locale/browser dependent. For the included test case, for example, the date object is expected to return Mon Nov 12 2001 00:00:00 GMT+0000 (Greenwich Mean Time).

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

Thunno 2 t, 22 bytes

4Ḋ2,$3®i⁶°¹23×9÷KrƲ-7%

Attempt This Online!

Port of Kevin Cruijssen's 05AB1E answer.

Explanation

                        # implicit input
4Ḋ                      # divisible by 4
  2,                    # pair with 2
    $                   # next input
     3®                 # greater than or equal to 3
       i                # indexing
        ⁶               # third input
         °              # first input
          ¹             # second input
           23×          # multiply by 23
              9÷        # floor divide by 9
                Kr      # push the stack
                  Ʋ     # cumulative reduce by:
                   -    #  subtraction
                    7%  # modulo 7
                        # implicit output of tail
\$\endgroup\$
0
\$\begingroup\$

Python 3, 69 bytes

lambda y,m,d:((d+((y+y//4)+(0x562ad0e6c0>>m*3&7)))-(m<3)*(y%4<1)+6)%7

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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