COBOL Y2K redux

R, 126 bytes

function(x,a=x%/%100^(2:0)%%100,d=as.Date)'if'(a[2]<13,d(paste(19e6+x),'%Y%m%d'),d(a[3]+100*((a[2]-13)+87*a[1]),'2000-01-01'))

Try it online!

  • -5 bytes thanks to @Giuseppe suggestion to take a numeric input instead of string

T-SQL, 99 98 bytes

SELECT CONVERT(DATE,IIF(ISDATE(i)=1,'19'+i,
       DATEADD(d,8700*LEFT(i,2)+RIGHT(i,4)-935,'1999')))FROM t

Line break is for readability only. Thank goodness for implicit casting.

Input is via a pre-existing table t with CHAR column i, per our IO rules.

Goes through the following steps:

  1. Initial check is via the SQL function ISDATE(). (The behavior of this function changes based on language settings, it works as expected on my english-us server). Note this this is just a check for validity, if we tried to parse it directly, it would map 250101 as 2025-01-01, not 1925-01-01.
  2. If the string parses correctly as a date, tack 19 on the front (rather than change the server-level year cutoff setting). Final date conversion will come at the end.
  3. If the string does not parse as a date, convert it to a number instead. The shortest math I could find was 8700*PP + QQRR - 1300, which avoids the (very long) SQL SUBSTRING() function. This math checks out for the provided samples, I'm pretty sure it is right.
  4. Use DATEADD to add that many days to 2000-01-01, which can be shorted to 2000.
  5. Take that final result (either a string from step 2, or a DATETIME from step 4), and CONVERT() it to a pure DATE.

I thought at one point that I found a problematic date: 000229. This is the only date which parses differently for 19xx vs 20xx (since 2000 was a leap year, but 1900 was not, due to weird leap-year exceptions). Because of that, though, 000229 isn't even a valid input (since, as mentioned, 1900 was not a leap year), so doesn't have to be accounted for.


JavaScript (SpiderMonkey), 103 bytes

s=>new Date(...([a,b,c]=s.match(/../g),b>12?[2e3,0,(b-13+a*87)*100-~c]:[a,b-1,c])).toJSON().split`T`[0]

Try it online!


.toJSON will failed on a UTC+X timezone. This code works, but longer (+11bytes):

s=>Intl.DateTimeFormat`ii`.format(new Date(...([a,b,c]=s.match(/../g),b>12?[2e3,0,(b-13+a*87)*100-~c]:[a,b-1,c])))