[{"data":1,"prerenderedAt":757},["ShallowReactive",2],{"guide-daylight-saving-time-edge-cases":3},{"id":4,"title":5,"body":6,"date":749,"description":750,"extension":751,"meta":752,"navigation":221,"path":753,"readingTime":212,"seo":754,"stem":755,"__hash__":756},"guides\u002Fguides\u002Fdaylight-saving-time-edge-cases.md","Daylight Saving Time Edge Cases",{"type":7,"value":8,"toc":724},"minimark",[9,14,18,21,25,28,39,46,51,105,109,115,311,315,318,324,327,330,365,368,371,375,378,382,388,392,398,401,513,516,520,524,527,531,534,537,556,560,563,567,659,663,683,687,708,712,720],[10,11,13],"h2",{"id":12},"why-dst-breaks-software","Why DST Breaks Software",[15,16,17],"p",{},"Daylight Saving Time is a political decision, not a physical one. Governments decide when — or whether — to shift clocks. Rules change, exceptions appear, and some regions abolish DST entirely after decades of observance.",[15,19,20],{},"Your code needs to handle three categories of DST problems: timestamps that exist twice, timestamps that never exist, and durations that are not what you expect.",[10,22,24],{"id":23},"the-ambiguous-hour","The Ambiguous Hour",[15,26,27],{},"When clocks fall back, one local time occurs twice.",[29,30,35],"pre",{"className":31,"code":33,"language":34},[32],"language-text","2025-11-02 01:30:00 EDT (UTC-4)\n2025-11-02 01:30:00 EST (UTC-5)\n","text",[36,37,33],"code",{"__ignoreMap":38},"",[15,40,41,42,45],{},"Both timestamps look identical in local time: ",[36,43,44],{},"01:30",". Without an offset or timezone identifier, you cannot tell which one a user means.",[47,48,50],"h3",{"id":49},"how-it-breaks-code","How it breaks code",[29,52,56],{"className":53,"code":54,"language":55,"meta":38,"style":38},"language-javascript shiki shiki-themes github-light github-dark","\u002F\u002F DANGEROUS: parsing without timezone context\nconst local = new Date('2025-11-02 01:30:00')\n\u002F\u002F Browser assumes the SECOND occurrence (EST) — but your user might mean the first (EDT)\n","javascript",[36,57,58,67,99],{"__ignoreMap":38},[59,60,63],"span",{"class":61,"line":62},"line",1,[59,64,66],{"class":65},"sJ8bj","\u002F\u002F DANGEROUS: parsing without timezone context\n",[59,68,70,74,78,81,84,88,92,96],{"class":61,"line":69},2,[59,71,73],{"class":72},"szBVR","const",[59,75,77],{"class":76},"sj4cs"," local",[59,79,80],{"class":72}," =",[59,82,83],{"class":72}," new",[59,85,87],{"class":86},"sScJk"," Date",[59,89,91],{"class":90},"sVt8B","(",[59,93,95],{"class":94},"sZZnC","'2025-11-02 01:30:00'",[59,97,98],{"class":90},")\n",[59,100,102],{"class":61,"line":101},3,[59,103,104],{"class":65},"\u002F\u002F Browser assumes the SECOND occurrence (EST) — but your user might mean the first (EDT)\n",[47,106,108],{"id":107},"how-to-handle-it","How to handle it",[15,110,111,112,114],{},"Always store and compute in UTC. Convert to local time only for display. When a user enters ",[36,113,44],{}," on a fall-back date, ask which occurrence they mean, or disambiguate using the IANA timezone database.",[29,116,118],{"className":53,"code":117,"language":55,"meta":38,"style":38},"\u002F\u002F Using Intl to check ambiguity\nconst tz = 'America\u002FNew_York'\nconst formatter = new Intl.DateTimeFormat('en-US', {\n  timeZone: tz,\n  year: 'numeric', month: '2-digit', day: '2-digit',\n  hour: '2-digit', minute: '2-digit', timeZoneName: 'short'\n})\n\n\u002F\u002F Same wall time, two UTC equivalents\nconst edt = new Date('2025-11-02T05:30:00Z') \u002F\u002F 01:30 EDT\nconst est = new Date('2025-11-02T06:30:00Z') \u002F\u002F 01:30 EST\n\nformatter.format(edt) \u002F\u002F \"11\u002F02\u002F2025, 1:30 AM EDT\"\nformatter.format(est) \u002F\u002F \"11\u002F02\u002F2025, 1:30 AM EST\"\n",[36,119,120,125,137,162,168,191,210,216,223,229,254,278,283,298],{"__ignoreMap":38},[59,121,122],{"class":61,"line":62},[59,123,124],{"class":65},"\u002F\u002F Using Intl to check ambiguity\n",[59,126,127,129,132,134],{"class":61,"line":69},[59,128,73],{"class":72},[59,130,131],{"class":76}," tz",[59,133,80],{"class":72},[59,135,136],{"class":94}," 'America\u002FNew_York'\n",[59,138,139,141,144,146,148,151,154,156,159],{"class":61,"line":101},[59,140,73],{"class":72},[59,142,143],{"class":76}," formatter",[59,145,80],{"class":72},[59,147,83],{"class":72},[59,149,150],{"class":90}," Intl.",[59,152,153],{"class":86},"DateTimeFormat",[59,155,91],{"class":90},[59,157,158],{"class":94},"'en-US'",[59,160,161],{"class":90},", {\n",[59,163,165],{"class":61,"line":164},4,[59,166,167],{"class":90},"  timeZone: tz,\n",[59,169,171,174,177,180,183,186,188],{"class":61,"line":170},5,[59,172,173],{"class":90},"  year: ",[59,175,176],{"class":94},"'numeric'",[59,178,179],{"class":90},", month: ",[59,181,182],{"class":94},"'2-digit'",[59,184,185],{"class":90},", day: ",[59,187,182],{"class":94},[59,189,190],{"class":90},",\n",[59,192,194,197,199,202,204,207],{"class":61,"line":193},6,[59,195,196],{"class":90},"  hour: ",[59,198,182],{"class":94},[59,200,201],{"class":90},", minute: ",[59,203,182],{"class":94},[59,205,206],{"class":90},", timeZoneName: ",[59,208,209],{"class":94},"'short'\n",[59,211,213],{"class":61,"line":212},7,[59,214,215],{"class":90},"})\n",[59,217,219],{"class":61,"line":218},8,[59,220,222],{"emptyLinePlaceholder":221},true,"\n",[59,224,226],{"class":61,"line":225},9,[59,227,228],{"class":65},"\u002F\u002F Same wall time, two UTC equivalents\n",[59,230,232,234,237,239,241,243,245,248,251],{"class":61,"line":231},10,[59,233,73],{"class":72},[59,235,236],{"class":76}," edt",[59,238,80],{"class":72},[59,240,83],{"class":72},[59,242,87],{"class":86},[59,244,91],{"class":90},[59,246,247],{"class":94},"'2025-11-02T05:30:00Z'",[59,249,250],{"class":90},") ",[59,252,253],{"class":65},"\u002F\u002F 01:30 EDT\n",[59,255,257,259,262,264,266,268,270,273,275],{"class":61,"line":256},11,[59,258,73],{"class":72},[59,260,261],{"class":76}," est",[59,263,80],{"class":72},[59,265,83],{"class":72},[59,267,87],{"class":86},[59,269,91],{"class":90},[59,271,272],{"class":94},"'2025-11-02T06:30:00Z'",[59,274,250],{"class":90},[59,276,277],{"class":65},"\u002F\u002F 01:30 EST\n",[59,279,281],{"class":61,"line":280},12,[59,282,222],{"emptyLinePlaceholder":221},[59,284,286,289,292,295],{"class":61,"line":285},13,[59,287,288],{"class":90},"formatter.",[59,290,291],{"class":86},"format",[59,293,294],{"class":90},"(edt) ",[59,296,297],{"class":65},"\u002F\u002F \"11\u002F02\u002F2025, 1:30 AM EDT\"\n",[59,299,301,303,305,308],{"class":61,"line":300},14,[59,302,288],{"class":90},[59,304,291],{"class":86},[59,306,307],{"class":90},"(est) ",[59,309,310],{"class":65},"\u002F\u002F \"11\u002F02\u002F2025, 1:30 AM EST\"\n",[10,312,314],{"id":313},"the-missing-hour","The Missing Hour",[15,316,317],{},"When clocks spring forward, one local time never exists.",[29,319,322],{"className":320,"code":321,"language":34},[32],"2025-03-09 02:30:00 — this time does not exist in America\u002FNew_York\n",[36,323,321],{"__ignoreMap":38},[15,325,326],{},"Clocks jump from 01:59:59 EST directly to 03:00:00 EDT. Any timestamp between 02:00 and 03:00 on that date is phantom.",[47,328,50],{"id":329},"how-it-breaks-code-1",[29,331,333],{"className":53,"code":332,"language":55,"meta":38,"style":38},"\u002F\u002F User schedules a recurring event at 2:30 AM daily\n\u002F\u002F On March 9, that time does not exist\n\u002F\u002F Different systems handle this differently:\n\u002F\u002F - Some move it to 3:30 AM (spring forward)\n\u002F\u002F - Some move it to 1:30 AM (fall back)\n\u002F\u002F - Some silently drop the event\n",[36,334,335,340,345,350,355,360],{"__ignoreMap":38},[59,336,337],{"class":61,"line":62},[59,338,339],{"class":65},"\u002F\u002F User schedules a recurring event at 2:30 AM daily\n",[59,341,342],{"class":61,"line":69},[59,343,344],{"class":65},"\u002F\u002F On March 9, that time does not exist\n",[59,346,347],{"class":61,"line":101},[59,348,349],{"class":65},"\u002F\u002F Different systems handle this differently:\n",[59,351,352],{"class":61,"line":164},[59,353,354],{"class":65},"\u002F\u002F - Some move it to 3:30 AM (spring forward)\n",[59,356,357],{"class":61,"line":170},[59,358,359],{"class":65},"\u002F\u002F - Some move it to 1:30 AM (fall back)\n",[59,361,362],{"class":61,"line":193},[59,363,364],{"class":65},"\u002F\u002F - Some silently drop the event\n",[47,366,108],{"id":367},"how-to-handle-it-1",[15,369,370],{},"Validate user-input times against the IANA database. If a time falls in a gap, present a clear message: \"This time does not exist on this date due to Daylight Saving Time. Please choose 1:30 AM or 3:30 AM.\"",[10,372,374],{"id":373},"duration-shifts","Duration Shifts",[15,376,377],{},"A \"24-hour\" period does not always contain 24 hours in local time.",[47,379,381],{"id":380},"spring-forward-23-hour-day","Spring forward: 23-hour day",[29,383,386],{"className":384,"code":385,"language":34},[32],"March 9, 2025: 1:00 AM EST → March 10, 2025: 1:00 AM EDT = 23 hours\n",[36,387,385],{"__ignoreMap":38},[47,389,391],{"id":390},"fall-back-25-hour-day","Fall back: 25-hour day",[29,393,396],{"className":394,"code":395,"language":34},[32],"November 2, 2025: 1:00 AM EDT → November 3, 2025: 1:00 AM EST = 25 hours\n",[36,397,395],{"__ignoreMap":38},[47,399,50],{"id":400},"how-it-breaks-code-2",[29,402,404],{"className":53,"code":403,"language":55,"meta":38,"style":38},"\u002F\u002F WRONG: assuming 24 hours per day\nconst tomorrow = new Date(today.getTime() + 24 * 60 * 60 * 1000)\n\u002F\u002F On a spring-forward day, this lands on the SAME calendar date at 1:00 AM EDT\n\u002F\u002F instead of the next day's midnight\n\n\u002F\u002F CORRECT: use date arithmetic, not millisecond arithmetic\nconst tomorrow = new Date(today)\ntomorrow.setDate(tomorrow.getDate() + 1)\n",[36,405,406,411,456,461,466,470,475,490],{"__ignoreMap":38},[59,407,408],{"class":61,"line":62},[59,409,410],{"class":65},"\u002F\u002F WRONG: assuming 24 hours per day\n",[59,412,413,415,418,420,422,424,427,430,433,436,439,442,445,447,449,451,454],{"class":61,"line":69},[59,414,73],{"class":72},[59,416,417],{"class":76}," tomorrow",[59,419,80],{"class":72},[59,421,83],{"class":72},[59,423,87],{"class":86},[59,425,426],{"class":90},"(today.",[59,428,429],{"class":86},"getTime",[59,431,432],{"class":90},"() ",[59,434,435],{"class":72},"+",[59,437,438],{"class":76}," 24",[59,440,441],{"class":72}," *",[59,443,444],{"class":76}," 60",[59,446,441],{"class":72},[59,448,444],{"class":76},[59,450,441],{"class":72},[59,452,453],{"class":76}," 1000",[59,455,98],{"class":90},[59,457,458],{"class":61,"line":101},[59,459,460],{"class":65},"\u002F\u002F On a spring-forward day, this lands on the SAME calendar date at 1:00 AM EDT\n",[59,462,463],{"class":61,"line":164},[59,464,465],{"class":65},"\u002F\u002F instead of the next day's midnight\n",[59,467,468],{"class":61,"line":170},[59,469,222],{"emptyLinePlaceholder":221},[59,471,472],{"class":61,"line":193},[59,473,474],{"class":65},"\u002F\u002F CORRECT: use date arithmetic, not millisecond arithmetic\n",[59,476,477,479,481,483,485,487],{"class":61,"line":212},[59,478,73],{"class":72},[59,480,417],{"class":76},[59,482,80],{"class":72},[59,484,83],{"class":72},[59,486,87],{"class":86},[59,488,489],{"class":90},"(today)\n",[59,491,492,495,498,501,504,506,508,511],{"class":61,"line":218},[59,493,494],{"class":90},"tomorrow.",[59,496,497],{"class":86},"setDate",[59,499,500],{"class":90},"(tomorrow.",[59,502,503],{"class":86},"getDate",[59,505,432],{"class":90},[59,507,435],{"class":72},[59,509,510],{"class":76}," 1",[59,512,98],{"class":90},[15,514,515],{},"For scheduling: always compute durations in UTC. Display in local time. A daily recurring event should be stored as \"daily at 14:00 UTC\" rather than \"daily at 9:00 AM Eastern\" — the latter shifts with DST.",[10,517,519],{"id":518},"international-edge-cases","International Edge Cases",[47,521,523],{"id":522},"the-southern-hemisphere","The Southern Hemisphere",[15,525,526],{},"Countries below the equator observe DST in opposite months. Australia springs forward in October and falls back in April. If your team is in New York and your users are in Sydney, both hemispheres' transitions affect your application.",[47,528,530],{"id":529},"regions-that-abolished-dst","Regions that abolished DST",[15,532,533],{},"The European Union voted to abolish DST in 2019. Implementation has been delayed repeatedly. Your code should rely on the IANA database, not assumptions about which countries observe DST.",[15,535,536],{},"Notable non-observers:",[538,539,540,544,547,550,553],"ul",{},[541,542,543],"li",{},"Japan (never observed)",[541,545,546],{},"China (single timezone, no DST)",[541,548,549],{},"India (no DST)",[541,551,552],{},"Arizona (most of the state; the Navajo Nation does observe DST)",[541,554,555],{},"Hawaii (no DST)",[47,557,559],{"id":558},"last-minute-rule-changes","Last-minute rule changes",[15,561,562],{},"Brazil abolished DST in 2019, then reinstated it temporarily in 2021 during a power crisis. Russia moved between permanent summer time, permanent winter time, and back. Your timezone library must be updated regularly to track these changes.",[10,564,566],{"id":565},"timezone-selection-anti-patterns","Timezone Selection Anti-Patterns",[568,569,570,586],"table",{},[571,572,573],"thead",{},[574,575,576,580,583],"tr",{},[577,578,579],"th",{},"Anti-pattern",[577,581,582],{},"Why it fails",[577,584,585],{},"Correct approach",[587,588,589,601,626,637,648],"tbody",{},[574,590,591,595,598],{},[592,593,594],"td",{},"Hardcoding UTC offsets",[592,596,597],{},"Offsets change with DST",[592,599,600],{},"Use IANA identifiers",[574,602,603,614,617],{},[592,604,605,606,609,610,613],{},"Using abbreviations (",[36,607,608],{},"EST",", ",[36,611,612],{},"CST",")",[592,615,616],{},"Ambiguous across regions",[592,618,619,620,609,623],{},"Use ",[36,621,622],{},"America\u002FNew_York",[36,624,625],{},"America\u002FChicago",[574,627,628,631,634],{},[592,629,630],{},"Storing local time without timezone",[592,632,633],{},"Cannot reconstruct UTC",[592,635,636],{},"Store UTC + IANA timezone",[574,638,639,642,645],{},[592,640,641],{},"Assuming DST dates are fixed",[592,643,644],{},"Governments change rules",[592,646,647],{},"Keep IANA database updated",[574,649,650,653,656],{},[592,651,652],{},"Testing only summer dates",[592,654,655],{},"Misses fall-back ambiguities",[592,657,658],{},"Test both transition dates",[10,660,662],{"id":661},"key-takeaways","Key Takeaways",[538,664,665,668,671,674,677,680],{},[541,666,667],{},"DST creates ambiguous hours (fall back) and missing hours (spring forward) — always validate user input against the IANA database",[541,669,670],{},"Store timestamps in UTC; convert to local time only for display",[541,672,673],{},"Never assume days are 24 hours — use date arithmetic, not millisecond arithmetic",[541,675,676],{},"Southern Hemisphere DST operates in opposite months — global apps must handle both",[541,678,679],{},"Regions change DST rules without warning — keep your timezone library updated",[541,681,682],{},"Always use IANA timezone identifiers, never abbreviations or hardcoded offsets",[10,684,686],{"id":685},"related-guides","Related Guides",[538,688,689,696,702],{},[541,690,691],{},[692,693,695],"a",{"href":694},"\u002Fguides\u002Ftimezone-converter-guide","Timezone Converter Guide",[541,697,698],{},[692,699,701],{"href":700},"\u002Fguides\u002Fworking-with-timezones","Working with Timezones",[541,703,704],{},[692,705,707],{"href":706},"\u002Fguides\u002Ftimezone-conversion-scheduled-jobs","Timezone Conversion in Scheduled Jobs",[10,709,711],{"id":710},"try-it-yourself","Try It Yourself",[15,713,714,715,719],{},"Convert times across DST boundaries safely with our free ",[692,716,718],{"href":717},"\u002Ftools\u002Ftimezone-converter","Timezone Converter",". All conversions use IANA timezone data with automatic DST adjustment — no manual offset lookup needed.",[721,722,723],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}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);}",{"title":38,"searchDepth":69,"depth":69,"links":725},[726,727,731,735,740,745,746,747,748],{"id":12,"depth":69,"text":13},{"id":23,"depth":69,"text":24,"children":728},[729,730],{"id":49,"depth":101,"text":50},{"id":107,"depth":101,"text":108},{"id":313,"depth":69,"text":314,"children":732},[733,734],{"id":329,"depth":101,"text":50},{"id":367,"depth":101,"text":108},{"id":373,"depth":69,"text":374,"children":736},[737,738,739],{"id":380,"depth":101,"text":381},{"id":390,"depth":101,"text":391},{"id":400,"depth":101,"text":50},{"id":518,"depth":69,"text":519,"children":741},[742,743,744],{"id":522,"depth":101,"text":523},{"id":529,"depth":101,"text":530},{"id":558,"depth":101,"text":559},{"id":565,"depth":69,"text":566},{"id":661,"depth":69,"text":662},{"id":685,"depth":69,"text":686},{"id":710,"depth":69,"text":711},"2026-05-28","Navigate DST edge cases that break code — ambiguous hours, missing hours, duration shifts, and timezone rules that change without warning.","md",{"immutable":221},"\u002Fguides\u002Fdaylight-saving-time-edge-cases",{"title":5,"description":750},"guides\u002Fdaylight-saving-time-edge-cases","OUEm8HKNBl2zZBR7F5rM2_3PzfJvXHzd7sy1-X6Omug",1780401333388]