20
\$\begingroup\$

June 2020 is a month in which June 1st corresponds to Monday, June 2nd corresponds to Tuesday, ... June 7th corresponds to Sunday. For reference, here's the cal of June 2020.

      June 2020     
Su Mo Tu We Th Fr Sa
    1  2  3  4  5  6
 7  8  9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30            

Given a year and a month in the format [year, month], output two distinct values that tell whether this month starts on a Monday.

Test cases

[2020,6] -> True
[2021,2] -> True
[1929,4] -> True

[1969,1] -> False
[1997,5] -> False
[2060,1] -> False

Specification

  • The input can be in any format you prefer for your answer, e.g. numeric list, numeric tuple, etc. It doesn't have to be taken in this rigid format (it's JSON by the way).
  • However, making the input a Date object is a loophole here. You shouldn't make the input a Date object.
  • The month in the input doesn't have to be 1-indexed - it can also be 0-indexed.
  • You need to support all years after 1582 (the start of the Proleptic Gregorian calendar), up to the year 9999.
\$\endgroup\$
13
  • 8
    \$\begingroup\$ Is this asking, in less jargony terms, "does the given month start on a Monday"? The question is kind of hard to parse \$\endgroup\$ Jun 14, 2020 at 1:20
  • 18
    \$\begingroup\$ I suggest scrapping the entire challenge text and replacing it with: Given a year and a month, answer whether the given month begins with a Monday in the given year. \$\endgroup\$
    – Adám
    Jun 14, 2020 at 1:49
  • 2
    \$\begingroup\$ @MitchellSpector Unless anything specific is stated, you can assume that default I/O rules apply. (And the format used happens to be JSON, a very well-supported standard.) \$\endgroup\$
    – Adám
    Jun 14, 2020 at 2:15
  • 2
    \$\begingroup\$ I asked because the challenge specifically says "in the format [year, month]". That implies to me a rigid input format (how else would a rigid input format be expressed?). I agree with what I think is your implication that the challenge would be better with the usual default I/O rules. I think OP should clarify this. @Adám \$\endgroup\$ Jun 14, 2020 at 2:18
  • 4
    \$\begingroup\$ How large a year range do we have to support? For instance, certain hundred years skip the leap day, and year -1 coming directly before year 1 doesn't work well with some number types. \$\endgroup\$ Jun 14, 2020 at 12:22

35 Answers 35

15
\$\begingroup\$

Excel, 44 34 23 19 18 bytes

