[{"data":1,"prerenderedAt":2313},["ShallowReactive",2],{"doc:\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Ffix-mixed-day-first-and-month-first-dates-in-excel-data":3,"surround:\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Ffix-mixed-day-first-and-month-first-dates-in-excel-data":2280,"ancestors:\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Ffix-mixed-day-first-and-month-first-dates-in-excel-data":2288,"children:\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Ffix-mixed-day-first-and-month-first-dates-in-excel-data":2293,"related:\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Ffix-mixed-day-first-and-month-first-dates-in-excel-data":2294},{"id":4,"title":5,"body":6,"dateModified":2246,"datePublished":2246,"description":2247,"extension":2248,"faq":2249,"keyword":2258,"kind":2259,"meta":2260,"navigation":103,"path":2269,"seo":2270,"slug":2273,"stem":2274,"topics":2275,"type":2278,"__hash__":2279},"docs\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Ffix-mixed-day-first-and-month-first-dates-in-excel-data\u002Findex.md","Fix Mixed Day-First and Month-First Dates in Excel Data",{"type":7,"value":8,"toc":2233},"minimark",[9,28,33,61,71,75,280,319,492,496,499,908,922,1027,1031,1034,1187,1198,1366,1370,1373,1738,1768,1772,1775,1967,1974,1978,1981,2104,2107,2111,2156,2160,2168,2172,2178,2184,2190,2196,2200,2229],[10,11,12,16,17,21,22,27],"p",{},[13,14,15],"code",{},"03\u002F04\u002F2026"," is 3 April in London and March 4 in New York. When a sheet combines rows typed by people in both places — or exports from systems configured differently — the date column becomes a mixture, and no single parsing setting is right for every row. Worse, the convenient options ",[18,19,20],"em",{},"look"," right: pandas parses the whole column without an error and the dates come out plausible. They are just wrong for some rows, and nothing tells you which. This page shows how to find out what the column actually contains, decide each row's convention from evidence, parse with explicit formats, and report the rows that genuinely cannot be decided. It belongs to ",[23,24,26],"a",{"href":25},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002F","Working with Dates and Times in Excel Data",".",[29,30,32],"h2",{"id":31},"prerequisites","Prerequisites",[34,35,40],"pre",{"className":36,"code":37,"language":38,"meta":39,"style":39},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install pandas openpyxl\n","bash","",[13,41,42],{"__ignoreMap":39},[43,44,47,51,55,58],"span",{"class":45,"line":46},"line",1,[43,48,50],{"class":49},"sMTad","pip",[43,52,54],{"class":53},"srMev"," install",[43,56,57],{"class":53}," pandas",[43,59,60],{"class":53}," openpyxl\n",[10,62,63,66,67,70],{},[13,64,65],{},"orders_mixed_dates.xlsx"," has eleven orders with a ",[13,68,69],{},"Source"," column. London writes day\u002Fmonth\u002Fyear, New York month\u002Fday\u002Fyear, the ERP exports ISO dates, one manual row holds a real Excel date (a number with a date format), one has a written-out month, and the Lyon office has a single row that is ambiguous on its own.",[29,72,74],{"id":73},"step-1-see-why-one-setting-cannot-work","Step 1 — See why one setting cannot work",[34,76,80],{"className":77,"code":78,"language":79,"meta":39,"style":39},"language-python shiki shiki-themes github-light github-dark-high-contrast","import pandas as pd\n\norders = pd.read_excel(\"orders_mixed_dates.xlsx\")\nprint(orders[\"OrderDate\"].map(type).value_counts().to_dict())\ntext = orders[\"OrderDate\"].astype(str)\nattempts = pd.DataFrame({\n    \"raw\": text,\n    \"mixed, dayfirst\": pd.to_datetime(text, format=\"mixed\", dayfirst=True).dt.date,\n    \"mixed, monthfirst\": pd.to_datetime(text, format=\"mixed\", dayfirst=False).dt.date,\n})\nprint(attempts.assign(Source=orders[\"Source\"]).to_string(index=False))\n","python",[13,81,82,98,105,123,145,166,177,186,218,243,249],{"__ignoreMap":39},[43,83,84,88,92,95],{"class":45,"line":46},[43,85,87],{"class":86},"s-kum","import",[43,89,91],{"class":90},"skGVy"," pandas ",[43,93,94],{"class":86},"as",[43,96,97],{"class":90}," pd\n",[43,99,101],{"class":45,"line":100},2,[43,102,104],{"emptyLinePlaceholder":103},true,"\n",[43,106,108,111,114,117,120],{"class":45,"line":107},3,[43,109,110],{"class":90},"orders ",[43,112,113],{"class":86},"=",[43,115,116],{"class":90}," pd.read_excel(",[43,118,119],{"class":53},"\"orders_mixed_dates.xlsx\"",[43,121,122],{"class":90},")\n",[43,124,126,130,133,136,139,142],{"class":45,"line":125},4,[43,127,129],{"class":128},"sP0c6","print",[43,131,132],{"class":90},"(orders[",[43,134,135],{"class":53},"\"OrderDate\"",[43,137,138],{"class":90},"].map(",[43,140,141],{"class":128},"type",[43,143,144],{"class":90},").value_counts().to_dict())\n",[43,146,148,151,153,156,158,161,164],{"class":45,"line":147},5,[43,149,150],{"class":90},"text ",[43,152,113],{"class":86},[43,154,155],{"class":90}," orders[",[43,157,135],{"class":53},[43,159,160],{"class":90},"].astype(",[43,162,163],{"class":128},"str",[43,165,122],{"class":90},[43,167,169,172,174],{"class":45,"line":168},6,[43,170,171],{"class":90},"attempts ",[43,173,113],{"class":86},[43,175,176],{"class":90}," pd.DataFrame({\n",[43,178,180,183],{"class":45,"line":179},7,[43,181,182],{"class":53},"    \"raw\"",[43,184,185],{"class":90},": text,\n",[43,187,189,192,195,199,201,204,207,210,212,215],{"class":45,"line":188},8,[43,190,191],{"class":53},"    \"mixed, dayfirst\"",[43,193,194],{"class":90},": pd.to_datetime(text, ",[43,196,198],{"class":197},"sa561","format",[43,200,113],{"class":86},[43,202,203],{"class":53},"\"mixed\"",[43,205,206],{"class":90},", ",[43,208,209],{"class":197},"dayfirst",[43,211,113],{"class":86},[43,213,214],{"class":128},"True",[43,216,217],{"class":90},").dt.date,\n",[43,219,221,224,226,228,230,232,234,236,238,241],{"class":45,"line":220},9,[43,222,223],{"class":53},"    \"mixed, monthfirst\"",[43,225,194],{"class":90},[43,227,198],{"class":197},[43,229,113],{"class":86},[43,231,203],{"class":53},[43,233,206],{"class":90},[43,235,209],{"class":197},[43,237,113],{"class":86},[43,239,240],{"class":128},"False",[43,242,217],{"class":90},[43,244,246],{"class":45,"line":245},10,[43,247,248],{"class":90},"})\n",[43,250,252,254,257,259,261,264,267,270,273,275,277],{"class":45,"line":251},11,[43,253,129],{"class":128},[43,255,256],{"class":90},"(attempts.assign(",[43,258,69],{"class":197},[43,260,113],{"class":86},[43,262,263],{"class":90},"orders[",[43,265,266],{"class":53},"\"Source\"",[43,268,269],{"class":90},"]).to_string(",[43,271,272],{"class":197},"index",[43,274,113],{"class":86},[43,276,240],{"class":128},[43,278,279],{"class":90},"))\n",[10,281,282,283,286,287,290,291,294,295,298,299,302,303,307,308,311,312,314,315,318],{},"The column holds strings and one ",[13,284,285],{},"datetime"," — openpyxl converted the real Excel date. Parsing with ",[13,288,289],{},"format=\"mixed\", dayfirst=True"," gets London right and New York's ambiguous rows wrong, as expected. But look at two rows where it should not matter. ",[13,292,293],{},"04\u002F13\u002F2026"," cannot be day-first — there is no month 13 — yet the parser quietly ",[18,296,297],{},"swaps"," it to 13 April instead of complaining. And the ERP's ",[13,300,301],{},"2026-04-05",", an unambiguous ISO date, comes back as ",[304,305,306],"strong",{},"4 May",": with ",[13,309,310],{},"format=\"mixed\"",", the ",[13,313,209],{}," flag is applied to ISO strings too. The real Excel date fares no better once it has been turned into text for parsing: ",[13,316,317],{},"2026-04-09 00:00:00"," comes back as 4 September. Switching to month-first fixes those rows and breaks London. No single setting works, and neither raises an error.",[320,321,329,330,329,334,329,338,329,346,329,354,329,360,329,364,329,368,329,371,329,376,329,378,329,380,329,383,329,387,329,389,329,391,329,394,329,398,329,400,329,402,329,406,329,410,329,414,329,418,329,420,329,423,329,428,329,432,329,434,329,437,329,441,329,445,329,447,329,450,329,454,329,458,329,464,329,468,329,474,329,479,329,487],"svg",{"viewBox":322,"role":323,"ariaLabelledBy":324,"xmlns":327,"style":328},"4 0 752 168","img",[325,326],"md-wrong-t","md-wrong-d","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;max-width:752px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif","\n  ",[331,332,333],"title",{"id":325},"One parsing setting, silently wrong rows",[335,336,337],"desc",{"id":326},"Raw values 03\u002F04\u002F2026 from London, 04\u002F13\u002F2026 from New York and 2026-04-05 from the ERP. Parsed with format mixed and dayfirst true, London is correct, the New York date is silently swapped to 13 April and the ISO date becomes 4 May.",[339,340],"rect",{"x":341,"y":342,"width":343,"height":344,"fill":345},"4","0","752","168","#ffffff",[339,347],{"x":348,"y":349,"width":350,"height":351,"rx":342,"fill":345,"stroke":352,"style":353},"20.0","40.0","85.4","28.0","var(--line,#cdd5e6)","stroke-width:1px",[355,356,69],"text",{"x":357,"y":358,"style":359},"62.7","59.0","font-size:11px;font-weight:700;fill:var(--text,#172033);text-anchor:middle",[339,361],{"x":362,"y":349,"width":363,"height":351,"rx":342,"fill":345,"stroke":352,"style":353},"105.4","94.9",[355,365,367],{"x":366,"y":358,"style":359},"152.8","OrderDate",[339,369],{"x":348,"y":370,"width":350,"height":351,"rx":342,"fill":345,"stroke":352,"style":353},"68.0",[355,372,375],{"x":357,"y":373,"style":374},"87.0","font-size:11px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","London",[339,377],{"x":362,"y":370,"width":363,"height":351,"rx":342,"fill":345,"stroke":352,"style":353},[355,379,15],{"x":366,"y":373,"style":374},[339,381],{"x":348,"y":382,"width":350,"height":351,"rx":342,"fill":345,"stroke":352,"style":353},"96.0",[355,384,386],{"x":357,"y":385,"style":374},"115.0","New York",[339,388],{"x":362,"y":382,"width":363,"height":351,"rx":342,"fill":345,"stroke":352,"style":353},[355,390,293],{"x":366,"y":385,"style":374},[339,392],{"x":348,"y":393,"width":350,"height":351,"rx":342,"fill":345,"stroke":352,"style":353},"124.0",[355,395,397],{"x":357,"y":396,"style":374},"143.0","ERP export",[339,399],{"x":362,"y":393,"width":363,"height":351,"rx":342,"fill":345,"stroke":352,"style":353},[355,401,301],{"x":366,"y":396,"style":374},[339,403],{"x":404,"y":349,"width":405,"height":351,"rx":342,"fill":345,"stroke":352,"style":353},"528.8","92.0",[355,407,409],{"x":408,"y":358,"style":359},"574.8","Parsed",[339,411],{"x":412,"y":349,"width":413,"height":351,"rx":342,"fill":345,"stroke":352,"style":353},"620.8","119.2",[355,415,417],{"x":416,"y":358,"style":359},"680.4","Correct?",[339,419],{"x":404,"y":370,"width":405,"height":351,"rx":342,"fill":345,"stroke":352,"style":353},[355,421,422],{"x":408,"y":373,"style":374},"3 Apr 2026",[339,424],{"x":412,"y":370,"width":413,"height":351,"rx":342,"fill":425,"stroke":426,"style":427},"#d9f4f1","var(--teal,#0f9488)","stroke-width:1.5px",[355,429,431],{"x":416,"y":373,"style":430},"font-size:11px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","yes",[339,433],{"x":404,"y":382,"width":405,"height":351,"rx":342,"fill":345,"stroke":352,"style":353},[355,435,436],{"x":408,"y":385,"style":374},"13 Apr 2026",[339,438],{"x":412,"y":382,"width":413,"height":351,"rx":342,"fill":439,"stroke":440,"style":427},"#fdefd8","var(--gold,#b4740a)",[355,442,444],{"x":416,"y":385,"style":443},"font-size:11px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","swapped silently",[339,446],{"x":404,"y":393,"width":405,"height":351,"rx":342,"fill":345,"stroke":352,"style":353},[355,448,449],{"x":408,"y":396,"style":374},"4 May 2026",[339,451],{"x":412,"y":393,"width":413,"height":351,"rx":342,"fill":452,"stroke":453,"style":427},"#fce9e9","var(--danger,#dc2626)",[355,455,457],{"x":416,"y":396,"style":456},"font-size:11px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","no — was 5 Apr",[355,459,463],{"x":460,"y":461,"style":462},"110.1","29.0","font-size:12.5px;font-weight:700;fill:var(--muted,#5b6780);text-anchor:middle","raw text",[355,465,467],{"x":466,"y":461,"style":462},"634.4","parsed",[45,469],{"x1":470,"y1":382,"x2":471,"y2":382,"stroke":472,"style":473},"210.3","514.8","var(--brand,#5b5cf0)","stroke-width:2px",[475,476],"polygon",{"points":477,"fill":478},"518.8,96.0 509.8,101.0 509.8,91.0","#5b5cf0",[339,480],{"x":481,"y":482,"width":483,"height":484,"rx":485,"fill":345,"stroke":352,"style":486},"249.1","63.0","230.8","22.0","11","stroke-width:1.2px",[355,488,289],{"x":489,"y":490,"style":491},"364.5","78.0","font-size:11.5px;font-weight:400;fill:var(--brand-strong,#4338ca);text-anchor:middle;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace",[29,493,495],{"id":494},"step-2-classify-every-value","Step 2 — Classify every value",[10,497,498],{},"Parse nothing yet. Describe each value instead: is it already a date, an ISO string, a slash date whose first or second part is above 12, or a slash date where both parts could be a month?",[34,500,502],{"className":77,"code":501,"language":79,"meta":39,"style":39},"import datetime as dt\nimport re\n\nSLASH = re.compile(r\"^(\\d{1,2})[\u002F.-](\\d{1,2})[\u002F.-](\\d{4})$\")\nISO = re.compile(r\"^\\d{4}-\\d{2}-\\d{2}$\")\n\ndef classify(value):\n    if isinstance(value, (dt.datetime, pd.Timestamp)):\n        return \"excel date\"\n    s = str(value).strip()\n    if ISO.match(s):\n        return \"iso\"\n    m = SLASH.match(s)\n    if m:\n        a, b = int(m.group(1)), int(m.group(2))\n        if a > 12 and b \u003C= 12:\n            return \"day-first\"\n        if b > 12 and a \u003C= 12:\n            return \"month-first\"\n        if a \u003C= 12 and b \u003C= 12:\n            return \"ambiguous\"\n        return \"invalid\"\n    return \"other text\"\n\norders[\"Kind\"] = orders[\"OrderDate\"].map(classify)\nprint(orders[[\"OrderID\", \"Source\", \"OrderDate\", \"Kind\"]].to_string(index=False))\n",[13,503,504,516,523,527,578,618,622,634,645,653,666,676,684,698,706,736,765,774,795,803,824,832,840,849,854,874],{"__ignoreMap":39},[43,505,506,508,511,513],{"class":45,"line":46},[43,507,87],{"class":86},[43,509,510],{"class":90}," datetime ",[43,512,94],{"class":86},[43,514,515],{"class":90}," dt\n",[43,517,518,520],{"class":45,"line":100},[43,519,87],{"class":86},[43,521,522],{"class":90}," re\n",[43,524,525],{"class":45,"line":107},[43,526,104],{"emptyLinePlaceholder":103},[43,528,529,532,535,538,541,544,547,550,553,557,560,562,564,566,568,571,574,576],{"class":45,"line":125},[43,530,531],{"class":128},"SLASH",[43,533,534],{"class":86}," =",[43,536,537],{"class":90}," re.compile(",[43,539,540],{"class":86},"r",[43,542,543],{"class":53},"\"",[43,545,546],{"class":128},"^(\\d",[43,548,549],{"class":86},"{1,2}",[43,551,552],{"class":128},")[",[43,554,556],{"class":555},"sSjpA","\u002F.-",[43,558,559],{"class":128},"](\\d",[43,561,549],{"class":86},[43,563,552],{"class":128},[43,565,556],{"class":555},[43,567,559],{"class":128},[43,569,570],{"class":86},"{4}",[43,572,573],{"class":128},")$",[43,575,543],{"class":53},[43,577,122],{"class":90},[43,579,580,583,585,587,589,591,594,596,599,602,605,607,609,611,614,616],{"class":45,"line":147},[43,581,582],{"class":128},"ISO",[43,584,534],{"class":86},[43,586,537],{"class":90},[43,588,540],{"class":86},[43,590,543],{"class":53},[43,592,593],{"class":128},"^\\d",[43,595,570],{"class":86},[43,597,598],{"class":53},"-",[43,600,601],{"class":128},"\\d",[43,603,604],{"class":86},"{2}",[43,606,598],{"class":53},[43,608,601],{"class":128},[43,610,604],{"class":86},[43,612,613],{"class":128},"$",[43,615,543],{"class":53},[43,617,122],{"class":90},[43,619,620],{"class":45,"line":168},[43,621,104],{"emptyLinePlaceholder":103},[43,623,624,627,631],{"class":45,"line":179},[43,625,626],{"class":86},"def",[43,628,630],{"class":629},"s_Opv"," classify",[43,632,633],{"class":90},"(value):\n",[43,635,636,639,642],{"class":45,"line":188},[43,637,638],{"class":86},"    if",[43,640,641],{"class":128}," isinstance",[43,643,644],{"class":90},"(value, (dt.datetime, pd.Timestamp)):\n",[43,646,647,650],{"class":45,"line":220},[43,648,649],{"class":86},"        return",[43,651,652],{"class":53}," \"excel date\"\n",[43,654,655,658,660,663],{"class":45,"line":245},[43,656,657],{"class":90},"    s ",[43,659,113],{"class":86},[43,661,662],{"class":128}," str",[43,664,665],{"class":90},"(value).strip()\n",[43,667,668,670,673],{"class":45,"line":251},[43,669,638],{"class":86},[43,671,672],{"class":128}," ISO",[43,674,675],{"class":90},".match(s):\n",[43,677,679,681],{"class":45,"line":678},12,[43,680,649],{"class":86},[43,682,683],{"class":53}," \"iso\"\n",[43,685,687,690,692,695],{"class":45,"line":686},13,[43,688,689],{"class":90},"    m ",[43,691,113],{"class":86},[43,693,694],{"class":128}," SLASH",[43,696,697],{"class":90},".match(s)\n",[43,699,701,703],{"class":45,"line":700},14,[43,702,638],{"class":86},[43,704,705],{"class":90}," m:\n",[43,707,709,712,714,717,720,723,726,729,731,734],{"class":45,"line":708},15,[43,710,711],{"class":90},"        a, b ",[43,713,113],{"class":86},[43,715,716],{"class":128}," int",[43,718,719],{"class":90},"(m.group(",[43,721,722],{"class":128},"1",[43,724,725],{"class":90},")), ",[43,727,728],{"class":128},"int",[43,730,719],{"class":90},[43,732,733],{"class":128},"2",[43,735,279],{"class":90},[43,737,739,742,745,748,751,754,757,760,762],{"class":45,"line":738},16,[43,740,741],{"class":86},"        if",[43,743,744],{"class":90}," a ",[43,746,747],{"class":86},">",[43,749,750],{"class":128}," 12",[43,752,753],{"class":86}," and",[43,755,756],{"class":90}," b ",[43,758,759],{"class":86},"\u003C=",[43,761,750],{"class":128},[43,763,764],{"class":90},":\n",[43,766,768,771],{"class":45,"line":767},17,[43,769,770],{"class":86},"            return",[43,772,773],{"class":53}," \"day-first\"\n",[43,775,777,779,781,783,785,787,789,791,793],{"class":45,"line":776},18,[43,778,741],{"class":86},[43,780,756],{"class":90},[43,782,747],{"class":86},[43,784,750],{"class":128},[43,786,753],{"class":86},[43,788,744],{"class":90},[43,790,759],{"class":86},[43,792,750],{"class":128},[43,794,764],{"class":90},[43,796,798,800],{"class":45,"line":797},19,[43,799,770],{"class":86},[43,801,802],{"class":53}," \"month-first\"\n",[43,804,806,808,810,812,814,816,818,820,822],{"class":45,"line":805},20,[43,807,741],{"class":86},[43,809,744],{"class":90},[43,811,759],{"class":86},[43,813,750],{"class":128},[43,815,753],{"class":86},[43,817,756],{"class":90},[43,819,759],{"class":86},[43,821,750],{"class":128},[43,823,764],{"class":90},[43,825,827,829],{"class":45,"line":826},21,[43,828,770],{"class":86},[43,830,831],{"class":53}," \"ambiguous\"\n",[43,833,835,837],{"class":45,"line":834},22,[43,836,649],{"class":86},[43,838,839],{"class":53}," \"invalid\"\n",[43,841,843,846],{"class":45,"line":842},23,[43,844,845],{"class":86},"    return",[43,847,848],{"class":53}," \"other text\"\n",[43,850,852],{"class":45,"line":851},24,[43,853,104],{"emptyLinePlaceholder":103},[43,855,857,859,862,865,867,869,871],{"class":45,"line":856},25,[43,858,263],{"class":90},[43,860,861],{"class":53},"\"Kind\"",[43,863,864],{"class":90},"] ",[43,866,113],{"class":86},[43,868,155],{"class":90},[43,870,135],{"class":53},[43,872,873],{"class":90},"].map(classify)\n",[43,875,877,879,882,885,887,889,891,893,895,897,900,902,904,906],{"class":45,"line":876},26,[43,878,129],{"class":128},[43,880,881],{"class":90},"(orders[[",[43,883,884],{"class":53},"\"OrderID\"",[43,886,206],{"class":90},[43,888,266],{"class":53},[43,890,206],{"class":90},[43,892,135],{"class":53},[43,894,206],{"class":90},[43,896,861],{"class":53},[43,898,899],{"class":90},"]].to_string(",[43,901,272],{"class":197},[43,903,113],{"class":86},[43,905,240],{"class":128},[43,907,279],{"class":90},[10,909,910,911,914,915,917,918,921],{},"Only three rows are decided by their own digits — ",[13,912,913],{},"21\u002F04\u002F2026"," (day-first), ",[13,916,293],{}," and ",[13,919,920],{},"12\u002F30\u002F2026"," (month-first). Four slash dates are ambiguous, the ERP rows are ISO, one row is a genuine Excel date, and one is written-out text. That is typical: in most months, most slash dates are ambiguous, because both the day and the month are 12 or less on 40% of days.",[320,923,329,929,329,932,329,935,329,939,329,945,329,951,329,955,329,959,329,962,329,966,329,969,329,973,329,975,329,979,329,982,329,985,329,988,329,992,329,995,329,998,329,1001,329,1005,329,1007,329,1009,329,1012,329,1016,329,1018,329,1021],{"viewBox":924,"role":323,"ariaLabelledBy":925,"xmlns":327,"style":928},"4 0 744 286",[926,927],"md-kinds-t","md-kinds-d","width:100%;max-width:744px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[331,930,931],{"id":926},"What the eleven date values turned out to be",[335,933,934],{"id":927},"Four values are ambiguous slash dates, two are unambiguous month-first, one unambiguous day-first, two ISO strings, one a real Excel date and one written-out text.",[339,936],{"x":341,"y":342,"width":937,"height":938,"fill":345},"744","286",[339,940],{"x":348,"y":941,"width":942,"height":351,"rx":943,"fill":944,"stroke":352,"style":353},"16.0","197.5","7","#e7ebef",[355,946,950],{"x":947,"y":948,"style":949},"118.8","34.5","font-size:12.5px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","ambiguous slash date",[339,952],{"x":953,"y":941,"width":954,"height":351,"rx":943,"fill":452,"stroke":453,"style":427},"227.5","487.9",[355,956,341],{"x":957,"y":948,"style":958},"723.5","font-size:12px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:start",[339,960],{"x":348,"y":961,"width":942,"height":351,"rx":943,"fill":944,"stroke":352,"style":353},"56.0",[355,963,965],{"x":947,"y":964,"style":949},"74.5","month-first (2nd part > 12)",[339,967],{"x":953,"y":961,"width":968,"height":351,"rx":943,"fill":425,"stroke":426,"style":427},"244.0",[355,970,733],{"x":971,"y":964,"style":972},"479.5","font-size:12px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:start",[339,974],{"x":348,"y":382,"width":942,"height":351,"rx":943,"fill":944,"stroke":352,"style":353},[355,976,978],{"x":947,"y":977,"style":949},"114.5","day-first (1st part > 12)",[339,980],{"x":953,"y":382,"width":981,"height":351,"rx":943,"fill":425,"stroke":426,"style":427},"122.0",[355,983,722],{"x":984,"y":977,"style":972},"357.5",[339,986],{"x":348,"y":987,"width":942,"height":351,"rx":943,"fill":944,"stroke":352,"style":353},"136.0",[355,989,991],{"x":947,"y":990,"style":949},"154.5","ISO yyyy-mm-dd",[339,993],{"x":953,"y":987,"width":968,"height":351,"rx":943,"fill":994,"stroke":472,"style":427},"#f0f4ff",[355,996,733],{"x":971,"y":990,"style":997},"font-size:12px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:start",[339,999],{"x":348,"y":1000,"width":942,"height":351,"rx":943,"fill":944,"stroke":352,"style":353},"176.0",[355,1002,1004],{"x":947,"y":1003,"style":949},"194.5","real Excel date",[339,1006],{"x":953,"y":1000,"width":981,"height":351,"rx":943,"fill":994,"stroke":472,"style":427},[355,1008,722],{"x":984,"y":1003,"style":997},[339,1010],{"x":348,"y":1011,"width":942,"height":351,"rx":943,"fill":944,"stroke":352,"style":353},"216.0",[355,1013,1015],{"x":947,"y":1014,"style":949},"234.5","written-out month",[339,1017],{"x":953,"y":1011,"width":981,"height":351,"rx":943,"fill":944,"stroke":352,"style":427},[355,1019,722],{"x":984,"y":1014,"style":1020},"font-size:12px;font-weight:700;fill:var(--text,#172033);text-anchor:start",[355,1022,1026],{"x":1023,"y":1024,"style":1025},"380.0","266.0","font-size:12.5px;font-weight:400;fill:var(--muted,#5b6780);text-anchor:middle","Only three of the seven slash dates decide their own convention.",[29,1028,1030],{"id":1029},"step-3-infer-each-sources-convention-from-its-unambiguous-rows","Step 3 — Infer each source's convention from its unambiguous rows",[10,1032,1033],{},"A source rarely mixes conventions internally. If any of its rows are unambiguously day-first and none month-first, the ambiguous ones are day-first too:",[34,1035,1037],{"className":77,"code":1036,"language":79,"meta":39,"style":39},"votes = (orders[orders[\"Kind\"].isin([\"day-first\", \"month-first\"])]\n         .groupby(\"Source\")[\"Kind\"].agg(lambda k: set(k)))\nconvention = {src: kinds.pop() for src, kinds in votes.items() if len(kinds) == 1}\nconflicts = [src for src, kinds in votes.items() if len(kinds) > 1]\nprint(\"convention by source:\", convention)\nprint(\"sources with conflicting evidence:\", conflicts)\n",[13,1038,1039,1065,1091,1131,1162,1175],{"__ignoreMap":39},[43,1040,1041,1044,1046,1049,1051,1054,1057,1059,1062],{"class":45,"line":46},[43,1042,1043],{"class":90},"votes ",[43,1045,113],{"class":86},[43,1047,1048],{"class":90}," (orders[orders[",[43,1050,861],{"class":53},[43,1052,1053],{"class":90},"].isin([",[43,1055,1056],{"class":53},"\"day-first\"",[43,1058,206],{"class":90},[43,1060,1061],{"class":53},"\"month-first\"",[43,1063,1064],{"class":90},"])]\n",[43,1066,1067,1070,1072,1074,1076,1079,1082,1085,1088],{"class":45,"line":100},[43,1068,1069],{"class":90},"         .groupby(",[43,1071,266],{"class":53},[43,1073,552],{"class":90},[43,1075,861],{"class":53},[43,1077,1078],{"class":90},"].agg(",[43,1080,1081],{"class":86},"lambda",[43,1083,1084],{"class":90}," k: ",[43,1086,1087],{"class":128},"set",[43,1089,1090],{"class":90},"(k)))\n",[43,1092,1093,1096,1098,1101,1104,1107,1110,1113,1116,1119,1122,1125,1128],{"class":45,"line":107},[43,1094,1095],{"class":90},"convention ",[43,1097,113],{"class":86},[43,1099,1100],{"class":90}," {src: kinds.pop() ",[43,1102,1103],{"class":86},"for",[43,1105,1106],{"class":90}," src, kinds ",[43,1108,1109],{"class":86},"in",[43,1111,1112],{"class":90}," votes.items() ",[43,1114,1115],{"class":86},"if",[43,1117,1118],{"class":128}," len",[43,1120,1121],{"class":90},"(kinds) ",[43,1123,1124],{"class":86},"==",[43,1126,1127],{"class":128}," 1",[43,1129,1130],{"class":90},"}\n",[43,1132,1133,1136,1138,1141,1143,1145,1147,1149,1151,1153,1155,1157,1159],{"class":45,"line":125},[43,1134,1135],{"class":90},"conflicts ",[43,1137,113],{"class":86},[43,1139,1140],{"class":90}," [src ",[43,1142,1103],{"class":86},[43,1144,1106],{"class":90},[43,1146,1109],{"class":86},[43,1148,1112],{"class":90},[43,1150,1115],{"class":86},[43,1152,1118],{"class":128},[43,1154,1121],{"class":90},[43,1156,747],{"class":86},[43,1158,1127],{"class":128},[43,1160,1161],{"class":90},"]\n",[43,1163,1164,1166,1169,1172],{"class":45,"line":147},[43,1165,129],{"class":128},[43,1167,1168],{"class":90},"(",[43,1170,1171],{"class":53},"\"convention by source:\"",[43,1173,1174],{"class":90},", convention)\n",[43,1176,1177,1179,1181,1184],{"class":45,"line":168},[43,1178,129],{"class":128},[43,1180,1168],{"class":90},[43,1182,1183],{"class":53},"\"sources with conflicting evidence:\"",[43,1185,1186],{"class":90},", conflicts)\n",[10,1188,1189,1190,1193,1194,1197],{},"London has one unambiguous day-first row, so its other rows are read day-first; New York has two month-first rows. Lyon has no deciding row at all, so its convention is unknown. A source that shows ",[18,1191,1192],{},"both"," kinds of evidence goes into ",[13,1195,1196],{},"conflicts"," — a sign that the sheet itself is mixed and needs a human. When sources are not recorded in the data, file names, sheet names or the user who submitted the file can serve the same purpose.",[320,1199,329,1204,329,1207,329,1210,329,1213,329,1219,329,1230,329,1234,329,1238,329,1242,329,1245,329,1248,329,1255,329,1259,329,1264,329,1271,329,1276,329,1281,329,1284,329,1287,329,1291,329,1294,329,1297,329,1303,329,1306,329,1309,329,1312,329,1315,329,1319,329,1322,329,1325,329,1331,329,1334,329,1337,329,1339,329,1342,329,1346,329,1349,329,1352,329,1359,329,1363],{"viewBox":1200,"role":323,"ariaLabelledBy":1201,"xmlns":327,"style":328},"4 0 752 272",[1202,1203],"md-rule-t","md-rule-d",[331,1205,1206],{"id":1202},"How each value gets its date",[335,1208,1209],{"id":1203},"Excel dates and ISO strings are converted directly. A slash date whose first part is above 12 is day-first, whose second part is above 12 is month-first. An ambiguous slash date takes its source's inferred convention, or is flagged for review if the source has no deciding rows.",[339,1211],{"x":341,"y":342,"width":343,"height":1212,"fill":345},"272",[339,1214],{"x":1215,"y":941,"width":1216,"height":1217,"rx":1218,"fill":994,"stroke":472,"style":473},"240.0","280.0","75.5","12",[1220,1221,1223],"g",{"transform":1222},"translate(368.0,29.0) scale(1.000)",[1224,1225],"path",{"d":1226,"fill":1227,"stroke":1228,"style":1229},"M11 4a7 7 0 1 0 .01 0z M16 16l5 5","none","var(--brand-strong,#4338ca)","stroke-width:1.80px;stroke-linecap:round;stroke-linejoin:round",[355,1231,1233],{"x":1023,"y":1217,"style":1232},"font-size:13.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","What kind of value is it?",[45,1235],{"x1":1023,"y1":1236,"x2":1023,"y2":1237,"stroke":472,"style":473},"91.5","111.5",[45,1239],{"x1":1240,"y1":1237,"x2":1241,"y2":1237,"stroke":472,"style":473},"104.0","656.0",[45,1243],{"x1":1240,"y1":1237,"x2":1240,"y2":1244,"stroke":472,"style":473},"157.5",[475,1246],{"points":1247,"fill":478},"104.0,161.5 99.0,152.5 109.0,152.5",[339,1249],{"x":1250,"y":1251,"width":1252,"height":1253,"rx":1254,"fill":345,"stroke":352,"style":486},"62.6","121.5","82.9","21.0","10",[355,1256,1258],{"x":1240,"y":987,"style":1257},"font-size:11.5px;font-weight:700;fill:var(--muted,#5b6780);text-anchor:middle","date or ISO",[339,1260],{"x":348,"y":1261,"width":1262,"height":1263,"rx":1218,"fill":425,"stroke":426,"style":473},"163.5","168.0","93.0",[1220,1265,1267],{"transform":1266},"translate(92.0,176.5) scale(1.000)",[1224,1268],{"d":1269,"fill":1227,"stroke":1270,"style":1229},"M5 12.5l4.5 4.5L19 7","var(--teal-ink,#0b6157)",[355,1272,1275],{"x":1240,"y":1273,"style":1274},"223.0","font-size:13.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","Use as is",[355,1277,1280],{"x":1240,"y":1278,"style":1279},"242.5","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","no guessing needed",[45,1282],{"x1":1283,"y1":1237,"x2":1283,"y2":1244,"stroke":472,"style":473},"288.0",[475,1285],{"points":1286,"fill":478},"288.0,161.5 283.0,152.5 293.0,152.5",[339,1288],{"x":1289,"y":1251,"width":1290,"height":1253,"rx":1254,"fill":345,"stroke":352,"style":486},"253.7","68.7",[355,1292,1293],{"x":1283,"y":987,"style":1257},"part > 12",[339,1295],{"x":1296,"y":1261,"width":1262,"height":1263,"rx":1218,"fill":425,"stroke":426,"style":473},"204.0",[1220,1298,1300],{"transform":1299},"translate(276.0,176.5) scale(1.000)",[1224,1301],{"d":1302,"fill":1227,"stroke":1270,"style":1229},"M5 9h14 M4 15h14 M10 4l-2 16 M16 4l-2 16",[355,1304,1305],{"x":1283,"y":1273,"style":1274},"Decided by digits",[355,1307,1308],{"x":1283,"y":1278,"style":1279},"day-first or month-first",[45,1310],{"x1":1311,"y1":1237,"x2":1311,"y2":1244,"stroke":472,"style":473},"472.0",[475,1313],{"points":1314,"fill":478},"472.0,161.5 467.0,152.5 477.0,152.5",[339,1316],{"x":1317,"y":1251,"width":1318,"height":1253,"rx":1254,"fill":345,"stroke":352,"style":486},"421.3","101.5",[355,1320,1321],{"x":1311,"y":987,"style":1257},"known source",[339,1323],{"x":1324,"y":1261,"width":1262,"height":1263,"rx":1218,"fill":994,"stroke":472,"style":473},"388.0",[1220,1326,1328],{"transform":1327},"translate(460.0,176.5) scale(1.000)",[1224,1329],{"d":1330,"fill":1227,"stroke":1228,"style":1229},"M9 11a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7z M2.5 20c0-3.6 2.9-6 6.5-6s6.5 2.4 6.5 6 M16 4.5a3.3 3.3 0 0 1 0 6.3 M18 14.3c2.2.7 3.5 2.8 3.5 5.7",[355,1332,1333],{"x":1311,"y":1273,"style":1232},"Source convention",[355,1335,1336],{"x":1311,"y":1278,"style":1279},"from unambiguous rows",[45,1338],{"x1":1241,"y1":1237,"x2":1241,"y2":1244,"stroke":472,"style":473},[475,1340],{"points":1341,"fill":478},"656.0,161.5 651.0,152.5 661.0,152.5",[339,1343],{"x":1344,"y":1251,"width":1345,"height":1253,"rx":1254,"fill":345,"stroke":352,"style":486},"597.7","116.5",[355,1347,1348],{"x":1241,"y":987,"style":1257},"unknown source",[339,1350],{"x":1351,"y":1261,"width":1262,"height":1263,"rx":1218,"fill":452,"stroke":453,"style":473},"572.0",[1220,1353,1355],{"transform":1354},"translate(644.0,176.5) scale(1.000)",[1224,1356],{"d":1357,"fill":1227,"stroke":1358,"style":1229},"M12 3.5l9.5 17h-19z M12 10v5 M12 17.8v.4","var(--accent-ink,#be185d)",[355,1360,1362],{"x":1241,"y":1273,"style":1361},"font-size:13.5px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","Flag for review",[355,1364,1365],{"x":1241,"y":1278,"style":1279},"do not guess",[29,1367,1369],{"id":1368},"step-4-parse-every-row-with-an-explicit-format","Step 4 — Parse every row with an explicit format",[10,1371,1372],{},"With a kind and a convention per row, each value is parsed with a format that cannot be misread:",[34,1374,1376],{"className":77,"code":1375,"language":79,"meta":39,"style":39},"FORMATS = {\"day-first\": \"%d\u002F%m\u002F%Y\", \"month-first\": \"%m\u002F%d\u002F%Y\", \"iso\": \"%Y-%m-%d\"}\n\ndef parse(row):\n    kind, value = row[\"Kind\"], row[\"OrderDate\"]\n    if kind == \"excel date\":\n        return pd.Timestamp(value)\n    if kind == \"ambiguous\":\n        kind = convention.get(row[\"Source\"], \"unknown\")\n    if kind in FORMATS:\n        s = re.sub(r\"[.-]\", \"\u002F\", str(value).strip()) if kind != \"iso\" else str(value).strip()\n        return pd.to_datetime(s, format=FORMATS[kind])\n    if kind == \"other text\":\n        return pd.to_datetime(str(value), format=\"%d %b %Y\", errors=\"coerce\")\n    return pd.NaT\n\norders[\"Date\"] = orders.apply(parse, axis=1)\norders[\"Needs review\"] = orders[\"Date\"].isna()\nprint(orders[[\"OrderID\", \"Source\", \"OrderDate\", \"Date\", \"Needs review\"]].to_string(index=False))\n",[13,1377,1378,1431,1435,1445,1464,1478,1485,1498,1518,1531,1585,1601,1614,1652,1659,1663,1686,1704],{"__ignoreMap":39},[43,1379,1380,1383,1385,1388,1390,1393,1395,1398,1401,1403,1405,1407,1410,1412,1415,1417,1420,1422,1425,1427,1429],{"class":45,"line":46},[43,1381,1382],{"class":128},"FORMATS",[43,1384,534],{"class":86},[43,1386,1387],{"class":90}," {",[43,1389,1056],{"class":53},[43,1391,1392],{"class":90},": ",[43,1394,543],{"class":53},[43,1396,1397],{"class":555},"%d",[43,1399,1400],{"class":53},"\u002F%m\u002F%Y\"",[43,1402,206],{"class":90},[43,1404,1061],{"class":53},[43,1406,1392],{"class":90},[43,1408,1409],{"class":53},"\"%m\u002F",[43,1411,1397],{"class":555},[43,1413,1414],{"class":53},"\u002F%Y\"",[43,1416,206],{"class":90},[43,1418,1419],{"class":53},"\"iso\"",[43,1421,1392],{"class":90},[43,1423,1424],{"class":53},"\"%Y-%m-",[43,1426,1397],{"class":555},[43,1428,543],{"class":53},[43,1430,1130],{"class":90},[43,1432,1433],{"class":45,"line":100},[43,1434,104],{"emptyLinePlaceholder":103},[43,1436,1437,1439,1442],{"class":45,"line":107},[43,1438,626],{"class":86},[43,1440,1441],{"class":629}," parse",[43,1443,1444],{"class":90},"(row):\n",[43,1446,1447,1450,1452,1455,1457,1460,1462],{"class":45,"line":125},[43,1448,1449],{"class":90},"    kind, value ",[43,1451,113],{"class":86},[43,1453,1454],{"class":90}," row[",[43,1456,861],{"class":53},[43,1458,1459],{"class":90},"], row[",[43,1461,135],{"class":53},[43,1463,1161],{"class":90},[43,1465,1466,1468,1471,1473,1476],{"class":45,"line":147},[43,1467,638],{"class":86},[43,1469,1470],{"class":90}," kind ",[43,1472,1124],{"class":86},[43,1474,1475],{"class":53}," \"excel date\"",[43,1477,764],{"class":90},[43,1479,1480,1482],{"class":45,"line":168},[43,1481,649],{"class":86},[43,1483,1484],{"class":90}," pd.Timestamp(value)\n",[43,1486,1487,1489,1491,1493,1496],{"class":45,"line":179},[43,1488,638],{"class":86},[43,1490,1470],{"class":90},[43,1492,1124],{"class":86},[43,1494,1495],{"class":53}," \"ambiguous\"",[43,1497,764],{"class":90},[43,1499,1500,1503,1505,1508,1510,1513,1516],{"class":45,"line":188},[43,1501,1502],{"class":90},"        kind ",[43,1504,113],{"class":86},[43,1506,1507],{"class":90}," convention.get(row[",[43,1509,266],{"class":53},[43,1511,1512],{"class":90},"], ",[43,1514,1515],{"class":53},"\"unknown\"",[43,1517,122],{"class":90},[43,1519,1520,1522,1524,1526,1529],{"class":45,"line":220},[43,1521,638],{"class":86},[43,1523,1470],{"class":90},[43,1525,1109],{"class":86},[43,1527,1528],{"class":128}," FORMATS",[43,1530,764],{"class":90},[43,1532,1533,1536,1538,1541,1543,1545,1548,1551,1554,1556,1558,1561,1563,1565,1568,1570,1572,1575,1578,1581,1583],{"class":45,"line":245},[43,1534,1535],{"class":90},"        s ",[43,1537,113],{"class":86},[43,1539,1540],{"class":90}," re.sub(",[43,1542,540],{"class":86},[43,1544,543],{"class":53},[43,1546,1547],{"class":128},"[",[43,1549,1550],{"class":555},".-",[43,1552,1553],{"class":128},"]",[43,1555,543],{"class":53},[43,1557,206],{"class":90},[43,1559,1560],{"class":53},"\"\u002F\"",[43,1562,206],{"class":90},[43,1564,163],{"class":128},[43,1566,1567],{"class":90},"(value).strip()) ",[43,1569,1115],{"class":86},[43,1571,1470],{"class":90},[43,1573,1574],{"class":86},"!=",[43,1576,1577],{"class":53}," \"iso\"",[43,1579,1580],{"class":86}," else",[43,1582,662],{"class":128},[43,1584,665],{"class":90},[43,1586,1587,1589,1592,1594,1596,1598],{"class":45,"line":251},[43,1588,649],{"class":86},[43,1590,1591],{"class":90}," pd.to_datetime(s, ",[43,1593,198],{"class":197},[43,1595,113],{"class":86},[43,1597,1382],{"class":128},[43,1599,1600],{"class":90},"[kind])\n",[43,1602,1603,1605,1607,1609,1612],{"class":45,"line":678},[43,1604,638],{"class":86},[43,1606,1470],{"class":90},[43,1608,1124],{"class":86},[43,1610,1611],{"class":53}," \"other text\"",[43,1613,764],{"class":90},[43,1615,1616,1618,1621,1623,1626,1628,1630,1632,1634,1637,1640,1642,1645,1647,1650],{"class":45,"line":686},[43,1617,649],{"class":86},[43,1619,1620],{"class":90}," pd.to_datetime(",[43,1622,163],{"class":128},[43,1624,1625],{"class":90},"(value), ",[43,1627,198],{"class":197},[43,1629,113],{"class":86},[43,1631,543],{"class":53},[43,1633,1397],{"class":555},[43,1635,1636],{"class":555}," %b",[43,1638,1639],{"class":53}," %Y\"",[43,1641,206],{"class":90},[43,1643,1644],{"class":197},"errors",[43,1646,113],{"class":86},[43,1648,1649],{"class":53},"\"coerce\"",[43,1651,122],{"class":90},[43,1653,1654,1656],{"class":45,"line":700},[43,1655,845],{"class":86},[43,1657,1658],{"class":90}," pd.NaT\n",[43,1660,1661],{"class":45,"line":708},[43,1662,104],{"emptyLinePlaceholder":103},[43,1664,1665,1667,1670,1672,1674,1677,1680,1682,1684],{"class":45,"line":738},[43,1666,263],{"class":90},[43,1668,1669],{"class":53},"\"Date\"",[43,1671,864],{"class":90},[43,1673,113],{"class":86},[43,1675,1676],{"class":90}," orders.apply(parse, ",[43,1678,1679],{"class":197},"axis",[43,1681,113],{"class":86},[43,1683,722],{"class":128},[43,1685,122],{"class":90},[43,1687,1688,1690,1693,1695,1697,1699,1701],{"class":45,"line":767},[43,1689,263],{"class":90},[43,1691,1692],{"class":53},"\"Needs review\"",[43,1694,864],{"class":90},[43,1696,113],{"class":86},[43,1698,155],{"class":90},[43,1700,1669],{"class":53},[43,1702,1703],{"class":90},"].isna()\n",[43,1705,1706,1708,1710,1712,1714,1716,1718,1720,1722,1724,1726,1728,1730,1732,1734,1736],{"class":45,"line":776},[43,1707,129],{"class":128},[43,1709,881],{"class":90},[43,1711,884],{"class":53},[43,1713,206],{"class":90},[43,1715,266],{"class":53},[43,1717,206],{"class":90},[43,1719,135],{"class":53},[43,1721,206],{"class":90},[43,1723,1669],{"class":53},[43,1725,206],{"class":90},[43,1727,1692],{"class":53},[43,1729,899],{"class":90},[43,1731,272],{"class":197},[43,1733,113],{"class":86},[43,1735,240],{"class":128},[43,1737,279],{"class":90},[10,1739,1740,1741,1744,1745,1747,1748,1751,1752,1754,1755,1758,1759,1762,1763,1767],{},"Every parse uses a fixed format, so ",[13,1742,1743],{},"%d\u002F%m\u002F%Y"," will raise rather than swap if a value does not fit — the opposite of ",[13,1746,310],{},"'s helpful guessing. The ISO rows come out as 5 April and 2 November, New York's ",[13,1749,1750],{},"05\u002F02\u002F2026"," as 2 May, London's ",[13,1753,15],{}," as 3 April, and Lyon's ",[13,1756,1757],{},"06\u002F07\u002F2026"," as ",[13,1760,1761],{},"NaT",", flagged for review. For a single, consistent column, the simpler approach in ",[23,1764,1766],{"href":1765},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fparse-excel-dates-into-python-datetimes-with-pandas\u002F","Parse Excel Dates into Python Datetimes with pandas"," is enough.",[29,1769,1771],{"id":1770},"step-5-report-what-was-decided-and-how","Step 5 — Report what was decided and how",[10,1773,1774],{},"The people who own the data should see each decision, not just the result. Write the review rows and the evidence to the output:",[34,1776,1778],{"className":77,"code":1777,"language":79,"meta":39,"style":39},"orders[\"Rule\"] = orders[\"Kind\"].where(orders[\"Kind\"] != \"ambiguous\",\n                                      \"ambiguous → \" + orders[\"Source\"].map(convention).fillna(\"unknown\"))\nwith pd.ExcelWriter(\"orders_dates_checked.xlsx\", engine=\"xlsxwriter\", datetime_format=\"dd mmm yyyy\") as xw:\n    orders[[\"OrderID\", \"Source\", \"OrderDate\", \"Date\", \"Rule\", \"Needs review\"]].astype({\"OrderDate\": str}).to_excel(\n        xw, sheet_name=\"Dates\", index=False)\n    orders[orders[\"Needs review\"]].to_excel(xw, sheet_name=\"Review\", index=False)\nprint(orders[\"Rule\"].value_counts().to_dict())\n",[13,1779,1780,1809,1828,1867,1906,1929,1956],{"__ignoreMap":39},[43,1781,1782,1784,1787,1789,1791,1793,1795,1798,1800,1802,1804,1806],{"class":45,"line":46},[43,1783,263],{"class":90},[43,1785,1786],{"class":53},"\"Rule\"",[43,1788,864],{"class":90},[43,1790,113],{"class":86},[43,1792,155],{"class":90},[43,1794,861],{"class":53},[43,1796,1797],{"class":90},"].where(orders[",[43,1799,861],{"class":53},[43,1801,864],{"class":90},[43,1803,1574],{"class":86},[43,1805,1495],{"class":53},[43,1807,1808],{"class":90},",\n",[43,1810,1811,1814,1817,1819,1821,1824,1826],{"class":45,"line":100},[43,1812,1813],{"class":53},"                                      \"ambiguous → \"",[43,1815,1816],{"class":86}," +",[43,1818,155],{"class":90},[43,1820,266],{"class":53},[43,1822,1823],{"class":90},"].map(convention).fillna(",[43,1825,1515],{"class":53},[43,1827,279],{"class":90},[43,1829,1830,1833,1836,1839,1841,1844,1846,1849,1851,1854,1856,1859,1862,1864],{"class":45,"line":107},[43,1831,1832],{"class":86},"with",[43,1834,1835],{"class":90}," pd.ExcelWriter(",[43,1837,1838],{"class":53},"\"orders_dates_checked.xlsx\"",[43,1840,206],{"class":90},[43,1842,1843],{"class":197},"engine",[43,1845,113],{"class":86},[43,1847,1848],{"class":53},"\"xlsxwriter\"",[43,1850,206],{"class":90},[43,1852,1853],{"class":197},"datetime_format",[43,1855,113],{"class":86},[43,1857,1858],{"class":53},"\"dd mmm yyyy\"",[43,1860,1861],{"class":90},") ",[43,1863,94],{"class":86},[43,1865,1866],{"class":90}," xw:\n",[43,1868,1869,1872,1874,1876,1878,1880,1882,1884,1886,1888,1890,1892,1894,1897,1899,1901,1903],{"class":45,"line":125},[43,1870,1871],{"class":90},"    orders[[",[43,1873,884],{"class":53},[43,1875,206],{"class":90},[43,1877,266],{"class":53},[43,1879,206],{"class":90},[43,1881,135],{"class":53},[43,1883,206],{"class":90},[43,1885,1669],{"class":53},[43,1887,206],{"class":90},[43,1889,1786],{"class":53},[43,1891,206],{"class":90},[43,1893,1692],{"class":53},[43,1895,1896],{"class":90},"]].astype({",[43,1898,135],{"class":53},[43,1900,1392],{"class":90},[43,1902,163],{"class":128},[43,1904,1905],{"class":90},"}).to_excel(\n",[43,1907,1908,1911,1914,1916,1919,1921,1923,1925,1927],{"class":45,"line":147},[43,1909,1910],{"class":90},"        xw, ",[43,1912,1913],{"class":197},"sheet_name",[43,1915,113],{"class":86},[43,1917,1918],{"class":53},"\"Dates\"",[43,1920,206],{"class":90},[43,1922,272],{"class":197},[43,1924,113],{"class":86},[43,1926,240],{"class":128},[43,1928,122],{"class":90},[43,1930,1931,1934,1936,1939,1941,1943,1946,1948,1950,1952,1954],{"class":45,"line":168},[43,1932,1933],{"class":90},"    orders[orders[",[43,1935,1692],{"class":53},[43,1937,1938],{"class":90},"]].to_excel(xw, ",[43,1940,1913],{"class":197},[43,1942,113],{"class":86},[43,1944,1945],{"class":53},"\"Review\"",[43,1947,206],{"class":90},[43,1949,272],{"class":197},[43,1951,113],{"class":86},[43,1953,240],{"class":128},[43,1955,122],{"class":90},[43,1957,1958,1960,1962,1964],{"class":45,"line":179},[43,1959,129],{"class":128},[43,1961,132],{"class":90},[43,1963,1786],{"class":53},[43,1965,1966],{"class":90},"].value_counts().to_dict())\n",[10,1968,1969,1970,1973],{},"The output shows each original text, the parsed date written as ",[13,1971,1972],{},"dd mmm yyyy"," — a format nobody can misread — and the rule that produced it. The review sheet lists the Lyon order, which someone has to confirm with the office. Writing dates with month names in reports is cheap insurance against the next round of confusion.",[29,1975,1977],{"id":1976},"step-6-sanity-check-the-parsed-dates","Step 6 — Sanity-check the parsed dates",[10,1979,1980],{},"Even with explicit formats, a wrong convention for a whole source produces valid-looking dates. A plausibility check against what you know about the data catches it: order dates should fall inside the reporting period and not in the future.",[34,1982,1984],{"className":77,"code":1983,"language":79,"meta":39,"style":39},"period_start, period_end = pd.Timestamp(\"2026-01-01\"), pd.Timestamp(\"2026-12-31\")\noutside = orders[(orders[\"Date\"] \u003C period_start) | (orders[\"Date\"] > period_end)]\nprint(\"outside the period:\", outside[\"OrderID\"].tolist())\nby_month = orders.dropna(subset=[\"Date\"]).groupby(orders[\"Date\"].dt.to_period(\"M\"))[\"OrderID\"].count()\nprint(by_month.to_dict())\n",[13,1985,1986,2007,2042,2059,2097],{"__ignoreMap":39},[43,1987,1988,1991,1993,1996,1999,2002,2005],{"class":45,"line":46},[43,1989,1990],{"class":90},"period_start, period_end ",[43,1992,113],{"class":86},[43,1994,1995],{"class":90}," pd.Timestamp(",[43,1997,1998],{"class":53},"\"2026-01-01\"",[43,2000,2001],{"class":90},"), pd.Timestamp(",[43,2003,2004],{"class":53},"\"2026-12-31\"",[43,2006,122],{"class":90},[43,2008,2009,2012,2014,2017,2019,2021,2024,2027,2030,2033,2035,2037,2039],{"class":45,"line":100},[43,2010,2011],{"class":90},"outside ",[43,2013,113],{"class":86},[43,2015,2016],{"class":90}," orders[(orders[",[43,2018,1669],{"class":53},[43,2020,864],{"class":90},[43,2022,2023],{"class":86},"\u003C",[43,2025,2026],{"class":90}," period_start) ",[43,2028,2029],{"class":86},"|",[43,2031,2032],{"class":90}," (orders[",[43,2034,1669],{"class":53},[43,2036,864],{"class":90},[43,2038,747],{"class":86},[43,2040,2041],{"class":90}," period_end)]\n",[43,2043,2044,2046,2048,2051,2054,2056],{"class":45,"line":107},[43,2045,129],{"class":128},[43,2047,1168],{"class":90},[43,2049,2050],{"class":53},"\"outside the period:\"",[43,2052,2053],{"class":90},", outside[",[43,2055,884],{"class":53},[43,2057,2058],{"class":90},"].tolist())\n",[43,2060,2061,2064,2066,2069,2072,2074,2076,2078,2081,2083,2086,2089,2092,2094],{"class":45,"line":125},[43,2062,2063],{"class":90},"by_month ",[43,2065,113],{"class":86},[43,2067,2068],{"class":90}," orders.dropna(",[43,2070,2071],{"class":197},"subset",[43,2073,113],{"class":86},[43,2075,1547],{"class":90},[43,2077,1669],{"class":53},[43,2079,2080],{"class":90},"]).groupby(orders[",[43,2082,1669],{"class":53},[43,2084,2085],{"class":90},"].dt.to_period(",[43,2087,2088],{"class":53},"\"M\"",[43,2090,2091],{"class":90},"))[",[43,2093,884],{"class":53},[43,2095,2096],{"class":90},"].count()\n",[43,2098,2099,2101],{"class":45,"line":147},[43,2100,129],{"class":128},[43,2102,2103],{"class":90},"(by_month.to_dict())\n",[10,2105,2106],{},"No order falls outside 2026 here. The monthly counts are the second check: if a source's convention had been inferred wrongly, its orders would pile up in the first twelve days of the wrong months, or vanish from months with days above 12, and the distribution would look lumpy next to previous periods. Comparing this month's distribution with last month's is a cheap guard to add to a recurring job.",[29,2108,2110],{"id":2109},"common-pitfalls","Common pitfalls",[2112,2113,2114,2129,2135,2141,2147],"ul",{},[2115,2116,2117,2124,2125,2128],"li",{},[304,2118,2119,2121,2122,27],{},[13,2120,310],{}," with ",[13,2123,209],{}," It swaps unambiguous month-first dates ",[18,2126,2127],{},"and"," reinterprets ISO dates; never use it on a mixed column.",[2115,2130,2131,2134],{},[304,2132,2133],{},"Parsing before classifying."," Once parsed, you cannot tell a correct date from a swapped one.",[2115,2136,2137,2140],{},[304,2138,2139],{},"Assuming most dates are unambiguous."," Days 1–12 make up about 40% of the calendar.",[2115,2142,2143,2146],{},[304,2144,2145],{},"Inferring from one row per source."," One unambiguous row is evidence, not proof; flag sources with conflicting evidence.",[2115,2148,2149,2152,2153,2155],{},[304,2150,2151],{},"Excel dates as strings."," Real date cells arrive as ",[13,2154,285],{}," objects; convert them directly, never via text.",[29,2157,2159],{"id":2158},"conclusion","Conclusion",[10,2161,2162,2163,2121,2165,2167],{},"A column that mixes day-first, month-first, ISO and real Excel dates cannot be parsed with one setting, and ",[13,2164,310],{},[13,2166,209],{}," silently swaps the rows it gets wrong — ISO dates included. Classify each value, infer each source's convention from its unambiguous rows, parse every row with an explicit format, and send the rows that remain ambiguous to a person, with the rule used for every date written alongside the result.",[29,2169,2171],{"id":2170},"frequently-asked-questions","Frequently asked questions",[10,2173,2174,2177],{},[304,2175,2176],{},"How do I parse a column with both dd\u002Fmm\u002Fyyyy and mm\u002Fdd\u002Fyyyy dates?","\nClassify each value first: if the first part is above 12 it is day-first, if the second part is above 12 it is month-first, otherwise it is ambiguous. Resolve ambiguous rows from the convention of their source, then parse each row with an explicit format such as %d\u002F%m\u002F%Y or %m\u002F%d\u002F%Y.",[10,2179,2180,2183],{},[304,2181,2182],{},"Why does pd.to_datetime with dayfirst=True change my ISO dates?","\nWith format=\"mixed\", pandas applies the dayfirst preference to every value, including ISO strings such as 2026-04-05, which it then reads as 4 May. Parse ISO dates separately with format=\"%Y-%m-%d\".",[10,2185,2186,2189],{},[304,2187,2188],{},"Why doesn't pandas raise an error for 04\u002F13\u002F2026 with dayfirst=True?","\ndayfirst is a preference, not a rule: when the value cannot be day-first, the parser swaps to month-first silently. Use an explicit format, which raises or returns NaT for values that do not fit.",[10,2191,2192,2195],{},[304,2193,2194],{},"How can I tell whether 06\u002F07\u002F2026 is June or July?","\nFrom the value alone you cannot. Look for unambiguous dates from the same source, or ask the sender; otherwise flag the row for review rather than guessing.",[29,2197,2199],{"id":2198},"related","Related",[2112,2201,2202,2208,2215,2222],{},[2115,2203,2204,2205,2207],{},"Up one level: ",[23,2206,26],{"href":25}," — dates in spreadsheet data.",[2115,2209,2210,2214],{},[23,2211,2213],{"href":2212},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fconvert-text-dates-like-20240131-with-pandas\u002F","Convert Text Dates Like 20240131 with pandas"," — compact date strings.",[2115,2216,2217,2221],{},[23,2218,2220],{"href":2219},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Ffix-excel-serial-numbers-showing-instead-of-dates\u002F","Fix Excel Serial Numbers Showing Instead of Dates"," — when dates arrive as numbers.",[2115,2223,2224,2228],{},[23,2225,2227],{"href":2226},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Flocalise-an-excel-report-for-other-languages-and-locales\u002F","Localise an Excel Report for Other Languages and Locales"," — writing dates for different audiences.",[2230,2231,2232],"style",{},"html pre.shiki code .sMTad, html code.shiki .sMTad{--shiki-default:#6F42C1;--shiki-dark:#FFB757}html pre.shiki code .srMev, html code.shiki .srMev{--shiki-default:#032F62;--shiki-dark:#ADDCFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s-kum, html code.shiki .s-kum{--shiki-default:#D73A49;--shiki-dark:#FF9492}html pre.shiki code .skGVy, html code.shiki .skGVy{--shiki-default:#24292E;--shiki-dark:#F0F3F6}html pre.shiki code .sP0c6, html code.shiki .sP0c6{--shiki-default:#005CC5;--shiki-dark:#91CBFF}html pre.shiki code .sa561, html code.shiki .sa561{--shiki-default:#E36209;--shiki-dark:#FFB757}html pre.shiki code .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}html pre.shiki code .s_Opv, html code.shiki .s_Opv{--shiki-default:#6F42C1;--shiki-dark:#DBB7FF}",{"title":39,"searchDepth":100,"depth":100,"links":2234},[2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245],{"id":31,"depth":100,"text":32},{"id":73,"depth":100,"text":74},{"id":494,"depth":100,"text":495},{"id":1029,"depth":100,"text":1030},{"id":1368,"depth":100,"text":1369},{"id":1770,"depth":100,"text":1771},{"id":1976,"depth":100,"text":1977},{"id":2109,"depth":100,"text":2110},{"id":2158,"depth":100,"text":2159},{"id":2170,"depth":100,"text":2171},{"id":2198,"depth":100,"text":2199},"2026-10-02","A date column that combines 03\u002F04\u002F2026 from a UK office, 04\u002F13\u002F2026 from a US one, ISO dates from a system and real Excel dates cannot be parsed with one setting — and pandas' format=\"mixed\" with dayfirst=True silently swaps both unambiguous US dates and ISO dates. Classify each value, infer each source's convention from its unambiguous rows, parse with explicit formats, and flag what stays ambiguous.","md",[2250,2252,2254,2256],{"q":2176,"a":2251},"Classify each value first: if the first part is above 12 it is day-first, if the second part is above 12 it is month-first, otherwise it is ambiguous. Resolve ambiguous rows from the convention of their source, then parse each row with an explicit format such as %d\u002F%m\u002F%Y or %m\u002F%d\u002F%Y.",{"q":2182,"a":2253},"With format=\"mixed\", pandas applies the dayfirst preference to every value, including ISO strings such as 2026-04-05, which it then reads as 4 May. Parse ISO dates separately with format=\"%Y-%m-%d\".",{"q":2188,"a":2255},"dayfirst is a preference, not a rule: when the value cannot be day-first, the parser swaps to month-first silently. Use an explicit format, which raises or returns NaT for values that do not fit.",{"q":2194,"a":2257},"From the value alone you cannot. Look for unambiguous dates from the same source, or ask the sender; otherwise flag the row for review rather than guessing.","fix mixed day first and month first dates in excel data",null,{"breadcrumb":2261},[2262,2265,2268],{"name":2263,"item":2264},"Home","\u002F",{"name":2266,"item":2267},"Advanced Data Transformation and Cleaning for Excel Automation","\u002Fadvanced-data-transformation-and-cleaning\u002F",{"name":26,"item":25},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Ffix-mixed-day-first-and-month-first-dates-in-excel-data",{"title":2271,"description":2272},"Fix Mixed dd\u002Fmm and mm\u002Fdd Dates in Excel Data with pandas","Parse a column mixing day-first, month-first, ISO and real Excel dates: why to_datetime(format=\"mixed\", dayfirst=True) swaps 2026-04-05 and 04\u002F13\u002F2026, classifying values, inferring the convention per source, explicit formats, and flagging ambiguous dates.","fix-mixed-day-first-and-month-first-dates-in-excel-data","advanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Ffix-mixed-day-first-and-month-first-dates-in-excel-data\u002Findex",[2276,2277],"dates-and-times","data-cleaning","how-to","_MsqROgex4496wUPK8lnxXBX_1zqqGIXxLoF_arIZXE",[2281,2284],{"title":2220,"path":2282,"stem":2283,"children":-1},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Ffix-excel-serial-numbers-showing-instead-of-dates","advanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Ffix-excel-serial-numbers-showing-instead-of-dates\u002Findex",{"title":2285,"path":2286,"stem":2287,"children":-1},"Flag Public Holidays in Excel Data with Python","\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fflag-public-holidays-in-excel-data-with-python","advanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fflag-public-holidays-in-excel-data-with-python\u002Findex",[2289,2291],{"path":2290,"title":2266},"\u002Fadvanced-data-transformation-and-cleaning",{"path":2292,"title":26},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data",[],[2295,2298,2301,2304,2307,2310],{"path":2296,"title":2297,"kind":2278},"\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fhighlight-overdue-dates-with-openpyxl","Highlight Overdue Dates in Excel with openpyxl",{"path":2299,"title":2300,"kind":2278},"\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fhighlight-weekends-and-holidays-in-a-date-column","Highlight Weekends and Holidays in a Date Column",{"path":2302,"title":2303,"kind":2278},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fkeep-the-latest-record-per-key-with-pandas","Keep the Latest Record per Key When Deduplicating with pandas",{"path":2305,"title":2306,"kind":2278},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcreating-pivot-tables-from-excel-data\u002Fcalculate-moving-averages-with-pandas-rolling","Calculate Moving Averages with pandas rolling",{"path":2308,"title":2309,"kind":2278},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Feomonth-and-edate-equivalents-in-pandas","EOMONTH and EDATE Equivalents in pandas",{"path":2311,"title":2312,"kind":2278},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fyearfrac-and-days360-equivalents-in-python","YEARFRAC and DAYS360 Equivalents in Python",1790972106337]