# Tesco's Burger Relish Best Before End date number

Given a date between 2010-01-01 and 2099-12-31 as three integers (please state your order if not [year,month,day]), answer with Tesco's corresponding five-digit Burger Relish Best Before End date number.

The format is simply the last two digits of the year, followed immediately by three digits representing the day of that year, between 000 and 365.

Cookies if you can do this using only numeric operations and comparisons. You may put such code separately from your golfed code, if it isn't also the shortest code you have.

### Test cases

[year,month,day]BRBBED:

[2010,1,1]10000

[2019,7,5]19185

[2020,5,20]20140

[2096,12,31]96365

[2099,12,31]99364

• "Cookies if you can do this using only numeric operations." Good luck handling dates without e.g. comparison operators... – Erik the Outgolfer Jul 5 '19 at 16:08
• Closely related – Arnauld Jul 5 '19 at 16:22
• @Arnauld But that's a do-X-without-Y with an input domain that makes things harder. – Adám Jul 5 '19 at 16:33
• @wizzwizz4 It was in the news recently: independent.co.uk/life-style/… : The supermarket’s unusual labelling choice came to light on Sunday after customer Matthew Stock shared a photograph on Twitter featuring a burger relish that had an expiration date of “20140” and asked Tesco to “please explain” it. – seventyeightist Jul 6 '19 at 19:41

# PowerShell, 7470 67 bytes

param($y,$m,$d)-join"$y 00$((date "$m/$d/$y"|% d*r)-1)"[2,3+-3..-1]

Try it online!

Exactly what it says on the tin (but formatted weirdly). Takes in $year,$month, $day, plucks out the last two digits of the$year, gets a .NET datetime object of the specified day, then gets the dayofyear (with |% d*r) thereof. Subtracts one to make it zero-indexed, then uses string formatting and slicing to make it three-padded (e.g., 000 instead of 0), and then -joins it all together into a single string with implicit output.

Note this is culture dependent due to the datetime formatting. This works in en-us, which is what TIO also uses.

-3 bytes thanks to mazzy

• -1 byte – mazzy Jul 5 '19 at 18:25
• @mazzy Don't need the parens in -join(...) since it's a single string slice, then. So that's another -2. Thanks! – AdmBorkBork Jul 5 '19 at 18:37

# C# (Visual C# Interactive Compiler), 8878737159 57 bytes

a=>a[0]%100*1000+new DateTime(a[0],a[1],a[2]).DayOfYear-1

Try it online!

• (y,m,d)=>y%100*1000+new DateTime(y,m,d).DayOfYear-1 for 51 bytes? – Ed T Jul 6 '19 at 1:59
• @EdT well it depends on your interpretation of the rules, I was aware of it but didn't do it, can be 51 curried also – Expired Data Jul 6 '19 at 2:04

# Ruby, 40 bytes

->d{Time.gm(*d).strftime('%y%j').to_i-1}

Try it online!

So close to being a built-in format, but %j is 1-indexed.

In a happier coincidence, though, Tesco Time (.gm) is one character shorter than local time (.new).

# PowerShell, 4845 39 bytes

Port of Expired Data's answer for C#

$args[0]*1E3+("$args"|date|% d*r)-2E6-1

Try it online!

# PowerShell, 6058 52 bytes

-join"$args 00$(("$args"|date|% d*r)-1)"[2,3+-3..-1] Try it online! Explanation: • The script takes three integers [year,month,day] • "$args" makes a string like YYYY MM DD
• "YYYY MM DD"|date converts string to [DateTime]. I don't know why it works. Can you explain?
• ("YYYY MM DD"|date|% d*r)-1 calculates dayOfYear
• the script makes a result string like YYYY MM DD 00### where ### is dayOfYear
• finally the script extracts chars from positions [2,3+-3..-1] of the result string and joins this chars to result
• Clever use of \$args. – AdmBorkBork Jul 5 '19 at 18:39
• Just like with my answer, you only have a single string slice, so you don't need parens in -join(...) for -2 bytes. Try it online! – AdmBorkBork Jul 5 '19 at 18:41
• Nice port! I knew there'd be a good way in PowerShell, but I didn't think it'd be that good – Expired Data Jul 5 '19 at 19:38