=2=MOD(A3&"-"&A2,7

-11 thanks to Adam and -4 thanks to Shazback

-1 thanks to this

Original Answer

=(TEXT(DATE(A2,A3,1),"ddd")="Mon")

Ensure that the year is placed in cell A2 and the month in A3.

:( Crossed out 44 is still 44.

\$\endgroup\$
7
  • \$\begingroup\$ =2=MOD(DATE(A2,A3,1),7) \$\endgroup\$
    – Adám
    Jun 14, 2020 at 2:22
  • \$\begingroup\$ You removed the final closing parenthesis. While I'm not to comment on the validity of that, what you have now is only 22 bytes. \$\endgroup\$
    – Adám
    Jun 14, 2020 at 2:43
  • 1
    \$\begingroup\$ Doesn't Google Sheets auto-close parentheses? \$\endgroup\$
    – Shaggy
    Jun 14, 2020 at 8:24
  • 4
    \$\begingroup\$ 1 byte can be saved by abusing the Date function's default value: =1=mod(date(A2,A3,),7) \$\endgroup\$
    – Shazback
    Jun 15, 2020 at 10:45
  • 1
    \$\begingroup\$ 24 bytes - but quite readable for a golf: =WEEKDAY(DATE(A2,A3,))=1 \$\endgroup\$
    – David258
    Jun 15, 2020 at 15:14
14
\$\begingroup\$

Ruby, 26 24 bytes

->d{Time.gm(*d).monday?}

Try it online!

You'll never guess what this does.

Edit: -2 bytes from Dingus.

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

Bash + GNU utilities, 25 22 19 bytes

date -d$1-1|grep ^M

Try it online!

Or verify the test cases online.

The input is passed as an argument in the format year-month, and the output is the exit code (0 for truthy, 1 for falsey, as usual).

\$\endgroup\$
4
  • 2
    \$\begingroup\$ It assumes being run on an english locale. \$\endgroup\$
    – Amessihel
    Jun 16, 2020 at 0:25
  • \$\begingroup\$ @Amessihel That's true. Of course, the question was in English, and TIO doesn't even seem to have any non-English locales available. \$\endgroup\$ Jun 16, 2020 at 1:16
  • \$\begingroup\$ date -d$1-1 +%u would be more universal and has 15 bytes, but will print numbers 1-7, which is not what OP requested. \$\endgroup\$
    – pLumo
    Jun 17, 2020 at 7:03
  • \$\begingroup\$ @pLumo Yes -- in fact, if you check the edit history, my first version worked that way: date +%u -d$1-$2-1|grep 1 was the code. But that's 25 bytes, including the grep at the end to check for the numerical code for Monday, so that it meets OP's specs. codegolf.stackexchange.com/revisions/206071/1 (I could take off 3 bytes with the more liberal input criteria OP provided in response to a question, using $1 instead of $1-$2, but that would still only get down to 22 bytes.) \$\endgroup\$ Jun 17, 2020 at 16:24
9
\$\begingroup\$

JavaScript (ES61),  33 26  25 bytes

1: This works in Chrome, Node and Edge Chromium

Saved 7 bytes thanks to @Shaggy
Saved 1 byte thanks to @l4m2

Using a built-in. Takes input as ([year, month]).

a=>/^M/.test(new Date(a))

Try it online!

How?

Converting the input to a Date object

The Date() constructor expects either:

Date(year, month [ , date [ , hours [ , minutes [ , seconds [ , ms ] ] ] ] ])

or:

Date(value)

In the first syntax, month must be 0-indexed.

In the second syntax, value is coerced to a string (unless it's undefined or it's an object) and parsed as such. Therefore, a 1-indexed month is expected in that case.

According to the ECMAScript specification:

The function first attempts to parse the format of the String according to the rules (including extended years) called out in Date Time String Format (20.3.1.15). If the String does not conform to that format the function may fall back to any implementation-specific heuristics or implementation-specific date formats.

So [2020,6] is turned into "2020,6" and parsed using implementation-specific heuristics which happen to work in V8-based engines when a comma is used as a separator. This also works with several other symbols.

Regular expression

When passed as the argument of /^M/.test(), the Date object is implicitly converted into a string in the following format:

"DDD MMM 01 YYYY 00:00:00 GMT[...]"

where:

  • DDD is the 3-letter abbreviation of the day of the week
  • MMM is the 3-letter abbreviation of the month
  • YYYY is the year in numerical format

Therefore, the string begins with a "M" iff the day of the week is Monday.


JavaScript (ES6),  62 61  60 bytes

Using a formula. Takes input as (year)(month), where month is 0-indexed.

y=>m=>(y-=m<2,y+=(y&~3)-3*~~(y/100)>>2)%7=='045204263153'[m]

Try it online!

\$\endgroup\$
9
  • \$\begingroup\$ 26 bytes \$\endgroup\$
    – Shaggy
    Jun 14, 2020 at 8:14
  • \$\begingroup\$ @Shaggy Nice. I don't think I've ever seen this trick before. I guess the Date constructor basically accepts any separator between the numbers. \$\endgroup\$
    – Arnauld
    Jun 14, 2020 at 8:28
  • \$\begingroup\$ The strangest part of it to me is that the month is now 1-indexed. \$\endgroup\$
    – Shaggy
    Jun 14, 2020 at 9:19
  • \$\begingroup\$ @Shaggy I've added an explanation. Please let me know if you think something is inaccurate. \$\endgroup\$
    – Arnauld
    Jun 14, 2020 at 10:00
  • 1
    \$\begingroup\$ 25 \$\endgroup\$
    – l4m2
    Jun 15, 2020 at 8:26
7
\$\begingroup\$

APL (Dyalog Unicode) 18.0, 9 bytes (SBCS)

Anonymous tacit prefix function.

1=7|1⎕DT⊂

Try it online! (uses a model, ∆DT, instead of ⎕DT so it can run using TIO's current version)

 enclose the argument (because we need the date to be a scalar)

1⎕DT convert Date-Time to days since 1899-12-31 (this will "pad" the date to the first of the month)

7| division remainder when divided by 7

1= does one equal that?

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

Wolfram Language 36 bytes

DayName@DateObject@{#,#2,1}==Monday&

examples

Naming the function f, to save space and increase clarity.

f = DayName@DateObject@{#, #2, 1} == Monday &
f[2020, 6]
f[2021, 2]
f[1929, 4]
f[1969, 1]
f[1997, 5]
f[2060, 1]

(*True*)
(*True*)
(*True*)
(*False*)
(*False*)
(*False*)
\$\endgroup\$
6
\$\begingroup\$

Red, 33 bytes

func[b][1 = pick(to now b)+ 1 10]

Try it online!

The argument bis a block containing the year and the month. now is function returning the current date and time; to now b converts the input to a date! datatype. The odd thing is that currently Red assigns the missing data (the day of month) 0 by default, but Red being 1-indexed, thus calculates the last day of the previos month instead of the first day of the given month:

to now [2020 6] gives 31-May-2020

That's why I add 1 to the resulting date. date! has among its path accessors /weekday, wich can be queried using indexing instead - 10 (tenth item). Too bad I can't use direct indexing using paths /10, because it only works on words (variables) and not on literal / unnamed data. That's why I use pickdate 10.

Finally I check if the weekday is 1 (for Monday).

\$\endgroup\$
6
\$\begingroup\$

T-SQL, 47 bytes

SELECT 1/datepart(w,datefromparts(y,m,7))FROM i

(10 bytes saved thanks to @t-clausen.dk)

Assumes the input is in a table i with two columns, y and m. It assumes Sunday is set as the first day of week, which is the default setting. Outputs 1 if the month starts on a Monday, 0 otherwise.

datepart(w,datefromparts(y,m,7)), the day of week of the seventh day of the month returns 1 (=Sunday) if the month starts on a Monday, and a higher number otherwise. Since it's an integer, the division is rounded down to zero in the latter case.

Demo

\$\endgroup\$
4
  • \$\begingroup\$ nice first answer. I hope to see more SQL answers. This will not work on all servers. It depends on the datefirst setting. SET datefirst 7 would ensure it works \$\endgroup\$ Jun 15, 2020 at 8:06
  • \$\begingroup\$ you can save a few bytes: 1/datepart(w,datefromparts(y,m,7)) \$\endgroup\$ Jun 15, 2020 at 8:33
  • \$\begingroup\$ Thanks, that's a nice trick. \$\endgroup\$
    – Glorfindel
    Jun 15, 2020 at 8:51
  • \$\begingroup\$ Sunday is the default setting for some languages. I know Germany, Denmark, Norway. Sweden and alot of other countries uses different defaults. So you can't release this code for production - but this doesn't matter for Codegolf, as long as your Demo works \$\endgroup\$ Jun 15, 2020 at 18:09
6
\$\begingroup\$

05AB1E, 36 bytes

Ð3‹12*+>₂*T÷s3‹Xα©т%D4÷®т÷©4÷®·(O7%Θ

Here we go again. 05AB1E has no date builtins, so everything is done manually. This solution is a derivative of my answer here.

Takes both inputs separated, the \$month\$ as first input and \$year\$ as second.

Try it online or verify all test cases.

Explanation:

The general formula to calculate the Day of the Week manually 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 in the day of the week \$h\$, where 0 = Saturday, 1 = Sunday, ..., 6 = Friday.
Source: Zeller's congruence

Since we only care about \$q=1\$, we can use that to golf 2 bytes. With the formula above, the result would be \$2\$ for Mondays (and thus requiring a leading $ to push both 1 AND the input-month; as well as a trailing 2Q to check if the result equal 2). But if we remove the \$q+\$ part, the result would be \$1\$ for Mondays (in which case we can use the implicit input-month, removing the $; and also use the ==1 builtin Θ instead of 2Q).

Ð             # Triplicate the (implicit) input-month
 3‹           # Check if the month is below 3 (Jan. / Feb.),
              # resulting in 1 or 0 for truthy/falsey respectively
   12*        # Multiply this 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
s3‹           # Check if the month is below 3 again (resulting in 1 / 0)
   Iα         # Take the absolute difference with the second input-year
     ©        # Store this potentially modified year in the register
      т%      # mYear modulo-100
D4÷           # mYear modulo-100, integer-divided by 4
®т÷©4÷        # mYear integer-divided by 100, and then integer-divided by 4
®·(           # mYear integer-divided by 100, doubled, and then made negative
O             # Take the sum of all values on the stack
 7%           # And then take modulo-7 to complete the formula,
              # resulting in 0 for Sunday, and [1, 6] for [Monday, Saturday]

Θ             # Check if this is equal to 1 (thus a Monday)
              # (after which the result is output implicitly)

Note that I've also used \$\left\lfloor{\frac{26(m+1)}{10}}\right\rfloor\$ instead of \$\left\lfloor{\frac{13(m+1)}{5}}\right\rfloor\$, since 05AB1E has a 1-byte builtin for both 26 and 10 ( and T respectively), saving a byte on the 13.

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

Japt -!, 6 5 bytes

ÓÐN e

Try it

ÓÐN e     :Implicit input of integers U=y and V=m
 Ð        :Create date object from
  N       :  The array of inputs [U,V] with the date defaulting to the 1st
    e     :0-indexed day of the week
Ó         :Decrement
          :Implicit output of Boolean negation
\$\endgroup\$
2
  • \$\begingroup\$ Looks like our "Try it" link shows that your solution does not produce the correct results. \$\endgroup\$ Jun 17, 2020 at 5:32
  • \$\begingroup\$ Depends on your locale, @Thomas. \$\endgroup\$
    – Shaggy
    Jun 18, 2020 at 13:57
5
\$\begingroup\$

Python 2, 56 bytes

lambda y,m:date(y,m,1).weekday()<1
from datetime import*

Try it online!

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

Julia 1.0, 39 bytes

using Dates
x*y=dayofweek(Date(x,y))==1

Try it online!

I am posting this seperate from my other answer, since it doesn't use the point-free style, and thus doesn't have the cool side-benifits of also working for year only etc. But it is shorter

\$\endgroup\$
1
  • 1
    \$\begingroup\$ save one byte by replacing ==1 with <2 \$\endgroup\$
    – MarcMush
    Oct 5, 2021 at 15:00
4
\$\begingroup\$

C (gcc), 61 60 59 bytes

Saved a byte thanks to ceilingcat!!!
Saved a byte thanks to nununoisy!!!

f(y,m){y-=m<2;m=(y+y/4-y/100+y/400+"bed=pen+fad."[m])%7<1;}

Try it online!

Straight-up calculation that uses 0-based months.

\$\endgroup\$
2
  • \$\begingroup\$ 59 bytes if you use 0-indexed months: Try it online! \$\endgroup\$
    – nununoisy
    Jun 15, 2020 at 7:22
  • \$\begingroup\$ @nununoisy Yes of course, was using a byte up in that string just to make it 1-based. Nice one = thank! :D \$\endgroup\$
    – Noodle9
    Jun 15, 2020 at 10:06
4
\$\begingroup\$

Python 3.8 (pre-release), 53 bytes

lambda x:date(*x,1).weekday()<1
from datetime import*

Try it online!

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

Bash + Standard Unix Tools, 17 bytes

cal $1|grep ' 6$'
  • Input like "06 2020".
  • Exit Code is 0 if first day of month is Monday and 1 if not.

Try it online!

In some implementations, additional two bytes are necessary:

 cal $1|grep ' 6 *$'
\$\endgroup\$
3
\$\begingroup\$

Perl 5 -MTime::Local -pa, 38 33 bytes

Shaved 5 bytes with help from @DomHastings

$_=(gmtime timegm 0,0,0,1,@F)=~Mo

Try it online!

Input is space separated: 0-indexed month followed by year.

\$\endgroup\$
1
  • \$\begingroup\$ Nice, I wasn't getting anything competitive with core functions... You can save a few bytes dropping the / around the regex and using @F instead of <>,$_ too: Try it online! \$\endgroup\$ Jun 15, 2020 at 16:02
3
\$\begingroup\$

PowerShell, 28 21 bytes

(d $i -U %A)-like'M*'

Try it online!

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

Java (JDK), 35 bytes

m->{m.set(5,1);return m.get(7)==2;}

Try it online!

Explanation

The input is taken as a java.util.Calendar. First we modify the calendar to force the first of the month, then we check if that day of week is a Monday.

m -> {
  m.set(Calendar.DAY_OF_MONTH, 1);    // DAY_OF_MONTH is the constant 5
  return m.get(Calendar.DAY_OF_WEEK)  // DAY_OF_WEEK is the constant 7
    == Calendar.MONDAY                // MONDAY is the constant 2. Don't ask why, no one knows.
}
\$\endgroup\$
2
\$\begingroup\$

Retina 0.8.2, 108 bytes

\d+
$*
^(11? )1
12$*1$1
\G1
13$*
(1+)\1{4}1{27,} (?=(1*)\2{399})(?=(1*)\3{3})(1*)(?=\4{99})
$1$2$3
^(1{7})*$

Try it online! Link includes speedup ^ so that the included test cases complete within TIO's time limit. Takes 1-indexed month first, then the year. Explanation:

\d+
$*

Convert to unary.

^(11? )1
12$*1$1

If the month is January or February, then add 12 and subtract 1 from the year.

\G1
13$*

Multiply the month by 13, which begins a form of Zeller's congruence.

(1+)\1{4}1{27,} (?=(1*)\2{399})(?=(1*)\3{3})(1*)(?=\4{99})
$1$2$3

The month is integer divided by 5, but with 27 subtracted, which allows the calculation to result in Monday = 0. The year is separately divided by both 400 and 4, after which 1% of the year is skipped thus effectively subtracting it. The month calculation, y/400 and y/4 are then added to the remaining (y-y/100). Note that Retina will attempt to match this expression more than once but will always fail because there is only one space in the input. However, these attempts make it very slow, so to optimise this the TIO link includes a leading ^. The code will work without it eventually though.

^(1{7})*$

Test whether the result is a multiple of 7.

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

Julia 41 bytes

(37 characters)

using Dates
isequal(1)∘dayofweek∘Date

It's fairly rare to find a code-golf that can be answered in point-free style in Julia. An interesting side effect of this, is that if you give this just 1 input it will tell you if the year starts with a Monday. And if you give it 3 inputs it will tell you if a given day is a Monday.

\$\endgroup\$
1
  • \$\begingroup\$ save 5 bytes by replacing isequal(1) with ==(1), and an additional byte with <(2) (requires Julia 1.2) \$\endgroup\$
    – MarcMush
    Oct 5, 2021 at 15:01
2
\$\begingroup\$

R, 39 bytes

strftime(paste0(scan(,''),'-1'),'%u')<2

Try it online!

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

PHP 7.4, 43 bytes

This code creates an anonymous function where you pass the month and year, returning true for monday, and false if the 1st day it isn't on a monday.

fn($Y,$M)=>!~-date(N,strtotime("$Y-$M-1"));

You can try this on: http://sandbox.onlinephpfunctions.com/code/5bf01ff098ef40b4b45bbc82e3b13a5e1b83f8d1


An alternative solution could be just this (40 bytes):

fn($Y,$M)=>date(N,strtotime("$Y-$M-1"));

Which returns the week day, where 1 is monday, 2 is tuesday ....

I don't think this is in the spirit of the question.

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

Python 3.8, 80 bytes

from calendar import Calendar as C
f=lambda x:C().monthdayscalendar(*x)[0][0]==1

Try it online!

\$\endgroup\$
1
  • 7
    \$\begingroup\$ This can be shorter with from calendar import*. \$\endgroup\$
    – ovs
    Jun 15, 2020 at 8:04
2
\$\begingroup\$

T-SQL, 43 bytes

PRINT datediff(d,0,concat(@+@y*100,14))%7/6

the expression

datediff(d,0,concat(@+@y*100,14))%7

will return 0-6. 6 represent Monday - this is divided by 6(rounding off)

Mondays returns 1, other weekdays returns 0

Try it online

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

brainfuck, 582 bytes

->+++[[>]>,>++++++[<-------->-]<[<++++++++++>-],>++++++[<-------->-]<[<+>-]+[-<+]->-]>>>[->>>>+>+<<<<<]>>>>[<<<<+>>>>-]<+>>>+++<+>+<[->-[>]<<]<[-]<[-<<<<->>>]>[-]>[-]>[-]>[-]>[-]+++>++>+++++>>+++>+++++>+>++++>++++++>++>+++++[-<+]->>>>[>>+>+<<<-]>>[>>>[-<<<<+>>>>]<<[->+<]<[->+<]>-]>>>[-<+<<+>>>]<<<[->>>+<<<]>[[-<+>]>[-<+>]<<<<[->>>>+<<<<]>>-]>>++++++++++[<+++++++>-]<<<<<<<[>>+>>>>--<<<<<<-]>>[-[->>+<]>[<]<]>>[-[->>+<]>[<]<]<<<[->+>>>>+<<<<<]>[-[->>+<]>[<]<]>>[-[->>+<]>[<]<]>>[-<<<<<<<+>>>>>>>]<<<<<<+++++++<<+>[>->+<[>]>[<+>-]<<[<]>-]>[-]+>[[-]<->]<[->+<]>>++++++++[<++++++>-]<.

Try it online!

Definitely not the shortest program here, this was more to see if it was possible to do. Expects input in the form of YYYYMM - the month needs to be 1-indexed and 2 characters wide. Outputs 1 if the month starts on Monday, 0 otherwise. This could be shortened by 21 bytes if the output was not ASCII.

Ungolfed:

-> reference

+++[                     input 3 sets of 2 numbers
 [>]                     find next zero
 >,>++++++[<-------->-]< input number and sub 48 ascii
 [<++++++++++>-]         mul by 10
 ,>++++++[<-------->-]   input next number and sub 48
 <[<+>-]                 copy to previous cell
 +[-<+]-                 move back to reference
 >-                      dec counter
]                        end input

>>>
[->>>>+>+<<<<<]       copy the month variable for comparison
>>>>[<<<<+>>>>-]<+>>>+++<+>+<[->-[>]<<]
<[-]<[-<              if month is less than 3
 <<<->>>              decrement the year
]>[-]>[-]>[-]>[-]>[-] clear out comparison cells to store lookup table


0 3   2  5    0 3   5     1 4    6      2  4
  +++>++>+++++>>+++>+++++>+>++++>++++++>++>++++ lookup table
+[-<+]- move back to reference
>>>>    move to month

[>>+>+<<<-]
>>[>>>[-<<<<+>>>>]<<[->+<]<[->+<]>-] access lookup table for month
>>>[-<+<<+>>>]<<<[->>>+<<<]>
[[-<+>]>[-<+>]<<<<[->>>>+<<<<]>>-]   copy table value to result
>>++++++++++[<+++++++>-]<<<<<<<      add 70 to result to prevent wrap

[>>+>>>>--<<<<<<-]
>>[-[->>+<]>[<]<]
>>[-[->>+<]>[<]<] add century div by 4

<<<[->+>>>>+<<<<<]> add year
[-[->>+<]>[<]<]
>>[-[->>+<]>[<]<]>> add year div by 4

[-<<<<<<<+>>>>>>>]                           set up modulo
<<<<<<+++++++<<+>[>->+<[>]>[<+>-]<<[<]>-]    all modulo 7
>[-]+>[[-]<->]<[->+<]>>++++++++[<++++++>-]<. display result
\$\endgroup\$
2
\$\begingroup\$

Befunge-93, 81 78 bytes

&&:2`!#v_2->267+**2-55+/\:"d"/02-*\:"d"%\:"d"%4/\"d"/4/++++7%!.@
-1\++55<   ^\

Try it online!

How does it work?

This is based on a formula which gives the day of the week given a date:

W = (k + floor(2.6m - 0.2) - 2C + Y + floor(Y/4) + floor(C/4)) mod 7

where

  • k is the day of month,
  • m is the month of the year, if years start with March (so Mar = 1, Apr = 2, ..., Dec = 10, Jan = 11, Feb = 12).
  • C is the century of the March adjusted year (so year = year - 1 in January and February).
  • Y is the year in the century (March adjusted).
  • W is the weekday, (Sun = 0, ..., Sat = 6).

We will be calculating

W' = floor((26m - 2)/10) - 2C + Y + floor(Y/4) + floor(C/4)) mod 7

the month will start with a Monday, iff W' == 0.

Breaking down the program gives us:

&&              Reads year and month


  :2`!#v_2->    If the month is January or February, subtract 1 from
-1\++55<   ^\   the year, and add 10 to the month; else, subtract
                2 from the month. (Years start in March).


267+**2-55+/    Calculate (2.6 * month - 0.2).

\:"d"/02-*      -2 * Century (= int (year / 100))

\:"d"%          Year in century (year % 100)

\:"d"%4/        4 year leap year cycle adjustment (int ((year % 100) / 4))

\"d"/4/         400 year leap year cycle adjustment
                (int (int (year / 100) / 4))

++++            Sum them all

7%              Mod 7.

!.@             Negate the result and print it -- if 0 (hence, first
                day of the month is a Monday), then 1, else (not a    
                Monday) 0.

Edit: Saved three bytes.

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

q, 33 32 bytes

accepting the inputs as strings:

{2=mod["d"$"M"$x,".",-2#"0",y]7}

explanation

                     -2#"0",y    /append "0" to 2nd input and take last 2 chars from result
               x,".",            /join by "."
           "M"$                  /tok, convert string to month type
       "d"$                      /cast to date type - returns 1st of month
   mod[                      ]7  /date mod 7, 0->sat,1->sun,2->mon,etc
 2=                              /check if equal 2
            

run like:

q){2=mod["d"$"M"$x,".",-2#"0",y]7}["1929";"4"]
1b
\$\endgroup\$
2
\$\begingroup\$

Factor, 20 bytes

[ 1 <date> monday? ]

Try it online!

  • 1 <date> Create a timestamp object from the given year, month, and using 1 as the day.
  • monday? Is it Monday? A builtin from the calendar vocabulary.
\$\endgroup\$
2
\$\begingroup\$

TI-Basic, 15 bytes

2=dayOfWk(Ans(1),Ans(2),1

Input is taken from Ans as a list. Output is stored in Ans and is displayed. Assumes that the time and date are set correctly before the program is run. Outputs 1 if the month starts on a Monday and 0 if it does not. Only works on TI-84+/SE.

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

jq, 50 bytes

.+[1]+(now|gmtime[3:8])|mktime|strftime("%w")=="1"

Try it online!

Not that short, but it's different enough that I thought it might be interesting enough to post...

It expects a year and a 0-indexed month as a list, meaning [2021,3] for April, 2021.

.+[1]+(               )                            - append "day 1" to input
       now|gmtime[3:8]                             - curr time breakout, drop Y/m/d fields
                       |mktime                     - convert to epoch time
                              |strftime("%w")=="1" - compare "day of week" to Monday
\$\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.