[{"data":1,"prerenderedAt":2207},["ShallowReactive",2],{"doc:\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fconvert-text-months-and-weekdays-to-dates":3,"surround:\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fconvert-text-months-and-weekdays-to-dates":2173,"ancestors:\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fconvert-text-months-and-weekdays-to-dates":2182,"children:\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fconvert-text-months-and-weekdays-to-dates":2187,"related:\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fconvert-text-months-and-weekdays-to-dates":2188},{"id":4,"title":5,"body":6,"dateModified":2139,"datePublished":2139,"description":2140,"extension":2141,"faq":2142,"keyword":2151,"kind":2152,"meta":2153,"navigation":141,"path":2162,"seo":2163,"slug":2166,"stem":2167,"topics":2168,"type":2171,"__hash__":2172},"docs\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fconvert-text-months-and-weekdays-to-dates\u002Findex.md","Convert Text Months and Weekdays to Dates",{"type":7,"value":8,"toc":2127},"minimark",[9,68,73,102,109,113,563,591,750,754,1325,1350,1569,1573,1837,1866,1870,1883,1887,1902,1970,1974,2019,2023,2032,2036,2050,2059,2073,2083,2087,2123],[10,11,12,13,17,18,21,22,21,25,28,29,21,32,35,36,39,40,21,43,21,46,49,50,53,54,57,58,61,62,67],"p",{},"Spreadsheets kept by hand rarely store periods as dates. A column headed ",[14,15,16],"em",{},"Month"," holds ",[14,19,20],{},"Jan 2026",", ",[14,23,24],{},"February 2026",[14,26,27],{},"Sept-26","; another sheet has ",[14,30,31],{},"Q3 2026",[14,33,34],{},"Week 14"," or ",[14,37,38],{},"FY27 P03","; a rota lists ",[14,41,42],{},"Mon",[14,44,45],{},"Tue",[14,47,48],{},"Wed",". They read well, but they sort alphabetically — ",[14,51,52],{},"April"," before ",[14,55,56],{},"January"," — they cannot be filtered by date range, and they cannot be joined to a table keyed by real dates. Converting them is a matter of telling pandas exactly what each format means, plus handling the cases its parser does not know, such as ",[14,59,60],{},"Sept"," or a fiscal year that starts in April. This page converts each common kind of label into a real date or a pandas period, with one rule per format, and reports every label that matched none of them instead of turning it silently into a missing value. It belongs to ",[63,64,66],"a",{"href":65},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002F","Working with Dates and Times in Excel Data",".",[69,70,72],"h2",{"id":71},"prerequisites","Prerequisites",[74,75,80],"pre",{"className":76,"code":77,"language":78,"meta":79,"style":79},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install pandas openpyxl\n","bash","",[81,82,83],"code",{"__ignoreMap":79},[84,85,88,92,96,99],"span",{"class":86,"line":87},"line",1,[84,89,91],{"class":90},"sMTad","pip",[84,93,95],{"class":94},"srMev"," install",[84,97,98],{"class":94}," pandas",[84,100,101],{"class":94}," openpyxl\n",[10,103,104,105,108],{},"The examples work on small Series of labels, the way they arrive from a column read with ",[81,106,107],{},"read_excel",". Everything uses English month and day names; the last section shows how to handle other languages.",[69,110,112],{"id":111},"step-1-month-and-year-in-several-spellings","Step 1 — Month and year, in several spellings",[74,114,118],{"className":115,"code":116,"language":117,"meta":79,"style":79},"language-python shiki shiki-themes github-light github-dark-high-contrast","import pandas as pd\n\nmonths = pd.Series([\"Jan 2026\", \"February 2026\", \"Mar-26\", \"Sept-26\", \"2026-10\", \"Nov 26\", \"Dec. 2026\", \"Smarch 2026\"])\n\nFIX = {r\"\\bSept\\b\": \"Sep\", r\"\\bJune\\b\": \"Jun\", r\"\\bJuly\\b\": \"Jul\", r\"\\.\": \"\"}\nFORMATS = [\"%b %Y\", \"%B %Y\", \"%b-%y\", \"%Y-%m\", \"%b %y\"]\n\ndef parse_month(s):\n    clean = s.str.strip().replace(FIX, regex=True)\n    out = pd.Series(pd.NaT, index=s.index, dtype=\"datetime64[ns]\")\n    for fmt in FORMATS:\n        todo = out.isna()\n        out[todo] = pd.to_datetime(clean[todo], format=fmt, errors=\"coerce\")\n    return out.dt.to_period(\"M\")\n\nresult = pd.DataFrame({\"label\": months, \"month\": parse_month(months)})\nprint(result.to_string(index=False))\nprint(\"not parsed:\", result.loc[result[\"month\"].isna(), \"label\"].tolist())\n","python",[81,119,120,136,143,196,201,295,346,351,364,391,420,438,449,478,492,497,520,539],{"__ignoreMap":79},[84,121,122,126,130,133],{"class":86,"line":87},[84,123,125],{"class":124},"s-kum","import",[84,127,129],{"class":128},"skGVy"," pandas ",[84,131,132],{"class":124},"as",[84,134,135],{"class":128}," pd\n",[84,137,139],{"class":86,"line":138},2,[84,140,142],{"emptyLinePlaceholder":141},true,"\n",[84,144,146,149,152,155,158,160,163,165,168,170,173,175,178,180,183,185,188,190,193],{"class":86,"line":145},3,[84,147,148],{"class":128},"months ",[84,150,151],{"class":124},"=",[84,153,154],{"class":128}," pd.Series([",[84,156,157],{"class":94},"\"Jan 2026\"",[84,159,21],{"class":128},[84,161,162],{"class":94},"\"February 2026\"",[84,164,21],{"class":128},[84,166,167],{"class":94},"\"Mar-26\"",[84,169,21],{"class":128},[84,171,172],{"class":94},"\"Sept-26\"",[84,174,21],{"class":128},[84,176,177],{"class":94},"\"2026-10\"",[84,179,21],{"class":128},[84,181,182],{"class":94},"\"Nov 26\"",[84,184,21],{"class":128},[84,186,187],{"class":94},"\"Dec. 2026\"",[84,189,21],{"class":128},[84,191,192],{"class":94},"\"Smarch 2026\"",[84,194,195],{"class":128},"])\n",[84,197,199],{"class":86,"line":198},4,[84,200,142],{"emptyLinePlaceholder":141},[84,202,204,208,211,214,217,220,223,225,227,229,232,235,237,239,241,243,246,248,250,252,255,257,259,261,263,266,268,270,272,275,277,279,281,285,287,289,292],{"class":86,"line":203},5,[84,205,207],{"class":206},"sP0c6","FIX",[84,209,210],{"class":124}," =",[84,212,213],{"class":128}," {",[84,215,216],{"class":124},"r",[84,218,219],{"class":94},"\"",[84,221,222],{"class":206},"\\b",[84,224,60],{"class":94},[84,226,222],{"class":206},[84,228,219],{"class":94},[84,230,231],{"class":128},": ",[84,233,234],{"class":94},"\"Sep\"",[84,236,21],{"class":128},[84,238,216],{"class":124},[84,240,219],{"class":94},[84,242,222],{"class":206},[84,244,245],{"class":94},"June",[84,247,222],{"class":206},[84,249,219],{"class":94},[84,251,231],{"class":128},[84,253,254],{"class":94},"\"Jun\"",[84,256,21],{"class":128},[84,258,216],{"class":124},[84,260,219],{"class":94},[84,262,222],{"class":206},[84,264,265],{"class":94},"July",[84,267,222],{"class":206},[84,269,219],{"class":94},[84,271,231],{"class":128},[84,273,274],{"class":94},"\"Jul\"",[84,276,21],{"class":128},[84,278,216],{"class":124},[84,280,219],{"class":94},[84,282,284],{"class":283},"s_b0D","\\.",[84,286,219],{"class":94},[84,288,231],{"class":128},[84,290,291],{"class":94},"\"\"",[84,293,294],{"class":128},"}\n",[84,296,298,301,303,306,308,312,315,317,320,322,324,326,329,331,334,336,338,340,343],{"class":86,"line":297},6,[84,299,300],{"class":206},"FORMATS",[84,302,210],{"class":124},[84,304,305],{"class":128}," [",[84,307,219],{"class":94},[84,309,311],{"class":310},"sSjpA","%b",[84,313,314],{"class":94}," %Y\"",[84,316,21],{"class":128},[84,318,319],{"class":94},"\"%B %Y\"",[84,321,21],{"class":128},[84,323,219],{"class":94},[84,325,311],{"class":310},[84,327,328],{"class":94},"-%y\"",[84,330,21],{"class":128},[84,332,333],{"class":94},"\"%Y-%m\"",[84,335,21],{"class":128},[84,337,219],{"class":94},[84,339,311],{"class":310},[84,341,342],{"class":94}," %y\"",[84,344,345],{"class":128},"]\n",[84,347,349],{"class":86,"line":348},7,[84,350,142],{"emptyLinePlaceholder":141},[84,352,354,357,361],{"class":86,"line":353},8,[84,355,356],{"class":124},"def",[84,358,360],{"class":359},"s_Opv"," parse_month",[84,362,363],{"class":128},"(s):\n",[84,365,367,370,372,375,377,379,383,385,388],{"class":86,"line":366},9,[84,368,369],{"class":128},"    clean ",[84,371,151],{"class":124},[84,373,374],{"class":128}," s.str.strip().replace(",[84,376,207],{"class":206},[84,378,21],{"class":128},[84,380,382],{"class":381},"sa561","regex",[84,384,151],{"class":124},[84,386,387],{"class":206},"True",[84,389,390],{"class":128},")\n",[84,392,394,397,399,402,405,407,410,413,415,418],{"class":86,"line":393},10,[84,395,396],{"class":128},"    out ",[84,398,151],{"class":124},[84,400,401],{"class":128}," pd.Series(pd.NaT, ",[84,403,404],{"class":381},"index",[84,406,151],{"class":124},[84,408,409],{"class":128},"s.index, ",[84,411,412],{"class":381},"dtype",[84,414,151],{"class":124},[84,416,417],{"class":94},"\"datetime64[ns]\"",[84,419,390],{"class":128},[84,421,423,426,429,432,435],{"class":86,"line":422},11,[84,424,425],{"class":124},"    for",[84,427,428],{"class":128}," fmt ",[84,430,431],{"class":124},"in",[84,433,434],{"class":206}," FORMATS",[84,436,437],{"class":128},":\n",[84,439,441,444,446],{"class":86,"line":440},12,[84,442,443],{"class":128},"        todo ",[84,445,151],{"class":124},[84,447,448],{"class":128}," out.isna()\n",[84,450,452,455,457,460,463,465,468,471,473,476],{"class":86,"line":451},13,[84,453,454],{"class":128},"        out[todo] ",[84,456,151],{"class":124},[84,458,459],{"class":128}," pd.to_datetime(clean[todo], ",[84,461,462],{"class":381},"format",[84,464,151],{"class":124},[84,466,467],{"class":128},"fmt, ",[84,469,470],{"class":381},"errors",[84,472,151],{"class":124},[84,474,475],{"class":94},"\"coerce\"",[84,477,390],{"class":128},[84,479,481,484,487,490],{"class":86,"line":480},14,[84,482,483],{"class":124},"    return",[84,485,486],{"class":128}," out.dt.to_period(",[84,488,489],{"class":94},"\"M\"",[84,491,390],{"class":128},[84,493,495],{"class":86,"line":494},15,[84,496,142],{"emptyLinePlaceholder":141},[84,498,500,503,505,508,511,514,517],{"class":86,"line":499},16,[84,501,502],{"class":128},"result ",[84,504,151],{"class":124},[84,506,507],{"class":128}," pd.DataFrame({",[84,509,510],{"class":94},"\"label\"",[84,512,513],{"class":128},": months, ",[84,515,516],{"class":94},"\"month\"",[84,518,519],{"class":128},": parse_month(months)})\n",[84,521,523,526,529,531,533,536],{"class":86,"line":522},17,[84,524,525],{"class":206},"print",[84,527,528],{"class":128},"(result.to_string(",[84,530,404],{"class":381},[84,532,151],{"class":124},[84,534,535],{"class":206},"False",[84,537,538],{"class":128},"))\n",[84,540,542,544,547,550,553,555,558,560],{"class":86,"line":541},18,[84,543,525],{"class":206},[84,545,546],{"class":128},"(",[84,548,549],{"class":94},"\"not parsed:\"",[84,551,552],{"class":128},", result.loc[result[",[84,554,516],{"class":94},[84,556,557],{"class":128},"].isna(), ",[84,559,510],{"class":94},[84,561,562],{"class":128},"].tolist())\n",[10,564,565,566,569,570,572,573,575,576,578,579,582,583,586,587,590],{},"The approach is to try a short list of explicit formats in turn, each only on the labels not yet parsed. An explicit format is far safer than letting pandas guess: ",[81,567,568],{},"%b-%y"," means a three-letter month, a hyphen and a two-digit year, and nothing else will match it by accident. Before parsing, a small set of replacements normalises what the formats cannot express — the four-letter ",[14,571,60],{}," that people often write but ",[81,574,311],{}," does not recognise, full names like ",[14,577,245],{}," in a column of abbreviations, and stray full stops. The result is converted to a monthly ",[81,580,581],{},"Period",", which is the right type for a label that means a whole month rather than a particular day: it sorts correctly, supports arithmetic like ",[14,584,585],{},"next month",", and turns into the first or last day of the month when a date is needed. ",[14,588,589],{},"Smarch 2026"," matches nothing and is listed rather than hidden — the kind of typo that would otherwise drop a month of data from a report without anyone noticing.",[592,593,601,602,601,606,601,610,601,618,601,628,601,635,601,640,601,644,601,650,601,655,601,659,601,664,601,667,601,670,601,674,601,677,601,682,601,688,601,692,601,696,601,700,601,704,601,707,601,712,601,717,601,721,601,724,601,728,601,731,601,736,601,741,601,744,601,747],"svg",{"viewBox":594,"role":595,"ariaLabelledBy":596,"xmlns":599,"style":600},"4 0 752 126","img",[597,598],"tm-parse-t","tm-parse-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  ",[603,604,605],"title",{"id":597},"Parsing a column of month labels",[607,608,609],"desc",{"id":598},"Labels are stripped and normalised, for example Sept becomes Sep and full stops are removed. Each explicit format is tried in turn on the labels still unparsed. The results become monthly periods, and labels that matched no format are reported.",[611,612],"rect",{"x":613,"y":614,"width":615,"height":616,"fill":617},"4","0","752","126","#ffffff",[611,619],{"x":620,"y":621,"width":622,"height":623,"rx":624,"fill":625,"stroke":626,"style":627},"20.0","16.0","115.2","94.0","12","#e7ebef","var(--line,#cdd5e6)","stroke-width:2px",[629,630,634],"text",{"x":631,"y":632,"style":633},"77.6","50.2","font-size:13.5px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","Raw labels",[629,636,639],{"x":631,"y":637,"style":638},"69.8","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","Jan 2026,",[629,641,643],{"x":631,"y":642,"style":638},"87.2","Sept-26, …",[86,645],{"x1":646,"y1":647,"x2":648,"y2":647,"stroke":649,"style":627},"140.2","63.0","162.2","var(--brand,#5b5cf0)",[651,652],"polygon",{"points":653,"fill":654},"166.2,63.0 157.2,68.0 157.2,58.0","#5b5cf0",[611,656],{"x":657,"y":621,"width":622,"height":623,"rx":624,"fill":658,"stroke":649,"style":627},"171.2","#f0f4ff",[629,660,663],{"x":661,"y":632,"style":662},"228.8","font-size:13.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Normalise",[629,665,666],{"x":661,"y":637,"style":638},"Sept → Sep,",[629,668,669],{"x":661,"y":642,"style":638},"drop dots",[86,671],{"x1":672,"y1":647,"x2":673,"y2":647,"stroke":649,"style":627},"291.4","313.4",[651,675],{"points":676,"fill":654},"317.4,63.0 308.4,68.0 308.4,58.0",[611,678],{"x":679,"y":621,"width":622,"height":623,"rx":624,"fill":680,"stroke":681,"style":627},"322.4","#fdefd8","var(--gold,#b4740a)",[629,683,687],{"x":684,"y":685,"style":686},"380.0","41.5","font-size:13.5px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","Try formats",[629,689,691],{"x":684,"y":690,"style":686},"59.0","in turn",[629,693,695],{"x":684,"y":694,"style":638},"78.5","%b %Y, %B",[629,697,699],{"x":684,"y":698,"style":638},"96.0","%Y, %b-%y…",[86,701],{"x1":702,"y1":647,"x2":703,"y2":647,"stroke":649,"style":627},"442.6","464.6",[651,705],{"points":706,"fill":654},"468.6,63.0 459.6,68.0 459.6,58.0",[611,708],{"x":709,"y":621,"width":622,"height":623,"rx":624,"fill":710,"stroke":711,"style":627},"473.6","#d9f4f1","var(--teal,#0f9488)",[629,713,716],{"x":714,"y":632,"style":715},"531.2","font-size:13.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","Monthly",[629,718,720],{"x":714,"y":719,"style":715},"67.8","periods",[629,722,723],{"x":714,"y":642,"style":638},"sortable",[86,725],{"x1":726,"y1":647,"x2":727,"y2":647,"stroke":649,"style":627},"593.8","615.8",[651,729],{"points":730,"fill":654},"619.8,63.0 610.8,68.0 610.8,58.0",[611,732],{"x":733,"y":621,"width":622,"height":623,"rx":624,"fill":734,"stroke":735,"style":627},"624.8","#fce9e9","var(--danger,#dc2626)",[629,737,740],{"x":738,"y":685,"style":739},"682.4","font-size:13.5px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","Report the",[629,742,743],{"x":738,"y":690,"style":739},"rest",[629,745,746],{"x":738,"y":694,"style":638},"e.g. Smarch",[629,748,749],{"x":738,"y":698,"style":638},"2026",[69,751,753],{"id":752},"step-2-quarters-iso-weeks-and-fiscal-periods","Step 2 — Quarters, ISO weeks and fiscal periods",[74,755,757],{"className":115,"code":756,"language":117,"meta":79,"style":79},"quarters = pd.Series([\"Q1 2026\", \"2026 Q2\", \"Q3-26\", \"2026Q4\"])\nq = quarters.str.extract(r\"Q([1-4])\\D*(\\d{2,4})|(\\d{4})\\s*Q([1-4])\")\nyear = q[1].fillna(q[2]).astype(int).map(lambda y: y + 2000 if y \u003C 100 else y)\nqtr = q[0].fillna(q[3]).astype(int)\nquarter_periods = pd.PeriodIndex.from_fields(year=year, quarter=qtr, freq=\"Q\")\nprint(dict(zip(quarters, quarter_periods.astype(str))))\n\nweeks = pd.Series([\"2026-W01\", \"2026-W14\", \"2026 week 53\"])\nw = weeks.str.extract(r\"(\\d{4})\\D*(\\d{1,2})$\").astype(int)\nmonday = pd.to_datetime(w[0].astype(str) + \"-W\" + w[1].astype(str).str.zfill(2) + \"-1\", format=\"%G-W%V-%u\", errors=\"coerce\")\nprint(dict(zip(weeks, monday.dt.date)))\n\nfiscal = pd.Series([\"FY27 P01\", \"FY27 P03\", \"FY27 P10\", \"FY27 P12\"])\nfy = fiscal.str.extract(r\"FY(\\d{2})\\s*P(\\d{2})\").astype(int)\nstart_month = 4                                         # the fiscal year starts in April and is named after the year it ends\ncalendar = (pd.PeriodIndex.from_fields(year=2000 + fy[0] - 1, month=start_month, freq=\"M\") + (fy[1] - 1)).astype(str)\nprint(dict(zip(fiscal, calendar)))\n",[81,758,759,788,851,909,931,967,990,994,1018,1058,1136,1151,1155,1184,1225,1239,1310],{"__ignoreMap":79},[84,760,761,764,766,768,771,773,776,778,781,783,786],{"class":86,"line":87},[84,762,763],{"class":128},"quarters ",[84,765,151],{"class":124},[84,767,154],{"class":128},[84,769,770],{"class":94},"\"Q1 2026\"",[84,772,21],{"class":128},[84,774,775],{"class":94},"\"2026 Q2\"",[84,777,21],{"class":128},[84,779,780],{"class":94},"\"Q3-26\"",[84,782,21],{"class":128},[84,784,785],{"class":94},"\"2026Q4\"",[84,787,195],{"class":128},[84,789,790,793,795,798,800,803,806,809,812,815,818,821,824,827,829,832,835,837,840,842,844,847,849],{"class":86,"line":138},[84,791,792],{"class":128},"q ",[84,794,151],{"class":124},[84,796,797],{"class":128}," quarters.str.extract(",[84,799,216],{"class":124},[84,801,802],{"class":94},"\"Q",[84,804,805],{"class":206},"([",[84,807,808],{"class":310},"1-4",[84,810,811],{"class":206},"])\\D",[84,813,814],{"class":124},"*",[84,816,817],{"class":206},"(\\d",[84,819,820],{"class":124},"{2,4}",[84,822,823],{"class":206},")",[84,825,826],{"class":124},"|",[84,828,817],{"class":206},[84,830,831],{"class":124},"{4}",[84,833,834],{"class":206},")\\s",[84,836,814],{"class":124},[84,838,839],{"class":94},"Q",[84,841,805],{"class":206},[84,843,808],{"class":310},[84,845,846],{"class":206},"])",[84,848,219],{"class":94},[84,850,390],{"class":128},[84,852,853,856,858,861,864,867,870,873,876,879,882,885,888,891,894,897,900,903,906],{"class":86,"line":145},[84,854,855],{"class":128},"year ",[84,857,151],{"class":124},[84,859,860],{"class":128}," q[",[84,862,863],{"class":206},"1",[84,865,866],{"class":128},"].fillna(q[",[84,868,869],{"class":206},"2",[84,871,872],{"class":128},"]).astype(",[84,874,875],{"class":206},"int",[84,877,878],{"class":128},").map(",[84,880,881],{"class":124},"lambda",[84,883,884],{"class":128}," y: y ",[84,886,887],{"class":124},"+",[84,889,890],{"class":206}," 2000",[84,892,893],{"class":124}," if",[84,895,896],{"class":128}," y ",[84,898,899],{"class":124},"\u003C",[84,901,902],{"class":206}," 100",[84,904,905],{"class":124}," else",[84,907,908],{"class":128}," y)\n",[84,910,911,914,916,918,920,922,925,927,929],{"class":86,"line":198},[84,912,913],{"class":128},"qtr ",[84,915,151],{"class":124},[84,917,860],{"class":128},[84,919,614],{"class":206},[84,921,866],{"class":128},[84,923,924],{"class":206},"3",[84,926,872],{"class":128},[84,928,875],{"class":206},[84,930,390],{"class":128},[84,932,933,936,938,941,944,946,949,952,954,957,960,962,965],{"class":86,"line":203},[84,934,935],{"class":128},"quarter_periods ",[84,937,151],{"class":124},[84,939,940],{"class":128}," pd.PeriodIndex.from_fields(",[84,942,943],{"class":381},"year",[84,945,151],{"class":124},[84,947,948],{"class":128},"year, ",[84,950,951],{"class":381},"quarter",[84,953,151],{"class":124},[84,955,956],{"class":128},"qtr, ",[84,958,959],{"class":381},"freq",[84,961,151],{"class":124},[84,963,964],{"class":94},"\"Q\"",[84,966,390],{"class":128},[84,968,969,971,973,976,978,981,984,987],{"class":86,"line":297},[84,970,525],{"class":206},[84,972,546],{"class":128},[84,974,975],{"class":206},"dict",[84,977,546],{"class":128},[84,979,980],{"class":206},"zip",[84,982,983],{"class":128},"(quarters, quarter_periods.astype(",[84,985,986],{"class":206},"str",[84,988,989],{"class":128},"))))\n",[84,991,992],{"class":86,"line":348},[84,993,142],{"emptyLinePlaceholder":141},[84,995,996,999,1001,1003,1006,1008,1011,1013,1016],{"class":86,"line":353},[84,997,998],{"class":128},"weeks ",[84,1000,151],{"class":124},[84,1002,154],{"class":128},[84,1004,1005],{"class":94},"\"2026-W01\"",[84,1007,21],{"class":128},[84,1009,1010],{"class":94},"\"2026-W14\"",[84,1012,21],{"class":128},[84,1014,1015],{"class":94},"\"2026 week 53\"",[84,1017,195],{"class":128},[84,1019,1020,1023,1025,1028,1030,1032,1034,1036,1039,1041,1043,1046,1049,1051,1054,1056],{"class":86,"line":366},[84,1021,1022],{"class":128},"w ",[84,1024,151],{"class":124},[84,1026,1027],{"class":128}," weeks.str.extract(",[84,1029,216],{"class":124},[84,1031,219],{"class":94},[84,1033,817],{"class":206},[84,1035,831],{"class":124},[84,1037,1038],{"class":206},")\\D",[84,1040,814],{"class":124},[84,1042,817],{"class":206},[84,1044,1045],{"class":124},"{1,2}",[84,1047,1048],{"class":206},")$",[84,1050,219],{"class":94},[84,1052,1053],{"class":128},").astype(",[84,1055,875],{"class":206},[84,1057,390],{"class":128},[84,1059,1060,1063,1065,1068,1070,1073,1075,1078,1080,1083,1086,1089,1091,1093,1095,1098,1100,1102,1104,1107,1109,1111,1113,1115,1118,1121,1124,1126,1128,1130,1132,1134],{"class":86,"line":393},[84,1061,1062],{"class":128},"monday ",[84,1064,151],{"class":124},[84,1066,1067],{"class":128}," pd.to_datetime(w[",[84,1069,614],{"class":206},[84,1071,1072],{"class":128},"].astype(",[84,1074,986],{"class":206},[84,1076,1077],{"class":128},") ",[84,1079,887],{"class":124},[84,1081,1082],{"class":94}," \"-W\"",[84,1084,1085],{"class":124}," +",[84,1087,1088],{"class":128}," w[",[84,1090,863],{"class":206},[84,1092,1072],{"class":128},[84,1094,986],{"class":206},[84,1096,1097],{"class":128},").str.zfill(",[84,1099,869],{"class":206},[84,1101,1077],{"class":128},[84,1103,887],{"class":124},[84,1105,1106],{"class":94}," \"-1\"",[84,1108,21],{"class":128},[84,1110,462],{"class":381},[84,1112,151],{"class":124},[84,1114,219],{"class":94},[84,1116,1117],{"class":310},"%G",[84,1119,1120],{"class":94},"-W%V-",[84,1122,1123],{"class":310},"%u",[84,1125,219],{"class":94},[84,1127,21],{"class":128},[84,1129,470],{"class":381},[84,1131,151],{"class":124},[84,1133,475],{"class":94},[84,1135,390],{"class":128},[84,1137,1138,1140,1142,1144,1146,1148],{"class":86,"line":422},[84,1139,525],{"class":206},[84,1141,546],{"class":128},[84,1143,975],{"class":206},[84,1145,546],{"class":128},[84,1147,980],{"class":206},[84,1149,1150],{"class":128},"(weeks, monday.dt.date)))\n",[84,1152,1153],{"class":86,"line":440},[84,1154,142],{"emptyLinePlaceholder":141},[84,1156,1157,1160,1162,1164,1167,1169,1172,1174,1177,1179,1182],{"class":86,"line":451},[84,1158,1159],{"class":128},"fiscal ",[84,1161,151],{"class":124},[84,1163,154],{"class":128},[84,1165,1166],{"class":94},"\"FY27 P01\"",[84,1168,21],{"class":128},[84,1170,1171],{"class":94},"\"FY27 P03\"",[84,1173,21],{"class":128},[84,1175,1176],{"class":94},"\"FY27 P10\"",[84,1178,21],{"class":128},[84,1180,1181],{"class":94},"\"FY27 P12\"",[84,1183,195],{"class":128},[84,1185,1186,1189,1191,1194,1196,1199,1201,1204,1206,1208,1211,1213,1215,1217,1219,1221,1223],{"class":86,"line":480},[84,1187,1188],{"class":128},"fy ",[84,1190,151],{"class":124},[84,1192,1193],{"class":128}," fiscal.str.extract(",[84,1195,216],{"class":124},[84,1197,1198],{"class":94},"\"FY",[84,1200,817],{"class":206},[84,1202,1203],{"class":124},"{2}",[84,1205,834],{"class":206},[84,1207,814],{"class":124},[84,1209,1210],{"class":94},"P",[84,1212,817],{"class":206},[84,1214,1203],{"class":124},[84,1216,823],{"class":206},[84,1218,219],{"class":94},[84,1220,1053],{"class":128},[84,1222,875],{"class":206},[84,1224,390],{"class":128},[84,1226,1227,1230,1232,1235],{"class":86,"line":494},[84,1228,1229],{"class":128},"start_month ",[84,1231,151],{"class":124},[84,1233,1234],{"class":206}," 4",[84,1236,1238],{"class":1237},"s-wDw","                                         # the fiscal year starts in April and is named after the year it ends\n",[84,1240,1241,1244,1246,1249,1251,1253,1256,1258,1261,1263,1266,1269,1272,1274,1277,1279,1282,1284,1286,1288,1290,1292,1295,1297,1299,1301,1303,1306,1308],{"class":86,"line":499},[84,1242,1243],{"class":128},"calendar ",[84,1245,151],{"class":124},[84,1247,1248],{"class":128}," (pd.PeriodIndex.from_fields(",[84,1250,943],{"class":381},[84,1252,151],{"class":124},[84,1254,1255],{"class":206},"2000",[84,1257,1085],{"class":124},[84,1259,1260],{"class":128}," fy[",[84,1262,614],{"class":206},[84,1264,1265],{"class":128},"] ",[84,1267,1268],{"class":124},"-",[84,1270,1271],{"class":206}," 1",[84,1273,21],{"class":128},[84,1275,1276],{"class":381},"month",[84,1278,151],{"class":124},[84,1280,1281],{"class":128},"start_month, ",[84,1283,959],{"class":381},[84,1285,151],{"class":124},[84,1287,489],{"class":94},[84,1289,1077],{"class":128},[84,1291,887],{"class":124},[84,1293,1294],{"class":128}," (fy[",[84,1296,863],{"class":206},[84,1298,1265],{"class":128},[84,1300,1268],{"class":124},[84,1302,1271],{"class":206},[84,1304,1305],{"class":128},")).astype(",[84,1307,986],{"class":206},[84,1309,390],{"class":128},[84,1311,1312,1314,1316,1318,1320,1322],{"class":86,"line":522},[84,1313,525],{"class":206},[84,1315,546],{"class":128},[84,1317,975],{"class":206},[84,1319,546],{"class":128},[84,1321,980],{"class":206},[84,1323,1324],{"class":128},"(fiscal, calendar)))\n",[10,1326,1327,1328,1331,1332,1335,1336,1338,1339,1342,1343,1345,1346,1349],{},"Quarter labels come in several orders, so a regular expression with two alternatives captures the number and the year whichever comes first, and two-digit years are widened to four. ",[81,1329,1330],{},"PeriodIndex.from_fields"," then builds proper quarterly periods. Week numbers need care: ",[14,1333,1334],{},"Week 1"," of a year is defined differently by different conventions, and the ISO 8601 definition — weeks start on Monday, and week 1 is the one containing the year's first Thursday — is the one most European businesses and most systems use. The directives ",[81,1337,1117],{}," (ISO year), ",[81,1340,1341],{},"%V"," (ISO week) and ",[81,1344,1123],{}," (weekday, Monday is 1) parse it exactly, giving the Monday that starts each week. Two results show why the convention matters. ISO week 1 of 2026 starts on Monday 29 December 2025, so a label for the first week of 2026 belongs partly to the previous calendar year. And 2026 is one of the years with 53 ISO weeks — it begins on a Thursday — so ",[14,1347,1348],{},"2026 week 53"," is valid and starts on 28 December; in a year with only 52 weeks the same label would fail to parse and be reported. Fiscal periods need one fact that is not in the label — the month the fiscal year starts — after which each period is that month plus an offset. Here FY27 runs from April 2026, so period 1 is April 2026 and period 10 is January 2027.",[592,1351,601,1357,601,1360,601,1363,601,1368,601,1374,601,1378,601,1384,601,1388,601,1392,601,1396,601,1400,601,1404,601,1407,601,1410,601,1414,601,1416,601,1419,601,1421,601,1424,601,1427,601,1430,601,1432,601,1435,601,1437,601,1439,601,1441,601,1444,601,1446,601,1449,601,1451,601,1454,601,1456,601,1458,601,1460,601,1463,601,1466,601,1469,601,1471,601,1474,601,1476,601,1479,601,1481,601,1484,601,1487,601,1491,601,1493,601,1496,601,1498,601,1501,601,1503,601,1506,601,1509,601,1513,601,1515,601,1518,601,1520,601,1522,601,1524,601,1527,601,1530,601,1534,601,1536,601,1539,601,1541,601,1543,601,1545,601,1549,601,1552,601,1556,601,1558,601,1560,601,1562,601,1564,601,1566],{"viewBox":1352,"role":595,"ariaLabelledBy":1353,"xmlns":599,"style":1356},"175 0 410 280",[1354,1355],"tm-periods-t","tm-periods-d","width:100%;max-width:410px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[603,1358,1359],{"id":1354},"Labels and what they become",[607,1361,1362],{"id":1355},"Q3-26 becomes the third quarter of 2026. 2026-W14 becomes the week starting Monday 30 March 2026. FY27 P01 becomes April 2026 and FY27 P10 becomes January 2027, because the fiscal year starts in April. ISO week 1 of 2026 starts on 29 December 2025, and 2026 has a week 53 starting on 28 December.",[611,1364],{"x":1365,"y":614,"width":1366,"height":1367,"fill":617},"175","410","280",[611,1369],{"x":1370,"y":621,"width":1371,"height":1372,"rx":614,"fill":625,"stroke":626,"style":1373},"191.3","32.0","24.0","stroke-width:1px",[611,1375],{"x":1376,"y":621,"width":1377,"height":1372,"rx":614,"fill":625,"stroke":626,"style":1373},"223.3","111.5",[629,1379,1383],{"x":1380,"y":1381,"style":1382},"279.0","33.0","font-size:11px;font-weight:600;fill:var(--muted,#5b6780);text-anchor:middle","A",[611,1385],{"x":1386,"y":621,"width":1387,"height":1372,"rx":614,"fill":625,"stroke":626,"style":1373},"334.8","100.3",[629,1389,1391],{"x":1390,"y":1381,"style":1382},"384.9","B",[611,1393],{"x":1394,"y":621,"width":1395,"height":1372,"rx":614,"fill":625,"stroke":626,"style":1373},"435.1","133.6",[629,1397,1399],{"x":1398,"y":1381,"style":1382},"501.9","C",[611,1401],{"x":1370,"y":1402,"width":1371,"height":1403,"rx":614,"fill":625,"stroke":626,"style":1373},"40.0","28.0",[629,1405,863],{"x":1406,"y":690,"style":1382},"207.3",[611,1408],{"x":1376,"y":1402,"width":1377,"height":1403,"rx":614,"fill":658,"stroke":649,"style":1409},"stroke-width:1.5px",[629,1411,1413],{"x":1380,"y":690,"style":1412},"font-size:12px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Label",[611,1415],{"x":1386,"y":1402,"width":1387,"height":1403,"rx":614,"fill":658,"stroke":649,"style":1409},[629,1417,1418],{"x":1390,"y":690,"style":1412},"Kind",[611,1420],{"x":1394,"y":1402,"width":1395,"height":1403,"rx":614,"fill":658,"stroke":649,"style":1409},[629,1422,1423],{"x":1398,"y":690,"style":1412},"Becomes",[611,1425],{"x":1370,"y":1426,"width":1371,"height":1403,"rx":614,"fill":625,"stroke":626,"style":1373},"68.0",[629,1428,869],{"x":1406,"y":1429,"style":1382},"87.0",[611,1431],{"x":1376,"y":1426,"width":1377,"height":1403,"rx":614,"fill":617,"stroke":626,"style":1373},[629,1433,27],{"x":1380,"y":1429,"style":1434},"font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:middle",[611,1436],{"x":1386,"y":1426,"width":1387,"height":1403,"rx":614,"fill":617,"stroke":626,"style":1373},[629,1438,1276],{"x":1390,"y":1429,"style":1434},[611,1440],{"x":1394,"y":1426,"width":1395,"height":1403,"rx":614,"fill":617,"stroke":626,"style":1373},[629,1442,1443],{"x":1398,"y":1429,"style":1434},"2026-09",[611,1445],{"x":1370,"y":698,"width":1371,"height":1403,"rx":614,"fill":625,"stroke":626,"style":1373},[629,1447,924],{"x":1406,"y":1448,"style":1382},"115.0",[611,1450],{"x":1376,"y":698,"width":1377,"height":1403,"rx":614,"fill":617,"stroke":626,"style":1373},[629,1452,1453],{"x":1380,"y":1448,"style":1434},"Q3-26",[611,1455],{"x":1386,"y":698,"width":1387,"height":1403,"rx":614,"fill":617,"stroke":626,"style":1373},[629,1457,951],{"x":1390,"y":1448,"style":1434},[611,1459],{"x":1394,"y":698,"width":1395,"height":1403,"rx":614,"fill":617,"stroke":626,"style":1373},[629,1461,1462],{"x":1398,"y":1448,"style":1434},"2026Q3",[611,1464],{"x":1370,"y":1465,"width":1371,"height":1403,"rx":614,"fill":625,"stroke":626,"style":1373},"124.0",[629,1467,613],{"x":1406,"y":1468,"style":1382},"143.0",[611,1470],{"x":1376,"y":1465,"width":1377,"height":1403,"rx":614,"fill":617,"stroke":626,"style":1373},[629,1472,1473],{"x":1380,"y":1468,"style":1434},"2026-W14",[611,1475],{"x":1386,"y":1465,"width":1387,"height":1403,"rx":614,"fill":617,"stroke":626,"style":1373},[629,1477,1478],{"x":1390,"y":1468,"style":1434},"ISO week",[611,1480],{"x":1394,"y":1465,"width":1395,"height":1403,"rx":614,"fill":617,"stroke":626,"style":1373},[629,1482,1483],{"x":1398,"y":1468,"style":1434},"Mon 30 Mar 2026",[611,1485],{"x":1370,"y":1486,"width":1371,"height":1403,"rx":614,"fill":625,"stroke":626,"style":1373},"152.0",[629,1488,1490],{"x":1406,"y":1489,"style":1382},"171.0","5",[611,1492],{"x":1376,"y":1486,"width":1377,"height":1403,"rx":614,"fill":617,"stroke":626,"style":1373},[629,1494,1495],{"x":1380,"y":1489,"style":1434},"FY27 P01",[611,1497],{"x":1386,"y":1486,"width":1387,"height":1403,"rx":614,"fill":617,"stroke":626,"style":1373},[629,1499,1500],{"x":1390,"y":1489,"style":1434},"fiscal period",[611,1502],{"x":1394,"y":1486,"width":1395,"height":1403,"rx":614,"fill":617,"stroke":626,"style":1373},[629,1504,1505],{"x":1398,"y":1489,"style":1434},"2026-04",[611,1507],{"x":1370,"y":1508,"width":1371,"height":1403,"rx":614,"fill":625,"stroke":626,"style":1373},"180.0",[629,1510,1512],{"x":1406,"y":1511,"style":1382},"199.0","6",[611,1514],{"x":1376,"y":1508,"width":1377,"height":1403,"rx":614,"fill":617,"stroke":626,"style":1373},[629,1516,1517],{"x":1380,"y":1511,"style":1434},"FY27 P10",[611,1519],{"x":1386,"y":1508,"width":1387,"height":1403,"rx":614,"fill":617,"stroke":626,"style":1373},[629,1521,1500],{"x":1390,"y":1511,"style":1434},[611,1523],{"x":1394,"y":1508,"width":1395,"height":1403,"rx":614,"fill":617,"stroke":626,"style":1373},[629,1525,1526],{"x":1398,"y":1511,"style":1434},"2027-01",[611,1528],{"x":1370,"y":1529,"width":1371,"height":1403,"rx":614,"fill":625,"stroke":626,"style":1373},"208.0",[629,1531,1533],{"x":1406,"y":1532,"style":1382},"227.0","7",[611,1535],{"x":1376,"y":1529,"width":1377,"height":1403,"rx":614,"fill":617,"stroke":626,"style":1373},[629,1537,1538],{"x":1380,"y":1532,"style":1434},"2026-W01",[611,1540],{"x":1386,"y":1529,"width":1387,"height":1403,"rx":614,"fill":617,"stroke":626,"style":1373},[629,1542,1478],{"x":1390,"y":1532,"style":1434},[611,1544],{"x":1394,"y":1529,"width":1395,"height":1403,"rx":614,"fill":680,"stroke":681,"style":1409},[629,1546,1548],{"x":1398,"y":1532,"style":1547},"font-size:12px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","Mon 29 Dec 2025",[611,1550],{"x":1370,"y":1551,"width":1371,"height":1403,"rx":614,"fill":625,"stroke":626,"style":1373},"236.0",[629,1553,1555],{"x":1406,"y":1554,"style":1382},"255.0","8",[611,1557],{"x":1376,"y":1551,"width":1377,"height":1403,"rx":614,"fill":617,"stroke":626,"style":1373},[629,1559,1348],{"x":1380,"y":1554,"style":1434},[611,1561],{"x":1386,"y":1551,"width":1387,"height":1403,"rx":614,"fill":617,"stroke":626,"style":1373},[629,1563,1478],{"x":1390,"y":1554,"style":1434},[611,1565],{"x":1394,"y":1551,"width":1395,"height":1403,"rx":614,"fill":617,"stroke":626,"style":1373},[629,1567,1568],{"x":1398,"y":1554,"style":1434},"Mon 28 Dec 2026",[69,1570,1572],{"id":1571},"step-3-weekday-names-in-the-right-order","Step 3 — Weekday names in the right order",[74,1574,1576],{"className":115,"code":1575,"language":117,"meta":79,"style":79},"days = pd.Series([\"Mon\", \"Wednesday\", \"fri\", \"Sun\", \"Tues\", \"Thur\"])\nORDER = [\"mon\", \"tue\", \"wed\", \"thu\", \"fri\", \"sat\", \"sun\"]\nday_number = days.str.strip().str.lower().str[:3].map({d: i for i, d in enumerate(ORDER)})\nweekday = pd.Categorical(days.str.strip().str[:3].str.title(), categories=[d.title() for d in ORDER], ordered=True)\nprint(pd.DataFrame({\"label\": days, \"number\": day_number, \"weekday\": weekday}).sort_values(\"weekday\").to_string(index=False))\n\nweek_start = pd.Timestamp(\"2026-10-05\")                 # a Monday\nprint((week_start + pd.to_timedelta(day_number, unit=\"D\")).dt.strftime(\"%a %d %b\").tolist())\n",[81,1577,1578,1617,1660,1693,1738,1775,1779,1798],{"__ignoreMap":79},[84,1579,1580,1583,1585,1587,1590,1592,1595,1597,1600,1602,1605,1607,1610,1612,1615],{"class":86,"line":87},[84,1581,1582],{"class":128},"days ",[84,1584,151],{"class":124},[84,1586,154],{"class":128},[84,1588,1589],{"class":94},"\"Mon\"",[84,1591,21],{"class":128},[84,1593,1594],{"class":94},"\"Wednesday\"",[84,1596,21],{"class":128},[84,1598,1599],{"class":94},"\"fri\"",[84,1601,21],{"class":128},[84,1603,1604],{"class":94},"\"Sun\"",[84,1606,21],{"class":128},[84,1608,1609],{"class":94},"\"Tues\"",[84,1611,21],{"class":128},[84,1613,1614],{"class":94},"\"Thur\"",[84,1616,195],{"class":128},[84,1618,1619,1622,1624,1626,1629,1631,1634,1636,1639,1641,1644,1646,1648,1650,1653,1655,1658],{"class":86,"line":138},[84,1620,1621],{"class":206},"ORDER",[84,1623,210],{"class":124},[84,1625,305],{"class":128},[84,1627,1628],{"class":94},"\"mon\"",[84,1630,21],{"class":128},[84,1632,1633],{"class":94},"\"tue\"",[84,1635,21],{"class":128},[84,1637,1638],{"class":94},"\"wed\"",[84,1640,21],{"class":128},[84,1642,1643],{"class":94},"\"thu\"",[84,1645,21],{"class":128},[84,1647,1599],{"class":94},[84,1649,21],{"class":128},[84,1651,1652],{"class":94},"\"sat\"",[84,1654,21],{"class":128},[84,1656,1657],{"class":94},"\"sun\"",[84,1659,345],{"class":128},[84,1661,1662,1665,1667,1670,1672,1675,1678,1681,1683,1686,1688,1690],{"class":86,"line":145},[84,1663,1664],{"class":128},"day_number ",[84,1666,151],{"class":124},[84,1668,1669],{"class":128}," days.str.strip().str.lower().str[:",[84,1671,924],{"class":206},[84,1673,1674],{"class":128},"].map({d: i ",[84,1676,1677],{"class":124},"for",[84,1679,1680],{"class":128}," i, d ",[84,1682,431],{"class":124},[84,1684,1685],{"class":206}," enumerate",[84,1687,546],{"class":128},[84,1689,1621],{"class":206},[84,1691,1692],{"class":128},")})\n",[84,1694,1695,1698,1700,1703,1705,1708,1711,1713,1716,1718,1721,1723,1726,1729,1732,1734,1736],{"class":86,"line":198},[84,1696,1697],{"class":128},"weekday ",[84,1699,151],{"class":124},[84,1701,1702],{"class":128}," pd.Categorical(days.str.strip().str[:",[84,1704,924],{"class":206},[84,1706,1707],{"class":128},"].str.title(), ",[84,1709,1710],{"class":381},"categories",[84,1712,151],{"class":124},[84,1714,1715],{"class":128},"[d.title() ",[84,1717,1677],{"class":124},[84,1719,1720],{"class":128}," d ",[84,1722,431],{"class":124},[84,1724,1725],{"class":206}," ORDER",[84,1727,1728],{"class":128},"], ",[84,1730,1731],{"class":381},"ordered",[84,1733,151],{"class":124},[84,1735,387],{"class":206},[84,1737,390],{"class":128},[84,1739,1740,1742,1745,1747,1750,1753,1756,1759,1762,1764,1767,1769,1771,1773],{"class":86,"line":203},[84,1741,525],{"class":206},[84,1743,1744],{"class":128},"(pd.DataFrame({",[84,1746,510],{"class":94},[84,1748,1749],{"class":128},": days, ",[84,1751,1752],{"class":94},"\"number\"",[84,1754,1755],{"class":128},": day_number, ",[84,1757,1758],{"class":94},"\"weekday\"",[84,1760,1761],{"class":128},": weekday}).sort_values(",[84,1763,1758],{"class":94},[84,1765,1766],{"class":128},").to_string(",[84,1768,404],{"class":381},[84,1770,151],{"class":124},[84,1772,535],{"class":206},[84,1774,538],{"class":128},[84,1776,1777],{"class":86,"line":297},[84,1778,142],{"emptyLinePlaceholder":141},[84,1780,1781,1784,1786,1789,1792,1795],{"class":86,"line":348},[84,1782,1783],{"class":128},"week_start ",[84,1785,151],{"class":124},[84,1787,1788],{"class":128}," pd.Timestamp(",[84,1790,1791],{"class":94},"\"2026-10-05\"",[84,1793,1794],{"class":128},")                 ",[84,1796,1797],{"class":1237},"# a Monday\n",[84,1799,1800,1802,1805,1807,1810,1813,1815,1818,1821,1823,1826,1829,1832,1834],{"class":86,"line":353},[84,1801,525],{"class":206},[84,1803,1804],{"class":128},"((week_start ",[84,1806,887],{"class":124},[84,1808,1809],{"class":128}," pd.to_timedelta(day_number, ",[84,1811,1812],{"class":381},"unit",[84,1814,151],{"class":124},[84,1816,1817],{"class":94},"\"D\"",[84,1819,1820],{"class":128},")).dt.strftime(",[84,1822,219],{"class":94},[84,1824,1825],{"class":310},"%a",[84,1827,1828],{"class":310}," %d",[84,1830,1831],{"class":310}," %b",[84,1833,219],{"class":94},[84,1835,1836],{"class":128},").tolist())\n",[10,1838,1839,1840,21,1843,1846,1847,1850,1851,1854,1855,1857,1858,1861,1862,1865],{},"A weekday on its own is not a date, but it has a fixed order and often needs turning into a date within a given week. The first three letters identify every English weekday, which absorbs ",[14,1841,1842],{},"Tues",[14,1844,1845],{},"Thur"," and ",[14,1848,1849],{},"Wednesday"," alike, and a small lookup turns them into numbers from 0 for Monday — the same convention as pandas' ",[81,1852,1853],{},"dayofweek",". An ordered categorical makes the names sort Monday to Sunday instead of alphabetically, which matters for every rota or opening-hours table. Adding the day number to the Monday of a week gives real dates: for the week starting Monday 5 October 2026, ",[14,1856,1849],{}," becomes 7 October and ",[14,1859,1860],{},"Sun"," becomes 11 October. The same lookup is a natural place to reject anything that is not a weekday at all, such as ",[14,1863,1864],{},"Holiday"," typed into a rota column.",[69,1867,1869],{"id":1868},"other-languages","Other languages",[10,1871,1872,1873,21,1876,21,1879,1882],{},"Month names in other languages — ",[14,1874,1875],{},"März",[14,1877,1878],{},"janvier",[14,1880,1881],{},"giugno"," — are best handled with an explicit mapping to month numbers rather than by changing the system locale, which affects the whole process and is not available on every machine. A dictionary of the twelve names, and their usual abbreviations, for each language in the data is short, reviewable and reliable; normalise the labels to lower case and strip accents before looking them up, and the same reporting of unmatched labels applies. The same is true of weekday names.",[69,1884,1886],{"id":1885},"store-the-result-keep-the-label","Store the result, keep the label",[10,1888,1889,1890,1893,1894,1897,1898,1901],{},"Once converted, the period should replace the label as the column the report works with — sorting, grouping, joining to a calendar table — but it is worth keeping the original label alongside for a while. When a total looks wrong, the first question is often ",[14,1891,1892],{},"which rows went into which month?",", and having the label next to the parsed period answers it immediately. When the workbook is written back out, a monthly period is best stored as the first day of the month formatted as ",[81,1895,1896],{},"mmm yyyy",", so Excel sees a real date and readers see ",[14,1899,1900],{},"Sep 2026","; a quarter can be stored the same way with a custom label in a neighbouring column.",[592,1903,601,1908,601,1911,601,1914,601,1917,601,1922,601,1928,601,1933,601,1937,601,1941,601,1945,601,1948,601,1953,601,1957,601,1960,601,1963,601,1966],{"viewBox":1904,"role":595,"ariaLabelledBy":1905,"xmlns":599,"style":600},"4 0 752 199",[1906,1907],"tm-types-t","tm-types-d",[603,1909,1910],{"id":1906},"Date or period",[607,1912,1913],{"id":1907},"A date is a single day and suits events such as an order date. A period represents a whole month, quarter or week and suits labels such as Sept-26 or Q3 2026; it sorts and does arithmetic by whole periods and converts to a start or end date when needed.",[611,1915],{"x":613,"y":614,"width":615,"height":1916,"fill":617},"199",[611,1918],{"x":620,"y":621,"width":1919,"height":1920,"rx":1921,"fill":625,"stroke":626,"style":627},"351.0","167.0","14",[629,1923,1927],{"x":1924,"y":1925,"style":1926},"195.5","44.0","font-size:14px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","Timestamp (a day)",[86,1929],{"x1":1930,"y1":1931,"x2":1932,"y2":1931,"stroke":626,"style":1373},"36.0","57.0","355.0",[629,1934,1936],{"x":1924,"y":1935,"style":1434},"77.0","one specific day",[629,1938,1940],{"x":1924,"y":1939,"style":1434},"103.0","orders, payments, events",[629,1942,1944],{"x":1924,"y":1943,"style":1434},"129.0","arithmetic in days",[611,1946],{"x":1947,"y":621,"width":1919,"height":1920,"rx":1921,"fill":710,"stroke":711,"style":627},"389.0",[629,1949,1952],{"x":1950,"y":1925,"style":1951},"564.5","font-size:14px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","Period (a span)",[86,1954],{"x1":1955,"y1":1931,"x2":1956,"y2":1931,"stroke":711,"style":1373},"405.0","724.0",[629,1958,1959],{"x":1950,"y":1935,"style":1434},"a whole month, quarter or week",[629,1961,1962],{"x":1950,"y":1939,"style":1434},"labels like Sept-26, Q3",[629,1964,1965],{"x":1950,"y":1943,"style":1434},"arithmetic in whole periods",[629,1967,1969],{"x":1950,"y":1968,"style":1434},"155.0",".start_time \u002F .end_time",[69,1971,1973],{"id":1972},"common-pitfalls","Common pitfalls",[1975,1976,1977,1985,1994,2003,2013],"ul",{},[1978,1979,1980,1984],"li",{},[1981,1982,1983],"strong",{},"Letting pandas guess the format."," Give explicit formats and try them in order.",[1978,1986,1987,1993],{},[1981,1988,1989,1990,1992],{},"Assuming ",[81,1991,311],{}," knows Sept."," Normalise common abbreviations before parsing.",[1978,1995,1996,1999,2000,2002],{},[1981,1997,1998],{},"Storing a month as a day."," Use a monthly ",[81,2001,581],{}," for labels that mean a whole month.",[1978,2004,2005,2008,2009,2012],{},[1981,2006,2007],{},"Non-ISO week numbers."," Use ",[81,2010,2011],{},"%G-W%V-%u"," for ISO weeks, and check which convention the source uses.",[1978,2014,2015,2018],{},[1981,2016,2017],{},"Silent NaT."," Report every label that no rule matched.",[69,2020,2022],{"id":2021},"conclusion","Conclusion",[10,2024,2025,2026,2028,2029,2031],{},"To convert period labels into dates, normalise the text, try a short list of explicit formats in order and turn months into monthly periods; extract quarters with a regular expression and build them with ",[81,2027,1330],{},"; parse ISO weeks with ",[81,2030,2011],{},"; map fiscal periods using the fiscal year's start month; and turn weekday names into numbers and an ordered categorical. Whatever matches no rule should be listed, not quietly dropped.",[69,2033,2035],{"id":2034},"frequently-asked-questions","Frequently asked questions",[10,2037,2038,2041,2042,2045,2046,2049],{},[1981,2039,2040],{},"How do I convert \"Jan 2026\" to a date in pandas?","\nUse ",[81,2043,2044],{},"pd.to_datetime(s, format=\"%b %Y\")",", and ",[81,2047,2048],{},".dt.to_period(\"M\")"," if the value means the whole month.",[10,2051,2052,2055,2056,2058],{},[1981,2053,2054],{},"Why does pandas not parse \"Sept\"?","\nThe ",[81,2057,311],{}," directive expects three-letter abbreviations; replace \"Sept\" with \"Sep\" before parsing.",[10,2060,2061,2064,2065,2068,2069,2072],{},[1981,2062,2063],{},"How do I convert an ISO week number to a date?","\nBuild a string like ",[81,2066,2067],{},"2026-W14-1"," and parse it with ",[81,2070,2071],{},"format=\"%G-W%V-%u\"",", which gives the Monday of that week.",[10,2074,2075,2078,2079,2082],{},[1981,2076,2077],{},"How do I sort weekday names Monday to Sunday?","\nMake them an ordered ",[81,2080,2081],{},"pd.Categorical"," with the categories in weekday order.",[69,2084,2086],{"id":2085},"related","Related",[1975,2088,2089,2095,2102,2109,2116],{},[1978,2090,2091,2092,2094],{},"Up one level: ",[63,2093,66],{"href":65}," — dates in Excel data.",[1978,2096,2097,2101],{},[63,2098,2100],{"href":2099},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Ffix-mixed-day-first-and-month-first-dates-in-excel-data\u002F","Fix Mixed Day-First and Month-First Dates in Excel Data"," — ambiguous full dates.",[1978,2103,2104,2108],{},[63,2105,2107],{"href":2106},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fgroup-excel-rows-by-month-and-quarter-with-pandas\u002F","Group Excel Rows by Month and Quarter with pandas"," — using the periods.",[1978,2110,2111,2115],{},[63,2112,2114],{"href":2113},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fcalculate-the-nth-weekday-of-a-month\u002F","Calculate the Nth Weekday of a Month"," — weekdays as dates.",[1978,2117,2118,2122],{},[63,2119,2121],{"href":2120},"\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"," — full dates rather than labels.",[2124,2125,2126],"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 .s_b0D, html code.shiki .s_b0D{--shiki-default:#22863A;--shiki-default-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold}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}html pre.shiki code .sa561, html code.shiki .sa561{--shiki-default:#E36209;--shiki-dark:#FFB757}html pre.shiki code .s-wDw, html code.shiki .s-wDw{--shiki-default:#6A737D;--shiki-dark:#BDC4CC}",{"title":79,"searchDepth":138,"depth":138,"links":2128},[2129,2130,2131,2132,2133,2134,2135,2136,2137,2138],{"id":71,"depth":138,"text":72},{"id":111,"depth":138,"text":112},{"id":752,"depth":138,"text":753},{"id":1571,"depth":138,"text":1572},{"id":1868,"depth":138,"text":1869},{"id":1885,"depth":138,"text":1886},{"id":1972,"depth":138,"text":1973},{"id":2021,"depth":138,"text":2022},{"id":2034,"depth":138,"text":2035},{"id":2085,"depth":138,"text":2086},"2026-10-02","Turn the period labels people type into Excel — \"Jan 2026\", \"September\", \"Sept-26\", \"Q3 2026\", \"Week 14\", \"FY27 P03\", \"Mon\" — into real dates and sortable periods with pandas: explicit formats for month names, a lookup for abbreviations pandas does not know, ISO week numbers, quarters, fiscal periods with a different year start, and weekday names in order, with every unparsed label reported.","md",[2143,2145,2147,2149],{"q":2040,"a":2144},"Use pd.to_datetime(s, format=\"%b %Y\"), and .dt.to_period(\"M\") if the value means the whole month.",{"q":2054,"a":2146},"The %b directive expects three-letter abbreviations; replace \"Sept\" with \"Sep\" before parsing.",{"q":2063,"a":2148},"Build a string like 2026-W14-1 and parse it with format=\"%G-W%V-%u\", which gives the Monday of that week.",{"q":2077,"a":2150},"Make them an ordered pd.Categorical with the categories in weekday order.","convert text month to date pandas",null,{"breadcrumb":2154},[2155,2158,2161],{"name":2156,"item":2157},"Home","\u002F",{"name":2159,"item":2160},"Advanced Data Transformation and Cleaning for Excel Automation","\u002Fadvanced-data-transformation-and-cleaning\u002F",{"name":66,"item":65},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fconvert-text-months-and-weekdays-to-dates",{"title":2164,"description":2165},"Convert Text Months and Weekdays to Dates in pandas","Parse month names, abbreviations like Sept, quarters, ISO weeks, fiscal periods and weekday names from Excel text into dates and periods with pandas, and report labels that do not parse.","convert-text-months-and-weekdays-to-dates","advanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fconvert-text-months-and-weekdays-to-dates\u002Findex",[2169,2170],"dates-and-times","data-cleaning","how-to","ffXyyi5ebCm1VMdwlgQPcHyNkT5xOzUBLGlxO3mm_vM",[2174,2178],{"title":2175,"path":2176,"stem":2177,"children":-1},"Convert Dates Like 20240131, 31.01.24 and 2024031 with pandas","\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fconvert-text-dates-like-20240131-with-pandas","advanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fconvert-text-dates-like-20240131-with-pandas\u002Findex",{"title":2179,"path":2180,"stem":2181,"children":-1},"Convert Unix Timestamps to Excel Dates with pandas","\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fconvert-unix-timestamps-to-excel-dates-with-pandas","advanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fconvert-unix-timestamps-to-excel-dates-with-pandas\u002Findex",[2183,2185],{"path":2184,"title":2159},"\u002Fadvanced-data-transformation-and-cleaning",{"path":2186,"title":66},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data",[],[2189,2192,2195,2198,2201,2204],{"path":2190,"title":2191,"kind":2171},"\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fhighlight-overdue-dates-with-openpyxl","Highlight Overdue Dates in Excel with openpyxl",{"path":2193,"title":2194,"kind":2171},"\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":2196,"title":2197,"kind":2171},"\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":2199,"title":2200,"kind":2171},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcreating-pivot-tables-from-excel-data\u002Fcalculate-moving-averages-with-pandas-rolling","Calculate Moving Averages with pandas rolling",{"path":2202,"title":2203,"kind":2171},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Feomonth-and-edate-equivalents-in-pandas","EOMONTH and EDATE Equivalents in pandas",{"path":2205,"title":2206,"kind":2171},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fyearfrac-and-days360-equivalents-in-python","YEARFRAC and DAYS360 Equivalents in Python",1790972104646]