# Legalize Reversed Date

Input:

A Date (containing dd, MM and yyyy). A date-object, or three separate integers are also valid as input.

Output:

Each part (dd, MM and yyyy) individually reverted and than rounded to the nearest valid date.

For example (in the format dd-MM-yyyy):
21-10-2016 becomes 12-01-6102

Challenge rules:

• Only dd, MM, yyyy is valid, but the order and which separate-symbols you use is your own choice.
So these are some valid format examples: dd-MM-yyyy; MM/dd/yyyy; yyyy MM dd; ddMMyyyy, etc.
And these are some invalid format examples: dd MMM yyyy; dd-MM-'yy; etc.
• You can also choose to just input a Date-object if your language supports it or three separate integer parameters, instead of the string representing a date.
• Please state which date-format you've used! (And the input and output must be in the same format.) It is also allowed to output a Date-object, as long as it can handle all test cases and the challenge rule below.
• The Julian to Gregorian Calendar transition is ignored for this challenge. So 1582 is just a valid reversed year for 2851.
See Challenge info / tips for all valid years, months and days.
• Since you cannot have February as reversed of any other month, you don't have to worry about leap years.

All reversed years, months and days:

• The year can always be reversed without a problem, reaching from 0001 (reversed of 1000) to 9999 (remains 9999). (So 0000 isn't a valid input, and there are also no test cases for it.)
• The only months you'll have reversed are: January (reversed from October / 10); October (reversed from January / 01); November (remains November / 11); and December (reversed from every other month / 02-09, 12).
• The only days you'll have reversed are: 01 (reversed from 10), 02 (reversed from 20), 03 (reversed from 30), 10 (reversed from 01), 11 (remains 11), 12 (reversed from 21), 13 (reversed from 31), 20 (reversed from 02), 21 (reversed from 12), 22 (remains 22), 30 (reversed from 03 or the same as 31 for November!), 31 (reversed from 04-09 / 13-19 / 23-29).

General rules:

• This is , so shortest answer in bytes wins.
Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
• Standard rules apply for your answer, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters and return statements/output, full programs. Your call.
• Default Loopholes are forbidden.

Test cases (dd-MM-yyyy as format):

21-07-2016   ->   12-12-6102
12-11-1991   ->   21-11-1991
01-01-2000   ->   10-10-0002
27-08-1875   ->   31-12-5781
18-12-2010   ->   31-12-0102
13-01-1981   ->   31-10-1891
04-11-1671   ->   30-11-1761  // Semi-tricky case, since November has 30 days
28-11-2036   ->   30-11-6302  // Semi-tricky case, since November has 30 days
14-06-1855   ->   31-12-5581
30-10-9999   ->   03-01-9999
01-01-2851   ->   10-10-1582

• @LegionMammal978 No, 21-07-2016 is reverted 12-70-6102 which is rounded to 12-12-6102. Not sure how you get the result ##-10-6107.. – Kevin Cruijssen Jul 27 '16 at 11:46
• @KevinCruijssen Okay, I thought it was that the month 70 wrapped around, with the year incrementing. – LegionMammal978 Jul 27 '16 at 11:48
• Is 10-10-2 valid output in the third case? – Luis Mendo Jul 27 '16 at 12:04
• @LuisMendo Yeah sure. I've seen other people do it as well. The challenge is more about correctly reversing and rounding the dates than the in- or output format. – Kevin Cruijssen Jul 27 '16 at 18:23
• Would it be acceptable to take three strings, and expect leading zeros? – user19547 Jul 27 '16 at 22:35

## Convex, 23 bytes

Byte count assumes CP-1252 encoding.

qS/Wf%_1=:=31^sCs¶.e<S*


I/O format is dd mm yyyy.

Try it online!

This is a direct port of my CJam answer. Convex is heavily based on CJam, and therefore the only difference is the use of Convex's ¶ operator which wraps the top two stack elements in a list, saving a byte over [...].

## CJam, 24 bytes

qS/Wf%[_1=:=31^sCs].e<S*


I/O format is dd mm yyyy.

Try it online!

Same byte count, I/O format mm dd yyyy:

qS/Wf%_0=:=1231^s2/.e<S*


Try it online!

### Explanation

qS/     e# Read input, split around spaces.
Wf%     e# Reverse each component.
[       e# Set marker for new list.
_1=   e#   Duplicate reversed strings, extract reversed month.
:=    e#   Check for equality of the characters. This gives 1 for
e#   November (11) and 0 for everything else.
31^   e#   XOR the result with 31, giving 30 for November and 31
e#   for everything else.
s     e#   Convert the result to a string, "30"/"31".
Cs    e#   Push 12, convert to string, "12".
]       e# Wrap "30"/"31" and "12" in a list.
.e<     e# Element-wise minimum. This clamps the day and month to their
e# respective maxima.
S*      e# Join the result with spaces.


The other version works similarly, except that we start from the integer 1230 or 1231 before converting it to ["12" "30"] or ["12" "31"].

• Languages with date built-in... – Leaky Nun Jul 27 '16 at 12:12
• @LeakyNun This doesn't use a date built-in and I don't see how it would help. – Martin Ender Jul 27 '16 at 12:12
• Then how do you know that there are 30 days in November? – Leaky Nun Jul 27 '16 at 12:13
• @LeakyNun I'll add an explanation later, but 1= gets the reversed month, := checks whether its digits are equal and ^ xors the result into 31, giving 30 for month 11 and 31 for everything else. – Martin Ender Jul 27 '16 at 12:14
• Oh, I didn't read the specs... – Leaky Nun Jul 27 '16 at 12:14

# Pyth, 55534643 41 bytes

APJ_Mczd=HhS,12sH=GhS,sGC@."❤❤ó»î"H%"%02d %02d %s"[GHeJ
APJ_Mczd=hS,12sH=hS,sGC@."❤❤ó»î"H%"%02d %02d %s"[GHeJ
APJ_Mcz\-%"%02d %02d %s"[hS,sGx31q11sHhS,12sHeJ
APJ_Mczdjd[>2+\0hS,sGx31q11sH>2+\0hS,12sHeJ
APJ_Mczdjd.[L\02[hS,sGx31q11sHhS,12sHeJ


where ❤❤ were two unprintables, respectively U+001C and U+001F.

Test suite.

# Dyalog APL, 32 33 bytes

⍕¨{⍵-3↑31 11≡2↑⍵}31 12 1E4⌊⍎∊⍕⌽¨⎕


I/O is list of three strings ('dd' 'mm' 'yyyy').

TryAPL, but note that ⎕ (prompt for input) has been replaced with ⍵ and the entire line enclosed in {...} to enable online testing, and ⍎ (execute expression) has been replaced with 2⊃⎕VFI (verify and fix input) because execution of arbitrary code is blocked.

# Python 3, 82 bytes

lambda x:[min(x[0][::-1],['31','30'][x[1]=='11']),min(x[1][::-1],'12'),x[2][::-1]]


An anonymous function that takes input, via argument, of the date as a list of strings of the form ['dd', 'mm', 'yyyy'] and returns the validated reversed date in the same format.

How it works

Python compares characters and strings by their Unicode code-points. This means that any comparison on two or more integers returns the same as that comparison on those integers as strings. Hence, calling min on two integers as strings returns the smallest integer as a string; by taking the reversed date-part as one argument and the maximum value as another, the day and month are clamped to the desired range. The date-parts are reversed by indexing with steps of -1 ([::-1]), and the maximum value for the month is changed from '31' to '30' if the month is November by indexing into a list with the Boolean result of a conditional.

Try it on Ideone

# C# 314305299249232 223 Bytes

using System.Linq;string f(int d,int m,int y){Func<int,string>r=i=>string.Concat((""+i).PadLeft(2,'0').Reverse());Func<string,int,string>x=(j,k)=>int.Parse(j)>k?""+k:j;return x(r(d),m==11?30:31)+"-"+x(r(m),12)+"-"+r(y);}


Thanks to @KevinCruijssen for pointing out that I could shorten my variable declaration, which also made aliasing string able to save some bytes.

Saved 50 bytes storing the reversing function for reuse and another 13 by doing the same for the rounding and removing the variable declarations.

Last update makes aliasing string no longer a byte saver.

### Ungolfed Version:

using System.Linq;
string dateReverse(int day, int month, int year)
{
//setup a resuable function to reverse
Func<int, string> reverse = intToReverse => string.Concat((""+intToReverse).PadLeft(2, '0').Reverse());

//another function for rounding
Func<string, int, string> round = (strToRound, maxVal) => int.Parse(strToRound) > maxVal ? "" + maxVal : strToRound;

//Join the strings into the "dd-mm-yyyy" date format
return
//Round down the day value, if november cap to 30 otherwise cap to 31
round(reverse(day), month == 11 ? 30 : 31) + "-" +

//Round the month down
round(reverse(month), 12) + "-" +

//we can use the reverse function here too and pad left just won't do anything
reverse(year);
}


Test it here

• You can ignore the space between using System.Linq; and the function, so that's -1 byte. Also, var n=...;var e=...; can be golfed by 1 byte using this instead: string n=...,e=...; It's not much, but still -2 bytes. ;) – Kevin Cruijssen Jul 27 '16 at 20:20
• Nice catch on that space, though it looks like my byte count actually didn't count it, so ill chock that up to a copy paste issue. Also I think using that variable declaration style Ill be able to win a few more bytes by aliasing string. – user19547 Jul 27 '16 at 20:27

# Ruby, 92 84 + 1 (-p flag) = 93 85 bytes

Uses - as the seperator.

d,m,y=chomp.split(?-).map &:reverse
\$_=[[d,m=="11"?"30":"31"].min,[m,"12"].min,y]*?-


## Pyke, 29 bytes

F_bw-o^tDI]SX(mhj_Xjth~%R@]Sh


Try it here!

I can definitely see this being golfable

# Javascript, 106105 94 bytes

d=>d.split,.map((a,b,r)=>(e=[...a].reverse().join,f=!b?r[1]==11^31:b<2&&12,f&&f<e?f:e))+''


Test suite (rev. 3)

Explanation

d=>d.split,                 // split into sections by ,

.map((a,b,r)=>(               // map each section

e=[...a].reverse().join,    // spread a date section into array and reverse and
// join with  to get string result

f=!b?r[1]==11^31              // if section being mapped is day (section 0),
// then max (f) is 30 for November(month 11) or else 31

:b<2&&12,                     // if part being mapped is month (section 1), then max (f) is 12

f&&f<e?f:e))                  // if there is a max (f)
// and the max (f) is less than the reversed string (e),
// then return the max (f),
// else return the reversed string (e)

+''                           // join all the sections back together with ,
// (concatenating [] with a string will do this)


Thanks @KevinCruijssen for saving 1 byte for b==1 to b<2. Thanks @Neil for saving 11 bytes by suggesting ES6 template literal and , separator.

• I'm pretty bad at JS, so correct me if I say something wrong, but can't b==1 be golfed down to b<2 to save a byte? It can't be 0 anymore, since you've already checked that at the !b? part of the code. It seems to work in your test suite when I change it. – Kevin Cruijssen Jul 27 '16 at 20:30
• @KevinCruijssen yep, you're right, thanks! I just overlooked it. I haven't done golfing in javascript for very look so I miss things like that sometimes – CShark Jul 27 '16 at 20:55
• *I meant 'for very long', not 'for very look' – CShark Jul 27 '16 at 21:03
• As you're targeting ES6, you can use template strings to shorten your code - join instead of join('') for example - but you can save a little more by using , as your separator, which allows you to use +'' to join the three values together. – Neil Jul 27 '16 at 23:25
• @Neil you mean , as the separator in the input? – CShark Jul 28 '16 at 14:16

## Python 2, 154 bytes

z=input().split("-");r=[x[::-1]for x in z];z[1]=r[1]if r[1]<'12'else '12';z[0]=r[0]if r[0]<'31'else '30'if z[1]=='11'else '31';z[2]=r[2];print "-".join(z)


Takes the input as a string, so quotes need to be specified in the input, e.g. "11-04-2016".

• Just a basic improvement since I'm not a Python golfer: z=[x[::-1]for x in z];z[1]=min(z[1],'12');z[0]=min(z[0],['31','30'][z[1]=='11']);print"-".join(z). Basically, you don't need to use r at all, and min accomplishes a lot of the things you want to do. – Value Ink Jul 27 '16 at 20:20

# 05AB1E, 24 bytes

#íÐÅsË31^12‚øεßт+¦}sθªðý


Port of @MartinEnder's CJam answer, so also inputs and outputs as a string in the format dd MM yyyy.

Explanation:

#                         # Split the (implicit) input by spaces
#  i.e. "04 11 1671" → ["04","11","1671"]
#  i.e. "20 01 2000" → ["20","01","2000"]
í                        # Reverse each string
#  i.e. ["04","11","1671"] → ["40","11","1761"]
#  i.e. ["20","01","2000"] → ["02","10","0002"]
Ð                       # Triplicate this list
Ås                     # Pop one of them, and push it's middle element (the months)
#  i.e. ["40","11","1761"] → "11"
#  i.e. ["02","10","0002"] → "10"
Ë                    # Check if the digits are the same (1 for 11; 0 otherwise)
#  i.e. "11" → 1 (truthy)
#  i.e. "10" → 0 (falsey)
31^                 # Bitwise-XOR with 31 (30 for November, 31 for other months)
#  i.e. 1 → 30
#  i.e. 0 → 31
12‚              # Pair it with 12
#  i.e. 30 → [30,12]
#  i.e. 31 → [31,12]
ø             # Zip/transpose; swapping rows and columns
# (implicitly removes year)
#  i.e. ["40","11","1761"] and [30,12] → [["40",30],["11",12]]
#  i.e. ["02","10","0002"] and [31,12] → [["02",31],["10",12]]
ε    }       # Map each pair to:
ß           # Get the minimum (implicitly converts to integer unfortunately)
#  i.e. [["40",30],["11",12]] → [30,11]
#  i.e. [["02",31],["10",12]] → [2,10]
#  i.e. [30,11] → [130,111]
#  i.e. [2,10] → [102,110]
¦        # Remove the first character
#  i.e. [130,111] → ["30","11"]
#  i.e. [102,110] → ["02","10"]
s      # Swap so the triplicated list is at the top of the stack again
θ     # Pop and only leave it's last element (the year)
#  i.e. ["40","11","1761"] → "1761"
#  i.e. ["02","10","0002"] → "0002"
ª    # Append it to the list
#  i.e. ["30","11"] and "1761" → ["30","11","1761"]
#  i.e. ["02","10"] and "0002" → ["02","10","0002"]
ðý  # Join the list by spaces (and output implicitly)
#  i.e. ["30","11","1761"] → "30 11 1761"
#  i.e. ["02","10","0002"] → "02 10 0002"