# Python 2, 6361 57 bytes

lambda y,m,d:y%100*1000+(153*m-2)/5+[m+1,1>y%4][2<m]+d-33

Try it online!

Returns the result as an integer.

Neil found that his Charcoal approach turned out to be lucky after some rearrangement.

Pure arithmetic and comparison solution (61 bytes):

lambda y,m,d:y%100*1000+30*m+m/2+(8<m<12)+~(0<y%4)*(2<m)+d-31
• Seems to be a day off for January and February? – Neil Jul 5 '19 at 20:32
• @Neil Oh LOL I just noticed I was subtracting the extra day February doesn't have even when that month hasn't passed yet. EDIT: should be fixed. – Erik the Outgolfer Jul 5 '19 at 20:33
• I ported my Charcoal solution, and then golfed it down to 57 bytes: y%100*1000+(153*m-2)/5+[m+1,1>y%4][2<m]+d-33. (Sadly this rearrangement has the same byte count in Charcoal.) – Neil Jul 5 '19 at 20:43
• @Neil LOL Charcoal thinking beats Python thinking 10/10 I guess. :D I'll add it and see what I can further do, if I can. – Erik the Outgolfer Jul 5 '19 at 20:52

# Python 3, 8785 74 bytes

lambda y,m,d:sum([y*1000-2000029+28*m,3,y%4==0,3,2,3,2,3,3,2,3,2,3][:m])+d

Try it online!

This is using only numeric operations and comparisons.

• -5: y%4==0 -> 1>y%4 and splitting up the long array into ([y*1000-2000029+28*m,3,1>y%4]+[3,2,3,2,3]*2) – ar4093 Aug 9 '19 at 11:41

# Jelly, 30 bytes

4ḍȯ2⁽¢wB+30¤_2¦ŻḣS+⁵’+³×ȷ¤_2ȷ6

A full program taking arguments y m d.
Jelly has no built-in date functionality.

Try it online!

### How?

⁽¢w                        -   1370
B                       -   to binary = [1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0]
+30                    -   add 30   = [31,30,31,30,31,30,31,31,30,31,30]
¦                - sparse application...
2                 -   to indices: [2]
_                  -   action: subtract...
4ḍ                             -     four divides y? -> 1 or 0
ȯ2                           -     OR 2               1 or 2
Ż               - prepend 0 = [0,31,29|28,31,30,31,30,31,31,30,31,30]
ḣ              - head to index m
S             - sum
’          - subtract one
³        -   y
ȷ      -   1000
×       -   multiply
2ȷ6 - 2000000
_    - subtract

# Charcoal, 33 bytes

ＩΣ⟦×φ﹪θ¹⁰⁰⊖ζ÷⊕×¹⁵³⊖η⁵⎇›η²⊖⊖¬﹪θ⁴⊖η

Try it online! Link is to verbose version of code. Try it online! Link includes test suite. I don't think Charcoal has any date functions, so here's a mathematical solution. Explanation:

×φ﹪θ¹⁰⁰                          Year * 1000
⊖ζ                        Day - 1
÷⊕×¹⁵³⊖η⁵               Days in previous months
⎇›η²            For months after Februrary
⊖⊖¬﹪θ⁴     Adjust for leap years else
Σ⟦                                 Take the sum
Ｉ                                   Cast to string for implicit print

# [R], 66 bytes

function(a,b,c)as.numeric(strftime(paste(a,b,c,sep='-'),'%y%j'))-1

taking 3 integers and pasting them into a string strftime can recognize and extract the wanted parts. 0 indexing costs 14 bytes and another conversion to numeric

# Ruby, 798179 78 bytes

->y,m,d{(y%100*k=1000)+[d-1,l=31,y%4<1?29:28,l,s=30,l,s,l,l,s,l,s][0,m].sum%k}

Cookies version. Saved a few bytes by including the -1 and day in the array that gets summed, since those spaces were spare anyway.

EDIT: I realised that using "...%03d"%... wasn't really in the spirit of 'numerical and comparison operators only' so I've updated this answer (and gone up by 2 bytes).

EDIT-2: ... and recovered them by using the alternative sub-array index format [start,length], which in turn allowed me to combine the first two entries in the array.

EDIT-3: y%4==0 can be shortened to y%4<1

