[{"data":1,"prerenderedAt":824},["ShallowReactive",2],{"blog-\u002Fblog\u002Fpython-datetime-explained":3},{"id":4,"title":5,"body":6,"description":811,"difficulty":812,"extension":813,"framework":814,"frameworkSlug":58,"meta":815,"navigation":86,"order":90,"path":816,"qaPath":817,"seo":818,"stem":819,"subtopic":21,"topic":820,"topicSlug":821,"updated":822,"__hash__":823},"blog\u002Fblog\u002Fpython-datetime-explained.md","Python datetime Explained — date, time, timedelta, Timezones, and Parsing",{"type":7,"value":8,"toc":801},"minimark",[9,14,28,32,53,166,176,180,194,245,256,260,271,348,354,358,367,515,525,529,555,651,662,666,669,717,728,732,797],[10,11,13],"h2",{"id":12},"python-datetime-explained","Python datetime, explained",[15,16,17,18,22,23,27],"p",{},"Dates and times are deceptively tricky — timezones, parsing, and arithmetic all have sharp\nedges. Python's ",[19,20,21],"code",{},"datetime"," module has everything you need, but using it well means\nunderstanding a few key distinctions, above all ",[24,25,26],"strong",{},"naive vs timezone-aware"," datetimes.",[10,29,31],{"id":30},"the-core-types","The core types",[15,33,34,35,38,39,42,43,45,46,49,50,52],{},"The module provides ",[19,36,37],{},"date"," (calendar day), ",[19,40,41],{},"time"," (clock time), ",[19,44,21],{}," (both together),\nand ",[19,47,48],{},"timedelta"," (a duration). ",[19,51,21],{}," is the one you'll use most.",[54,55,60],"pre",{"className":56,"code":57,"language":58,"meta":59,"style":59},"language-python shiki shiki-themes github-light github-dark","from datetime import date, datetime, time, timedelta\n\ndate(2026, 6, 19)                    # 2026-06-19\ndatetime(2026, 6, 19, 14, 30)        # 2026-06-19 14:30:00\ndatetime.now()                       # current local datetime (naive!)\ndate.today()                         # today's date\n","python","",[19,61,62,81,88,116,148,157],{"__ignoreMap":59},[63,64,67,71,75,78],"span",{"class":65,"line":66},"line",1,[63,68,70],{"class":69},"szBVR","from",[63,72,74],{"class":73},"sVt8B"," datetime ",[63,76,77],{"class":69},"import",[63,79,80],{"class":73}," date, datetime, time, timedelta\n",[63,82,84],{"class":65,"line":83},2,[63,85,87],{"emptyLinePlaceholder":86},true,"\n",[63,89,91,94,98,101,104,106,109,112],{"class":65,"line":90},3,[63,92,93],{"class":73},"date(",[63,95,97],{"class":96},"sj4cs","2026",[63,99,100],{"class":73},", ",[63,102,103],{"class":96},"6",[63,105,100],{"class":73},[63,107,108],{"class":96},"19",[63,110,111],{"class":73},")                    ",[63,113,115],{"class":114},"sJ8bj","# 2026-06-19\n",[63,117,119,122,124,126,128,130,132,134,137,139,142,145],{"class":65,"line":118},4,[63,120,121],{"class":73},"datetime(",[63,123,97],{"class":96},[63,125,100],{"class":73},[63,127,103],{"class":96},[63,129,100],{"class":73},[63,131,108],{"class":96},[63,133,100],{"class":73},[63,135,136],{"class":96},"14",[63,138,100],{"class":73},[63,140,141],{"class":96},"30",[63,143,144],{"class":73},")        ",[63,146,147],{"class":114},"# 2026-06-19 14:30:00\n",[63,149,151,154],{"class":65,"line":150},5,[63,152,153],{"class":73},"datetime.now()                       ",[63,155,156],{"class":114},"# current local datetime (naive!)\n",[63,158,160,163],{"class":65,"line":159},6,[63,161,162],{"class":73},"date.today()                         ",[63,164,165],{"class":114},"# today's date\n",[15,167,168,171,172,175],{},[19,169,170],{},"datetime.now()"," returns a ",[24,173,174],{},"naive"," datetime by default — no timezone attached, which is the\nsource of most datetime bugs.",[10,177,179],{"id":178},"naive-vs-timezone-aware","Naive vs timezone-aware",[15,181,182,183,185,186,189,190,193],{},"A ",[24,184,174],{}," datetime has no timezone; an ",[24,187,188],{},"aware"," one carries a ",[19,191,192],{},"tzinfo",". Mixing them, or\nassuming a naive value is UTC (or local), causes silent errors. Make production datetimes\naware and prefer UTC.",[54,195,197],{"className":56,"code":196,"language":58,"meta":59,"style":59},"from datetime import datetime, timezone\n\ndatetime.now()                       # naive — ambiguous which zone\ndatetime.now(timezone.utc)           # aware, UTC — do this\ndatetime.now().tzinfo                # None\ndatetime.now(timezone.utc).tzinfo    # UTC\n",[19,198,199,210,214,221,229,237],{"__ignoreMap":59},[63,200,201,203,205,207],{"class":65,"line":66},[63,202,70],{"class":69},[63,204,74],{"class":73},[63,206,77],{"class":69},[63,208,209],{"class":73}," datetime, timezone\n",[63,211,212],{"class":65,"line":83},[63,213,87],{"emptyLinePlaceholder":86},[63,215,216,218],{"class":65,"line":90},[63,217,153],{"class":73},[63,219,220],{"class":114},"# naive — ambiguous which zone\n",[63,222,223,226],{"class":65,"line":118},[63,224,225],{"class":73},"datetime.now(timezone.utc)           ",[63,227,228],{"class":114},"# aware, UTC — do this\n",[63,230,231,234],{"class":65,"line":150},[63,232,233],{"class":73},"datetime.now().tzinfo                ",[63,235,236],{"class":114},"# None\n",[63,238,239,242],{"class":65,"line":159},[63,240,241],{"class":73},"datetime.now(timezone.utc).tzinfo    ",[63,243,244],{"class":114},"# UTC\n",[15,246,247,248,251,252,255],{},"Rule of thumb: ",[24,249,250],{},"store and compute in UTC",", convert to local only for display. You can't\nsubtract a naive from an aware datetime — Python raises a ",[19,253,254],{},"TypeError",".",[10,257,259],{"id":258},"timezones-with-zoneinfo","Timezones with zoneinfo",[15,261,262,263,266,267,270],{},"Since Python 3.9, the standard library's ",[19,264,265],{},"zoneinfo"," provides real IANA timezones — no\nthird-party ",[19,268,269],{},"pytz"," needed. Use it to convert between zones.",[54,272,274],{"className":56,"code":273,"language":58,"meta":59,"style":59},"from datetime import datetime, timezone\nfrom zoneinfo import ZoneInfo\n\nutc_now = datetime.now(timezone.utc)\nny = utc_now.astimezone(ZoneInfo(\"America\u002FNew_York\"))   # convert zone\ntokyo = utc_now.astimezone(ZoneInfo(\"Asia\u002FTokyo\"))\n",[19,275,276,286,298,302,313,333],{"__ignoreMap":59},[63,277,278,280,282,284],{"class":65,"line":66},[63,279,70],{"class":69},[63,281,74],{"class":73},[63,283,77],{"class":69},[63,285,209],{"class":73},[63,287,288,290,293,295],{"class":65,"line":83},[63,289,70],{"class":69},[63,291,292],{"class":73}," zoneinfo ",[63,294,77],{"class":69},[63,296,297],{"class":73}," ZoneInfo\n",[63,299,300],{"class":65,"line":90},[63,301,87],{"emptyLinePlaceholder":86},[63,303,304,307,310],{"class":65,"line":118},[63,305,306],{"class":73},"utc_now ",[63,308,309],{"class":69},"=",[63,311,312],{"class":73}," datetime.now(timezone.utc)\n",[63,314,315,318,320,323,327,330],{"class":65,"line":150},[63,316,317],{"class":73},"ny ",[63,319,309],{"class":69},[63,321,322],{"class":73}," utc_now.astimezone(ZoneInfo(",[63,324,326],{"class":325},"sZZnC","\"America\u002FNew_York\"",[63,328,329],{"class":73},"))   ",[63,331,332],{"class":114},"# convert zone\n",[63,334,335,338,340,342,345],{"class":65,"line":159},[63,336,337],{"class":73},"tokyo ",[63,339,309],{"class":69},[63,341,322],{"class":73},[63,343,344],{"class":325},"\"Asia\u002FTokyo\"",[63,346,347],{"class":73},"))\n",[15,349,350,353],{},[19,351,352],{},"astimezone"," converts an aware datetime to another zone correctly, handling DST.",[10,355,357],{"id":356},"arithmetic-with-timedelta","Arithmetic with timedelta",[15,359,360,361,363,364,366],{},"Subtracting two datetimes gives a ",[19,362,48],{},"; adding a ",[19,365,48],{}," shifts a datetime.\nDurations are easy and exact.",[54,368,370],{"className":56,"code":369,"language":58,"meta":59,"style":59},"from datetime import datetime, timedelta\n\nstart = datetime(2026, 6, 19, 9)\nend = datetime(2026, 6, 19, 17, 30)\nduration = end - start               # timedelta(hours=8, minutes=30)\nduration.total_seconds()             # 30600.0\n\ndeadline = datetime.now() + timedelta(days=7, hours=12)\n",[19,371,372,383,387,415,445,464,472,477],{"__ignoreMap":59},[63,373,374,376,378,380],{"class":65,"line":66},[63,375,70],{"class":69},[63,377,74],{"class":73},[63,379,77],{"class":69},[63,381,382],{"class":73}," datetime, timedelta\n",[63,384,385],{"class":65,"line":83},[63,386,87],{"emptyLinePlaceholder":86},[63,388,389,392,394,397,399,401,403,405,407,409,412],{"class":65,"line":90},[63,390,391],{"class":73},"start ",[63,393,309],{"class":69},[63,395,396],{"class":73}," datetime(",[63,398,97],{"class":96},[63,400,100],{"class":73},[63,402,103],{"class":96},[63,404,100],{"class":73},[63,406,108],{"class":96},[63,408,100],{"class":73},[63,410,411],{"class":96},"9",[63,413,414],{"class":73},")\n",[63,416,417,420,422,424,426,428,430,432,434,436,439,441,443],{"class":65,"line":118},[63,418,419],{"class":73},"end ",[63,421,309],{"class":69},[63,423,396],{"class":73},[63,425,97],{"class":96},[63,427,100],{"class":73},[63,429,103],{"class":96},[63,431,100],{"class":73},[63,433,108],{"class":96},[63,435,100],{"class":73},[63,437,438],{"class":96},"17",[63,440,100],{"class":73},[63,442,141],{"class":96},[63,444,414],{"class":73},[63,446,447,450,452,455,458,461],{"class":65,"line":150},[63,448,449],{"class":73},"duration ",[63,451,309],{"class":69},[63,453,454],{"class":73}," end ",[63,456,457],{"class":69},"-",[63,459,460],{"class":73}," start               ",[63,462,463],{"class":114},"# timedelta(hours=8, minutes=30)\n",[63,465,466,469],{"class":65,"line":159},[63,467,468],{"class":73},"duration.total_seconds()             ",[63,470,471],{"class":114},"# 30600.0\n",[63,473,475],{"class":65,"line":474},7,[63,476,87],{"emptyLinePlaceholder":86},[63,478,480,483,485,488,491,494,498,500,503,505,508,510,513],{"class":65,"line":479},8,[63,481,482],{"class":73},"deadline ",[63,484,309],{"class":69},[63,486,487],{"class":73}," datetime.now() ",[63,489,490],{"class":69},"+",[63,492,493],{"class":73}," timedelta(",[63,495,497],{"class":496},"s4XuR","days",[63,499,309],{"class":69},[63,501,502],{"class":96},"7",[63,504,100],{"class":73},[63,506,507],{"class":496},"hours",[63,509,309],{"class":69},[63,511,512],{"class":96},"12",[63,514,414],{"class":73},[15,516,517,520,521,524],{},[19,518,519],{},"total_seconds()"," is the right way to get a duration as a single number; don't try to read\n",[19,522,523],{},".seconds"," alone (it excludes the days component).",[10,526,528],{"id":527},"formatting-and-parsing","Formatting and parsing",[15,530,531,534,535,538,539,100,542,100,545,100,548,100,551,554],{},[19,532,533],{},"strftime"," formats a datetime to a string; ",[19,536,537],{},"strptime"," parses a string into a datetime, using\nthe same directive codes (",[19,540,541],{},"%Y",[19,543,544],{},"%m",[19,546,547],{},"%d",[19,549,550],{},"%H",[19,552,553],{},"%M",").",[54,556,558],{"className":56,"code":557,"language":58,"meta":59,"style":59},"dt = datetime(2026, 6, 19, 14, 30)\ndt.strftime(\"%Y-%m-%d %H:%M\")        # '2026-06-19 14:30'\ndt.strftime(\"%A, %B %d\")             # 'Friday, June 19'\n\ndatetime.strptime(\"2026-06-19\", \"%Y-%m-%d\")   # parse back to datetime\n",[19,559,560,589,607,625,629],{"__ignoreMap":59},[63,561,562,565,567,569,571,573,575,577,579,581,583,585,587],{"class":65,"line":66},[63,563,564],{"class":73},"dt ",[63,566,309],{"class":69},[63,568,396],{"class":73},[63,570,97],{"class":96},[63,572,100],{"class":73},[63,574,103],{"class":96},[63,576,100],{"class":73},[63,578,108],{"class":96},[63,580,100],{"class":73},[63,582,136],{"class":96},[63,584,100],{"class":73},[63,586,141],{"class":96},[63,588,414],{"class":73},[63,590,591,594,597,599,602,604],{"class":65,"line":83},[63,592,593],{"class":73},"dt.strftime(",[63,595,596],{"class":325},"\"%Y-%m-",[63,598,547],{"class":96},[63,600,601],{"class":325}," %H:%M\"",[63,603,144],{"class":73},[63,605,606],{"class":114},"# '2026-06-19 14:30'\n",[63,608,609,611,614,616,619,622],{"class":65,"line":90},[63,610,593],{"class":73},[63,612,613],{"class":325},"\"%A, %B ",[63,615,547],{"class":96},[63,617,618],{"class":325},"\"",[63,620,621],{"class":73},")             ",[63,623,624],{"class":114},"# 'Friday, June 19'\n",[63,626,627],{"class":65,"line":118},[63,628,87],{"emptyLinePlaceholder":86},[63,630,631,634,637,639,641,643,645,648],{"class":65,"line":150},[63,632,633],{"class":73},"datetime.strptime(",[63,635,636],{"class":325},"\"2026-06-19\"",[63,638,100],{"class":73},[63,640,596],{"class":325},[63,642,547],{"class":96},[63,644,618],{"class":325},[63,646,647],{"class":73},")   ",[63,649,650],{"class":114},"# parse back to datetime\n",[15,652,653,654,657,658,661],{},"For the ISO 8601 standard format, prefer ",[19,655,656],{},"dt.isoformat()"," and ",[19,659,660],{},"datetime.fromisoformat()"," —\nno format string needed.",[10,663,665],{"id":664},"timestamps-and-the-epoch","Timestamps and the epoch",[15,667,668],{},"Convert to and from Unix timestamps (seconds since 1970-01-01 UTC) for storage or APIs.",[54,670,672],{"className":56,"code":671,"language":58,"meta":59,"style":59},"from datetime import datetime, timezone\n\nts = datetime.now(timezone.utc).timestamp()         # float seconds\ndatetime.fromtimestamp(ts, tz=timezone.utc)         # back to aware datetime\n",[19,673,674,684,688,701],{"__ignoreMap":59},[63,675,676,678,680,682],{"class":65,"line":66},[63,677,70],{"class":69},[63,679,74],{"class":73},[63,681,77],{"class":69},[63,683,209],{"class":73},[63,685,686],{"class":65,"line":83},[63,687,87],{"emptyLinePlaceholder":86},[63,689,690,693,695,698],{"class":65,"line":90},[63,691,692],{"class":73},"ts ",[63,694,309],{"class":69},[63,696,697],{"class":73}," datetime.now(timezone.utc).timestamp()         ",[63,699,700],{"class":114},"# float seconds\n",[63,702,703,706,709,711,714],{"class":65,"line":118},[63,704,705],{"class":73},"datetime.fromtimestamp(ts, ",[63,707,708],{"class":496},"tz",[63,710,309],{"class":69},[63,712,713],{"class":73},"timezone.utc)         ",[63,715,716],{"class":114},"# back to aware datetime\n",[15,718,719,720,723,724,727],{},"Always pass ",[19,721,722],{},"tz=timezone.utc"," to ",[19,725,726],{},"fromtimestamp"," to get an aware result rather than a\nlocal-time naive one.",[10,729,731],{"id":730},"recap","Recap",[15,733,734,735,739,740,744,745,747,748,750,751,754,755,757,758,761,762,765,766,768,769,773,774,657,776,778,779,785,786,747,789,792,793,796],{},"Use ",[24,736,737],{},[19,738,21],{}," for date+time, ",[24,741,742],{},[19,743,48],{}," for durations, and ",[19,746,37],{},"\u002F",[19,749,41],{}," for the\nparts. The crucial distinction is ",[24,752,753],{},"naive vs aware",": ",[19,756,170],{}," is naive — prefer\n",[19,759,760],{},"datetime.now(timezone.utc)",", store\u002Fcompute in ",[24,763,764],{},"UTC",", and convert with ",[19,767,352],{}," +\n",[24,770,771],{},[19,772,265],{}," only for display. Do arithmetic with ",[19,775,48],{},[19,777,519],{},". Format\nand parse with ",[24,780,781,747,783],{},[19,782,533],{},[19,784,537],{}," directives, or use ",[19,787,788],{},"isoformat",[19,790,791],{},"fromisoformat"," for\nISO 8601. Pass ",[19,794,795],{},"tz="," when converting timestamps so results stay aware.",[798,799,800],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}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 .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":59,"searchDepth":83,"depth":83,"links":802},[803,804,805,806,807,808,809,810],{"id":12,"depth":83,"text":13},{"id":30,"depth":83,"text":31},{"id":178,"depth":83,"text":179},{"id":258,"depth":83,"text":259},{"id":356,"depth":83,"text":357},{"id":527,"depth":83,"text":528},{"id":664,"depth":83,"text":665},{"id":730,"depth":83,"text":731},"How Python's datetime module works — date vs datetime, naive vs aware timezones, arithmetic with timedelta, parsing and formatting with strptime and strftime, and why you should default to UTC.","medium","md","Python",{},"\u002Fblog\u002Fpython-datetime-explained","\u002Fpython\u002Fstdlib\u002Fdatetime",{"title":5,"description":811},"blog\u002Fpython-datetime-explained","Standard Library Essentials","stdlib","2026-06-19","tIX_W0IVC1XpLRzrAV3gn8CvZi8OVcqiQSaWPWJ4mPQ",1782244093480]