Revision 9aec6be5-d8e4-484b-bc15-0b0ad55baeb9 - Code Golf Stack Exchange

#[05AB1E](https://github.com/Adriandmen/05AB1E/wiki/Commands), <s>130</s> 128 [bytes](https://github.com/Adriandmen/05AB1E/wiki/Codepage)

 žežfžg)V0[YÁćU`D3‹12*+>13*5÷Xт%D4÷Xт÷©4÷®·()ćsO7%2@+Y`©4Ö®тÖ®т4*%_**UD2Qi28円X+ë31s<7%É-}‹iY¬>0ëY1¾ǝDÅsD12‹i>1ë1円Dǝ¤>2}}ǝVYI'.¡Q#

I'm out of my mind..

For the golfing language 05AB1E it doesn't matter at all whether the input is with `.` or `-`. However, 05AB1E doesn't have any builtins for Date objects or calculations. The only builtin regarding dates it has is today's year/month/day/hours/minutes/seconds/microseconds.

So because of that, almost all of the code you see are manual calculations to go to the next day, and calculating the day of the week.

[Try it online](https://tio.run/##yy9OTMpM/f//6L7Uo/vSju5L1wwziI483HikPTTBxfhRw05DIy1tO0NjLdPD2yMuNqm6mIDpw9sPrQSyDq07tF1D80h7sb@5qpGDdmQCSHTaoXVABWDSREs1Xksr1MUoMDPGyCJC@/BqY8NiG3PVw526tUCzMyMPrbEzOLw60vDQvuNzXQ63FrsYGoHE7QwPr44xdDk@99ASO6Pa2uNzwyI91fUOLQxU/v/f0EzP0EDPyMDQAgA) or [Try it online with an emulated self-specified date of 'today'](https://tio.run/##JYzNSsNAFIX3fYohEtImJMxPpSoSXGTjomgXLQ0G7EimGmgTyEyELgoqSPEF3GVRcCORboMbFzOFrH0FXySm7V3c@93DOSfh9C5itXadCUBBSAUDUQzEAwPTJJ1TAcLQ7vftRTNAJCDjDFAO6EywNKYiemSAC5qKKL4/hNtsns0aCA9vMgWGSEK6MDpnWtBqaQTZCNsYolPNsOW6HsEbXz1vV8OJR/6evhE2LRcR81iV498X3evuryrlZ0NyI8t2Z7viVz0dX1j@ZKe@y01j2O@uqd@a5tDDgyjAJ2NLFQTx856u3uxl0x358suFqvCR/KlyT71yD@Gd7iJVBMircvnh4uWyykf@peHI9eCorgl0IHEwxPAf).

###Explanation:

*Wall of text incoming.*

In general, the code follows the following pseudo-code:

 1 Date currentDate = today;
 2 Integer counter = 0;
 3 Start an infinite loop:
 4* If(currentDate is NOT a Saturday and currentDate is NOT a Sunday):
 5 Counter += 1;
 6* currentDate += 1; // Set currentDate to the next day in line
 7 If(currentDate == parsed input-string):
 8 Stop the infinite loop, and output the counter

1) `Date currentDate = today;` is this part of the 05AB1E program:

<!-- language-all: lang-python -->

 že # Push today's day
 žf # Push today's month
 žg # Push today's year
 ) # Wrap them into a single list
 V # And store this list in variable `Y`

<!-- language-all: none -->

2) `Integer counter = 0;` and 3) `Start an infinite loop:` are straight-forward in the 05AB1E program:

<!-- language-all: lang-python -->

 0 # Push 0 to the stack
 [ # Start an infinite loop

<!-- language-all: none -->

4) `If(currentDate is NOT a Saturday and currentDate is NOT a Sunday):` is the first hard part with manual calculations. Since 05AB1E has no Date builtins, we'll have to calculate the *Day of the Week* manually.

The general 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:

- \$q\$ is the day of the month
- \$m\$ is the month for March through December (`[3, 12]`), and the month + 12 for January and February (`1` becomes `13`; `2` becomes `14`)
- \$K\$ is the year of the century (\$year \bmod 100\$)
- \$J\$ is the 0-indexed century ( \$\left\lfloor {\frac {year}{100}}\right\rfloor\$)

