Introduction
In a standard* (e.g. not 2020) tax year, estimated payments are due quarterly according to the schedule outlined in Publication 505.
| Payment Period | Due Date |
|---|---|
| January 1 – March 31 | April 15 |
| April 1 – May 31 | June 15 |
| June 1 – August 31 | September 15 |
| September 1 – December 31 | January 15 |
* Saturday, Sunday, holiday rule, fiscal year taxpayers, and January payment exceptions can be ignored for the purpose of this question; use the standard table provided.
Challenge
Input:
A date/timestamp, either provided as input to your solution (function parameter or stdin) as a string (at a minimum specifying a specific year, month, an day of month) or native Date object (or equivalent) or the current (dynamically updated) date/time based on the clock of the executing machine.
Output:
The most specific payment period, one of Q1, Q2, Q3, or Q4 as a string, either printed to stdout/console or programmatically returned from the function, to which a timely payment made on the input date would be applied.
| Input | Output |
|---|---|
| January 16 - April 15 | Q1 |
| April 16 - June 15 | Q2 |
| June 16 - September 15 | Q3 |
| September 16 - January 15 | Q4 |
A day shall commence at 00:00 (midnight) and cover time periods up to but not including 00:00 (midnight) of the following day. The last moment of a given day, to a ms granularity is 23:59:59.999.
-
\$\begingroup\$ can it take day of the year, as in the last day of the year is day 365? \$\endgroup\$smarnav– smarnav2021年06月17日 00:26:33 +00:00Commented Jun 17, 2021 at 0:26
-
2\$\begingroup\$ Publication 505 is 48 pages. Mind stating which page you got your table from so I don't have to pour over 48 pages to find the specific reference you're using for your tables? \$\endgroup\$Thomas Ward– Thomas Ward2021年06月17日 00:53:12 +00:00Commented Jun 17, 2021 at 0:53
-
1\$\begingroup\$ ALSO, this is for estimated taxes not general tax payments. Update your question to be specific about that, because estimated taxes don't actually fall within that fiscal quarter. I'm not sure you can golf this based on that. \$\endgroup\$Thomas Ward– Thomas Ward2021年06月17日 00:55:08 +00:00Commented Jun 17, 2021 at 0:55
-
3\$\begingroup\$ @ThomasWard Page 26, but the relevant bit is copied into the problem. It's an exercise in golfing, not tax code, hence ignoring the edge cases. The publication is just for flavor :) \$\endgroup\$arcyqwerty– arcyqwerty2021年06月17日 02:59:00 +00:00Commented Jun 17, 2021 at 2:59
-
1\$\begingroup\$ Coule we take three arguments day, month and year? \$\endgroup\$user100690– user1006902021年06月17日 05:18:15 +00:00Commented Jun 17, 2021 at 5:18
5 Answers 5
JavaScript (ES6), 53 bytes
Expects a string in "DD-MM-YYYY" format.
s=>"Q"+"4243131"[[d,m]=s.split`-`,(m*24|d>15)*9%23%7]
39 bytes
If we can just take the month and the day.
m=>d=>"Q"+"4243131"[(m*24|d>15)*9%23%7]
35 bytes
As suggested by @ovs, using a larger lookup table with a much simpler formula is actually shorter.
m=>d=>"Q"+"_4111223334444"[m+=d>15]
-
1\$\begingroup\$ Can you explain the thought process that goes around making formulas like these? Is it mainly brute force? what is the starting point? I am always amazed by how people find "magic formulas" for things \$\endgroup\$user100752– user1007522021年06月17日 08:07:38 +00:00Commented Jun 17, 2021 at 8:07
-
1\$\begingroup\$ @EliteDaMyth That's mainly brute force on several hard-coded templates and with hard-coded ranges for each variable. I was actually pretty sure that a more standard formula would work for that one, but I couldn't find any that was shorter than the hash. \$\endgroup\$Arnauld– Arnauld2021年06月17日 10:18:10 +00:00Commented Jun 17, 2021 at 10:18
-
1
-
\$\begingroup\$ @ovs I think that works indeed. \$\endgroup\$Arnauld– Arnauld2021年06月17日 13:53:35 +00:00Commented Jun 17, 2021 at 13:53
Retina 0.8.2, (削除) 72 (削除ここまで) 63 bytes
\d+
$*
1+-(1{1,5}(1)*)-1{1,15}(1)*
113ドル2ドル1ドル
(111)*1+
Q$#1
0|5
4
Try it online! Link includes test cases. Takes input in YYYY-MM-DD format. Explanation:
\d+
$*
Convert to unary.
1+-(1{1,5}(1)*)-1{1,15}(1)*
113ドル2ドル1ドル
Add 2, 3 or 4 to the month depending on whether the month is greater than 5 or the day is greater than 15 or not.
(111)*1+
Q$#1
Subtract 1 from the month, then integer divide it by 3 and prefix Q to the result. (This is to avoid zero width matches.)
0|5
4
Change Q0 and Q5 to Q4.
-
\$\begingroup\$ @Arnauld Bah, I'd totally misread the table... \$\endgroup\$Neil– Neil2021年06月17日 11:42:45 +00:00Commented Jun 17, 2021 at 11:42
R, (削除) 65 (削除ここまで) 62 bytes
function(d)paste0("Q",1+sum(c(3,5,8)<el(format(d-15,"%m"):1)))
Expects input in R's native Date class. Subtract 15 days from the input, extract the month (as a string such as "04"), and convert to numeric with el(...:1) (see this tip). We then get the result by adding 1 for each of the values 3, 5, and 8 which are smaller than the result.
-
\$\begingroup\$ I like the lexicographic comparison, but I think numeric can be shorter. \$\endgroup\$Dominic van Essen– Dominic van Essen2021年06月17日 14:16:00 +00:00Commented Jun 17, 2021 at 14:16
-
\$\begingroup\$ Ha! You edited while I was typing, and yours is better! Well done! \$\endgroup\$Dominic van Essen– Dominic van Essen2021年06月17日 14:16:33 +00:00Commented Jun 17, 2021 at 14:16
Charcoal, 28 bytes
≔I⪪S-θ§12344÷−§θ1+›16⊟θ›6⊟θ3
Try it online! Link is to verbose version of code. Takes input in the form YYYY-MM-DD. Explanation:
≔I⪪S-θ
Input the date, split it on - and cast to integer.
§12344÷−§θ1+›16⊟θ›6⊟θ3
Take the month, subtract 1 each if the day is less than 16 or the month is less than 6, divide by 3, then cyclically index into the string 12344, thus casting -1 and 4 to 4.
Python 3.8 (pre-release), 109 bytes
lambda n,i=int:'Q'+['?111223334444'[i(k:=(S:=n.split('-'))[1])],'1234'[i(k)//3-1]][k in'1469'and(i(S[0])<16)]
Way too long.
The OP has confirmed very kindly that this is the only solution of mine which is valid.
-
\$\begingroup\$ You're allowed to ignore useless arguments -there's a meta post about it. \$\endgroup\$emanresu A– emanresu A2021年06月17日 20:06:05 +00:00Commented Jun 17, 2021 at 20:06