Out of 3 date formats only, MDY, DMY & YMD, list the date formats for given dates. An ambiguous dates may have more than one possible formats.
📌 Challenge Details and Links
ExcelBI Excel Challenge Number: 605
Challenge Difficulty: ⭐️⭐️⭐️⭐️⭐️
📥Download Sample File
📥Link to the solutions on LinkedIn
Solving the challenge of Detect Possible Date Formats with Power Query
Power Query solution 1 for Detect Possible Date Formats, proposed by Abdallah Ally:
let
Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
AddCol = Table.AddColumn(
Source,
"My Answer",
each [
a = Text.Replace([Date], "/", "-"),
b = {"d", "dd"},
c = {"M", "MM", "MMM", "MMMM"},
d = {"yy", "yyyy"},
fx = (r, s, t) =>
List.TransformMany(
List.TransformMany(r, each s, (u, v) => u & "-" & v),
each t,
(w, x) => w & "-" & x
),
e = fx(b, c, d),
f = fx(c, b, d),
g = fx(d, c, b),
h = List.Zip({e, List.Repeat({"DMY"}, List.Count(e))}),
i = List.Zip({f, List.Repeat({"MDY"}, List.Count(f))}),
j = List.Zip({g, List.Repeat({"YMD"}, List.Count(g))}),
k = List.Transform(
h & i & j,
(x) => if (try Date.FromText(a, [Format = x{0}]))[HasError] then null else x{1}
),
l = Text.Combine(List.Distinct(List.RemoveNulls(k)), ", ")
][l]
),
Result = Table.AddColumn(AddCol, "Check", each [Answer Expected] = [My Answer])
in
Result
Power Query solution 2 for Detect Possible Date Formats, proposed by Seokho MOON:
let
Com = [Y = {"yy", "yyyy"}, M = {"M", "MMM"}, D = {"d"}, S = {"-", "/"}],
Func = (x as list) as list =>
[
T = List.Transform(x, each List.Transform(_, each {_})),
A = List.Accumulate(
{1 .. List.Count(T) - 1},
T{0},
(a, v) => List.TransformMany(a, (y) => T{v}, (y, z) => y & z)
),
R = List.Transform(A, each Text.Combine(List.RemoveLastN(_), List.Last(_)))
][R],
Format = [
DMY = Func({Com[D], Com[M], Com[Y], Com[S]}),
MDY = Func({Com[M], Com[D], Com[Y], Com[S]}),
YMD = Func({Com[Y], Com[M], Com[D], Com[S]})
],
Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
Res = Table.AddColumn(
Source,
"Answer Expected",
(x) =>
[
T = List.Transform(
Record.FieldNames(Format),
(y) =>
[
A = List.Accumulate(
Record.Field(Format, y),
{},
(a, v) => a & {(try Date.FromText(x[Date], [Format = v]))[HasError]}
),
R = if List.AllTrue(A) then null else y
][R]
),
F = Text.Combine(List.RemoveNulls(T), ", ")
][F]
)
in
Res
Power Query solution 3 for Detect Possible Date Formats, proposed by Mihai Radu O:
let
Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
s = Table.AddColumn(
Source,
"r",
each [
f = {"MDY", "DMY", "YMD"},
z = {"%d", "dd", "ddd", "dddd", "%M", "MM", "MMM", "MMMM", "%y", "yy", "yyy", "yyyy"},
p = List.Transform(
z,
(x) => List.Distinct(Text.ToList(Text.Upper(Text.Select(x, {"a" .. "z", "A" .. "Z"})))){0}
),
tb = List.Zip({p, z}),
a = Text.SplitAny([Date], "-/"),
b = List.Transform(
a,
(x) =>
List.Distinct(
List.RemoveNulls(
List.Transform(
tb,
(t) =>
try if Date.FromText(x, [Format = t{1}]) is date then t{0} else null otherwise null
)
)
)
),
c = List.Combine(
List.Transform(
{0 .. 2},
(x) =>
List.Combine(
List.Transform(
b{0},
(_a) =>
List.Combine(
List.Transform(b{1}, (_b) => List.Transform(b{2}, (_c) => {_a, _b, _c}))
)
)
)
)
),
d = List.Distinct(List.Transform(c, Text.Combine)),
e = Text.Combine(List.Select(d, (x) => List.Contains(f, x)), ", ")
][e]
)[r]
in
s
Solving the challenge of Detect Possible Date Formats with Excel
Excel solution 1 for Detect Possible Date Formats, proposed by Bo Rydobon 🇹🇭:
=MAP(A2:A10,LAMBDA(d,LET(f,{"DMY","MDY","YMD"},
ARRAYTOTEXT(FILTER(f,1-ISNA(XMATCH(f,REDUCE("",--TEXTSPLIT(d,{"/","-"}),LAMBDA(a,v,LET(b,DROP({"Y","D","M"},,IFERROR(1-MATCH(v,{0,13,32}),2)),TOCOL(a&b)))))))))))
Excel solution 2 for Detect Possible Date Formats, proposed by John V.:
=MAP(A2:A10,
LAMBDA(x,
LET(i,
TEXTSPLIT(
x,
{"-";"/"}
),
s,
SEQUENCE(
3,
3
),
ARRAYTOTEXT(FILTER({"DMY";"MDY";"YMD"},
BYROW(IF(ISERR(
-i
),
IF((s=2)+(s=4)+(s=8),
MONTH(
i&1
)),
i*{1,
1,
-1;1,
1,
-1;-1,
1,
1}<{32,
13,
0;13,
32,
0;0,
13,
32}),
AND))))))
Excel solution 3 for Detect Possible Date Formats, proposed by Timothée BLIOT:
=LET(A,
SEQUENCE(
12
),
B,
TEXT(
DATE(
1900,
A,
1
),
"MMM"
),
C,
REDUCE(
A2:A10,
UPPER(
B
),
LAMBDA(
w,
v,
SUBSTITUTE(
w,
v,
XLOOKUP(
v,
B,
A
)
)
)
),
MAP(C,
LAMBDA(x,
LET(D,
--REGEXEXTRACT(
x,
"d+",
1
),
M,
TAKE(
D,
,
1
),
N,
INDEX(
D,
,
2
),
O,
TAKE(
D,
,
-1
),
H,
LAMBDA(m,
n,
o,
p,
LET(d,
XLOOKUP(
p,
{1,
2,
3},
{"YYMMDD",
"DDMMYY",
"MMDDYY"}
),
Y,
IF(
p=1,
m,
o
),
V,
DATE(
IF(
Y<100,
2000+Y,
Y
),
IF(
p=1,
n,
IF(
p=2,
n,
m
)
),
IF(
p=1,
o,
IF(
p=2,
m,
n
)
)
),
w,
LAMBDA(
x,
TEXT(
MOD(
x,
100
),
"00"
)
),
ISNUMBER(
V
)*(TEXT(
V,
d
)=w(
m
)&w(
n
)&w(
o
)))),
TEXTJOIN(
",",
,
IF(
H(
M,
N,
O,
1
),
"YMD",
""
),
IF(
H(
M,
N,
O,
2
),
"DMY",
""
),
IF(
H(
M,
N,
O,
3
),
"MDY",
""
)
)))))
Excel solution 4 for Detect Possible Date Formats, proposed by Eddy Wijaya:
=REDUCE(B1,A2:A10,LAMBDA(a,v,VSTACK(a,LET(
sp,TEXTSPLIT(v,{"-","/"}),
c,MAP(sp,LAMBDA(m,IFERROR(MONTH(DATEVALUE(m&1))&";",--m))),
tx,MAP(c,LAMBDA(d,IFS(ISTEXT(d),"m:",
LEN(d)<=2,IFS(d<=12,"m",d<=31,"d",TRUE,"y"),
TRUE,"y"))),
f,CONCAT(tx),
IFS(ISNUMBER(SEARCH(":",f)),CONCAT(MAP(tx,LAMBDA(m,IFS(m="m:","M",m="m","D",TRUE,"Y")))),
LEFT(f,3)="mmm","DMY, MDY, YMD",
LEFT(f,2)="mm","DMY, MDY",
RIGHT(f,2)="mm","YMD",
FIND("md",f),UPPER(f),
TRUE,"")))))
Excel solution 5 for Detect Possible Date Formats, proposed by Philippe Brillault:
=LET(n,SEQUENCE(ROWS(_P)),VLOOKUP(REDUCE(_T,n,LAMBDA(t,i,REGEXREPLACE(t,INDEX(_P,i,1),INDEX(_P,i,2)))),_Cd,2,0))
Solving the challenge of Detect Possible Date Formats with Python
Python solution 1 for Detect Possible Date Formats, proposed by Abdallah Ally:
import pandas as pd
from itertools import product
# Create required data manipulation functions
def zip_values(format, *values):
products = ['/'.join(x) for x in product(*values)]
results = list(zip(products, [format] * len(products)))
return results
def get_date_styles():
d = ['%d']
m = ['%m', '%b', '%B']
y = ['%y', '%Y']
dmy = zip_values('DMY', d, m, y)
mdy = zip_values('MDY', m, d, y)
ymd = zip_values('YMD', y, m, d)
return dmy + mdy + ymd
def get_date_formats(str_date):
date_styles = get_date_styles()
date_formats = []
for style in date_styles:
try:
format = pd.to_datetime(str_date.replace('-', '/'), format=style[0])
date_formats.append(style[1])
except: ''
return ', '.join(date_formats)
df = pd.read_excel(file_path, usecols='A:B')
# Perform data manipulation
df['My Answer'] = df['Date'].map(get_date_formats)
df['Check'] = df['Answer Expected'] == df['My Answer']
df
Solving the challenge of Detect Possible Date Formats with Python in Excel
Python in Excel solution 1 for Detect Possible Date Formats, proposed by Alejandro Campos:
from datetime import datetime
df = xl("A1:A10", headers=True)
def check_formats(date_str):
valid_formats = []
for fmt in ["%m/%d/%Y", "%m-%d-%Y", "%b-%d-%y", "%b-%d-%Y"]:
try:
datetime.strptime(date_str, fmt)
valid_formats.append("MDY")
break
except:
pass
for fmt in ["%d/%m/%Y", "%d-%m-%Y", "%d-%b-%y", "%d-%b-%Y"]:
try:
datetime.strptime(date_str, fmt)
valid_formats.append("DMY")
break
except:
pass
for fmt in ["%Y-%m-%d", "%y-%m-%d", "%Y-%b-%d", "%y-%b-%d"]:
try:
datetime.strptime(date_str, fmt)
valid_formats.append("YMD")
break
except:
pass
return ", ".join(valid_formats) if valid_formats else "Invalid"
df['Answer Expected'] = df['Date'].apply(check_formats)
df
Python in Excel solution 2 for Detect Possible Date Formats, proposed by Anshu Bantra:
from datetime import datetime
import re
def infer_date_formats(date_str):
# List of ambiguous date formats to test
date_str = re.sub(r'[-/._s]', '-', str(date_str))
possible_formats = {
"%d-%m-%y": "DMY",
"%d-%m-%Y": "DMY",
"%d-%b-%y": "DMY",
"%d-%b-%Y": "DMY",
"%d-%B-%y": "DMY",
"%d-%B-%Y": "DMY",
"%m-%d-%Y": "MDY",
"%m-%d-%y": "MDY",
"%B-%d-%y": "MDY",
"%B-%d-%Y": "MDY",
"%b-%d-%y": "MDY",
"%b-%d-%Y": "MDY",
"%y-%d-%b": "YDM",
"%Y-%d-%b": "YDM",
"%y-%d-%B": "YDM",
"%Y-%d-%B": "YDM",
"%Y-%m-%d": "YMD",
"%y-%m-%d": "YMD",
}
valid_formats = []
for fmt, label in possible_formats.items():
try:
datetime.strptime(date_str, fmt)
valid_formats.append(label)
except ValueError:
continue
return ', '.join(valid_formats)
df = xl("A1:A10", headers=True)
df['Answer'] = df['Date'].apply(infer_date_formats)
df
Solving the challenge of Detect Possible Date Formats with R
R solution 1 for Detect Possible Date Formats, proposed by Konrad Gryczan, PhD:
library(tidyverse)
library(readxl)
library(lubridate)
input = read_excel(path, range = "A1:A10")
test = read_excel(path, range = "B1:B10")
all_formats = c("DMY", "MDY", "YMD")
parts = str_split(date_str, "[^A-Za-z0-9]+")[[1]]
letter_parts = which(str_detect(parts, "[A-Za-z]"))
if (length(letter_parts) > 0) {
month_pos = letter_parts[1]
format_positions = list("DMY" = 2, "MDY" = 1, "YMD" = 2)
all_formats = names(format_positions)[sapply(format_positions, function(pos) pos == month_pos)]
}
valid_formats = all_formats[sapply(all_formats, function(fmt) {
parsed_date = switch(fmt, "DMY" = dmy(date_str), "MDY" = mdy(date_str), "YMD" = ymd(date_str))
!is.na(parsed_date)
})]
if (length(valid_formats) == 0) NA else paste(valid_formats, collapse = ", ")
}
&&&