Resulting in in the day of the week \$h\,ドル where 0 = Saturday, 1 = Sunday, ..., 6 = Friday. 
[Source: Zeller's congruence](https://en.wikipedia.org/wiki/Zeller%27s_congruence)

We can see this in this part of the 05AB1E program:

<!-- language-all: lang-python -->

 Y # Push variable `Y`
 Á # Rotate it once towards the right ([dd, MM, yyyy] becomes [yyyy, dd, MM])
 ć # Head extracted (pops the list, and pushes [dd, MM] and yyyy)
 U # Pop and save the year in variable `X`
 ` # Push the day and month to the stack
 D3‹ # 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
 
 # Now we do the actual Zeller's formula:
 > # Month + 1
 13* # Multiplied by 13
 5÷ # Integer-divided by 5
 Xт% # Year modulo-100
 D4÷ # Year modulo-100 integer-divided by 4
 Xт÷©4÷ # Year integer-divided by 100, and then integer-divided by 4
 ®·( # Year integer-divided by 100, doubled, and then made negative
 ) # Wrap the entire stack into a list
 ć # Extract the head (the counter variable that was also on the stack)
 s # Swap so the calculated values above are as list at the top
 O # Take the sum of this entire list
 7% # And then take modulo-7 to complete the formula,
 # resulting in 0 for Saturday, 1 for Sunday, and [2, 6] for [Monday, Friday]
 
 2@ # Check if the day is greater than or equal to 2 (so a working day)

<!-- language-all: none -->

5) `Counter += 1;` is straight-forward again:

<!-- language-all: lang-python -->

 # The >=2 check with `2@` results in either 1 for truthy and 0 for falsey
 + # So just adding it to the counter variable is enough

<!-- language-all: none -->

6) `currentDate += 1; // Set currentDate to the next day in line` is again more complex, because we have to do it manually. So this will be expanded to the following pseudo-code:

 a Integer isLeapYear = currentDate.year % 4 == 0 &&
 (currentDate.year % 100 == 0 & currentDate.year % 400 != 0);
 b Integer daysInCurrentMonth = currentDate.month == 2 ?
 c 28 + isLeapYear
 d :
 e 31 - (currentDate.month - 1) % 7 % 2;
 f If(currentDate.day < daysInCurrentMonth):
 g nextDate.day += 1;
 h Else:
 i nextDate.day = 1;
 j If(currentDate.month < 12):
 k nextDate.month += 1;
 l Else:
 m nextDate.month = 1;
 n nextDate.year += 1;

Sources: 
[Algorithm for determining if a year is a leap year.](http://www.dispersiondesign.com/articles/time/determining_leap_years) 
[Algorithm for determining the number of days in a month.](http://www.dispersiondesign.com/articles/time/number_of_days_in_a_month)

6a) `Integer isLeapYear = currentDate.year % 4 == 0 && (currentDate.year % 100 == 0 & currentDate.year % 400 != 0)` is done like this in the 05AB1E program:

<!-- language-all: lang-python -->

 Y # Push variable `Y`
 ` # Push the days, month and year to the stack
 © # Save the year in the register (without popping)
 4Ö # Check if the year is divisible by 4
 * # AND
 ®тÖ # Check if the year is divisible by 100
 * # And
 ®т4*%_ # Check if the year modulo-400 is 0
 U # Pop and save the result in variable `X`

<!-- language-all: none -->

6b) `currentDate.month == 2 ?` and 6c) `28 + isLeapYear` are done like this:

<!-- language-all: lang-python -->

 D # Duplicate the month that is now the top of the stack
 2Q # Check if it's equal to 2
 i # And if it is:
 \ # Remove the duplicated month from the top of the stack
 28X+ # Add 28 and variable `X` (the isLeapYear) together

<!-- language-all: none -->

6d) `:` and 6e) `31 - (currentDate.month - 1) % 7 % 2;` are done like this:

<!-- language-all: lang-python -->

 ë # Else:
 31 # Push 31
 s # Swap so the duplicated month is at the top of the stack again
 < # Month - 1
 7% # Modulo-7
 É # Is odd (shortcut for %2)
 - # Subtract it from the 31
 } # Close the if-else

<!-- language-all: none -->

6f) `If(currentDate.day < daysInCurrentMonth):` is done like this:

<!-- language-all: lang-python -->

 ‹ # Check if the day that is still on the stack is smaller than the value calculated
 i # And if it is:

<!-- language-all: none -->

6g) `nextDate.day += 1;` is done like this:

<!-- language-all: lang-python -->

 Y # Push variable `Y`
 ¬ # Push its head, the days (without popping the list `Y`)
 > # Day + 1
 0 # Push index 0
 
 # (This part is done after the if-else clauses to save bytes)
 }} # Close the if-else clauses
 ǝ # Insert the day + 1 at index 0 in the list `Y`
 V # Pop and store the updated list in variable `Y` again

<!-- language-all: none -->

6h) `Else:` and 6i) `nextDate.day = 1;` are then done like this:

<!-- language-all: lang-python -->

 ë # Else:
 Y # Push variable `Y`
 1 # Push a 1
 ¾ # Push index 0
 ǝ # Insert 1 at index 0 (days part) in the list `Y`

<!-- language-all: none -->

6j) `If(currentDate.month < 12):`:

<!-- language-all: lang-python -->

 D # Duplicate the list `Y`
 Ås # Pop and push its middle (the month)
 D12‹ # Check if the month is below 12
 i # And if it is:

<!-- language-all: none -->

6k) `nextDate.month += 1;`:

<!-- language-all: lang-python -->

 > # Month + 1
 1 # Push index 1
 
 # (This part is done after the if-else clauses to save bytes)
 }} # Close the if-else clauses
 ǝ # Insert the month + 1 at index 1 in the list `Y`
 V # Pop and store the updated list in variable `Y` again

<!-- language-all: none -->

6l) `Else:`, 6m) `nextDate.month = 1;` and 6n) `nextDate.year += 1;` are then done like this:

<!-- language-all: lang-python -->

 ë # Else:
 \ # Delete the top item on the stack (the duplicated month)
 1 # Push 1
 D # Push index 1
 ǝ # Insert 1 at index 1 (month part) in the list `Y`

 ¤ # Take the tail of `Y` (the year)
 > # Year + 1
 2 # Index 2

 # (This part is done after the if-else clauses to save bytes)
 }} # Close the if-else clauses
 ǝ # Insert the year + 1 at index 2 in the list `Y`
 V # Pop and store the updated list in variable `Y` again

<!-- language-all: none -->

And finally at 8) `If(currentDate == parsed input-string):` and 9) `Stop the infinite loop, and output the counter`:

<!-- language-all: lang-python -->

 Y # Push variable `Y`
 I # Push the input
 '.¡ # Split it on dots
 Q # Check if the two lists are equal
 # # And if they are equal: stop the infinite loop

<!-- language-all: none -->

AltStyle によって変換されたページ (->オリジナル) /