# JavaScript, 70 57 bytes

(y,m,d,U=Date.UTC)=>y%100*1e3+(U(y,m-1,d)-U(y,0,1))/864e5

Try it online!

• 59 bytes? – Arnauld Jul 5 '19 at 19:24
• @Arnauld y%100*1e3 works because they have the same precedence. – Neil Jul 5 '19 at 20:01
• Heh, I was overcomplicating it by using string concatenation when simple arithmetic is all that was needed. Thanks @Arnauld and @Neil! – darrylyeo Jul 5 '19 at 20:36
• @darrylyeo something in the back of my head said -2000 was 1 byte too many but %100 was far too obvious! – Expired Data Jul 5 '19 at 21:19

# Perl 6, 45 bytes

{@_.[0]%100*1000-1+Date.new(|@_).day-of-year}

Try it online!

• 42 bytes – Jo King Jul 6 '19 at 22:18
• @joking I have no idea why .[0] was bombing in TIO when I did it. Good catch on 1e3, I'll update when I get to a computer – user0721090601 Jul 6 '19 at 22:45

# Red, 54 bytes

func[y m d][y % 100 * 1000 - 1 + pick to now[d m y]11]

Try it online!

# 8th, 77 71 bytes

Code

needs date/utils : f third -rot d:ymd> doy n:1- swap 100 mod 1000 * + ;

Return the result on TOS

Usage

ok> 2010 1 1 f .
10000
ok> 2019 7 5 f .
19185
ok> 2020 5 20 f .
20140
ok> 2096 12 31 f .
96365
ok> 2099 12 31 f .
99364

# 05AB1E, 2926 23 bytes

¦¦₄*•ΘÏF•ºS₂+I<£O¹4ÖI<O

Takes three loose inputs in the order $$\year\$$, $$\month\$$, $$\day\$$.

Explanation:

¦¦             # Remove the first two digits of the (implicit) input-year
#  i.e. year=2024 → 24
₄*           # Multiply it by 1000
#  → 24000
•ΘÏF•          # Push compressed integer 5254545
º         # Mirror it vertically to 52545455454525
S        # Convert it to a list of digits: [5,2,5,4,5,4,5,5,4,5,4,5,2,5]
₂+      # Add 26 to each: [31,28,31,30,31,30,31,31,30,31,30,31,28,31]
I<    # Push the second input-month decremented by 1
£   # Leave the first month-1 amount of values from the list
O  # Sum this list
#  i.e. month=4 → [31,28,31] → 90
¹              # Push the first input-year again
4Ö            # Check if it's divisible by 4
#  2024 → 1 (truthy)
I<             # Push the third input-days, decremented by 1
#  i.e. days=3 → 2
O              # Sum everything on the stack together
#  24000,90,1,2 → 24093
# (which is output implicitly as result)

See this 05AB1E tip of mine (section How to compress large integers?) to understand why •ΘÏF• is 5254545.

# Elm 0.19, 112 bytes

t y m d=1000*(y-2000)+List.sum(List.take m[d-1,31,if modBy 4 y<1 then 29 else 28,31,30,31,30,31,31,30,31,30,31])

Verify all test cases here.

# Japt, 23 bytes

Takes input as 3 individual strings, assuming that's allowed.

¤+@ÐUTX Å¶ÐN Å}as ùT3 É

Try it

Very unhappy with this (there must be a better way to get the day of the year!) but it's been a long day. A port of darrylyeo's JS solution would be 2 bytes shorter but, for some reason, despite Japt being JavaScript, floating point inaccuracies abound.

¤+@ÐUTX Å¶ÐN Å}as ùT3 É     :Implicit input of strings U=y, V=d & W=d (N=[U,V,W])
¤                           :Slice the first 2 characters off U
+                          :Append
@                         :  Function taking an integer X as its argument
ÐUTX                     :    Construct a Date object with U as the year, 0 as the month & X as the day
Å                   :    Convert to date string ("yyyy-mm-dd")
¶                  :    Test for equality with
ÐN Å              :    Construct a Date object from N and convert to a date string
}             :  End function
a            :  Return the first integer that returns true when passed through that function
s           :  Convert to string
ùT3       :  Left pad with 0 to length 3
É     :Subtract 1