[{"data":1,"prerenderedAt":2584},["ShallowReactive",2],{"page-\u002Fgo\u002F24-time-and-dates":3},{"id":4,"title":5,"body":6,"description":2577,"extension":2578,"meta":2579,"navigation":124,"path":2580,"seo":2581,"stem":2582,"__hash__":2583},"content\u002Fgo\u002F24-time-and-dates.md","24 — Time & Dates",{"type":7,"value":8,"toc":2571},"minimark",[9,13,22,2567],[10,11,5],"h1",{"id":12},"_24-time-dates",[14,15,17,21],"h2",{"id":16},"timetime-wall-clock-monotonic-clock",[18,19,20],"code",{},"time.Time"," — Wall Clock + Monotonic Clock",[23,24,26,286,290,2369,2554,2558],"code-wrapper",{"language":25},"go",[27,28,32],"pre",{"className":29,"code":30,"language":25,"meta":31,"style":31},"language-go shiki shiki-themes github-light github-dark","\u002F\u002F ┌──────────────────────────────────────────────────────────────────────┐\n\u002F\u002F │ time.Time contains TWO clocks:                                       │\n\u002F\u002F │   - Wall clock: the \"real world\" time (can be changed by NTP\u002FDST)  │\n\u002F\u002F │   - Monotonic clock: never goes backward, unaffected by NTP\u002FDST     │\n\u002F\u002F │                                                                      │\n\u002F\u002F │ time.Now() includes BOTH clocks.                                     │\n\u002F\u002F │ time.Parse\u002Ftime.Date include ONLY the wall clock.                    │\n\u002F\u002F │                                                                      │\n\u002F\u002F │ Subtraction (t2.Sub(t1)) uses the MONOTONIC clock if both times     │\n\u002F\u002F │ have it — accurate for measuring elapsed time.                      │\n\u002F\u002F │                                                                      │\n\u002F\u002F │ == compares BOTH clocks → use t.Equal(t2) for instant comparison.   │\n\u002F\u002F │ Before\u002FAfter use the monotonic clock if available.                  │\n\u002F\u002F └──────────────────────────────────────────────────────────────────────┘\n\nfunc clocks() {\n    t1 := time.Now()        \u002F\u002F has wall + monotonic\n    time.Sleep(100 * time.Millisecond)\n    t2 := time.Now()        \u002F\u002F has wall + monotonic\n\n    elapsed := t2.Sub(t1)   \u002F\u002F uses monotonic clock — accurate even if NTP jumps\n    fmt.Println(elapsed)     \u002F\u002F ~100ms (unaffected by wall clock changes)\n\n    \u002F\u002F Parsed times have NO monotonic clock:\n    parsed, _ := time.Parse(time.RFC3339, \"2024-03-15T14:30:00Z\")\n    \u002F\u002F parsed.Sub(t1) uses the wall clock — less reliable for elapsed time\n}\n","",[18,33,34,43,49,55,61,67,73,79,84,90,96,101,107,113,119,126,141,162,184,200,205,225,240,245,251,274,280],{"__ignoreMap":31},[35,36,39],"span",{"class":37,"line":38},"line",1,[35,40,42],{"class":41},"sdCPZ","\u002F\u002F ┌──────────────────────────────────────────────────────────────────────┐\n",[35,44,46],{"class":37,"line":45},2,[35,47,48],{"class":41},"\u002F\u002F │ time.Time contains TWO clocks:                                       │\n",[35,50,52],{"class":37,"line":51},3,[35,53,54],{"class":41},"\u002F\u002F │   - Wall clock: the \"real world\" time (can be changed by NTP\u002FDST)  │\n",[35,56,58],{"class":37,"line":57},4,[35,59,60],{"class":41},"\u002F\u002F │   - Monotonic clock: never goes backward, unaffected by NTP\u002FDST     │\n",[35,62,64],{"class":37,"line":63},5,[35,65,66],{"class":41},"\u002F\u002F │                                                                      │\n",[35,68,70],{"class":37,"line":69},6,[35,71,72],{"class":41},"\u002F\u002F │ time.Now() includes BOTH clocks.                                     │\n",[35,74,76],{"class":37,"line":75},7,[35,77,78],{"class":41},"\u002F\u002F │ time.Parse\u002Ftime.Date include ONLY the wall clock.                    │\n",[35,80,82],{"class":37,"line":81},8,[35,83,66],{"class":41},[35,85,87],{"class":37,"line":86},9,[35,88,89],{"class":41},"\u002F\u002F │ Subtraction (t2.Sub(t1)) uses the MONOTONIC clock if both times     │\n",[35,91,93],{"class":37,"line":92},10,[35,94,95],{"class":41},"\u002F\u002F │ have it — accurate for measuring elapsed time.                      │\n",[35,97,99],{"class":37,"line":98},11,[35,100,66],{"class":41},[35,102,104],{"class":37,"line":103},12,[35,105,106],{"class":41},"\u002F\u002F │ == compares BOTH clocks → use t.Equal(t2) for instant comparison.   │\n",[35,108,110],{"class":37,"line":109},13,[35,111,112],{"class":41},"\u002F\u002F │ Before\u002FAfter use the monotonic clock if available.                  │\n",[35,114,116],{"class":37,"line":115},14,[35,117,118],{"class":41},"\u002F\u002F └──────────────────────────────────────────────────────────────────────┘\n",[35,120,122],{"class":37,"line":121},15,[35,123,125],{"emptyLinePlaceholder":124},true,"\n",[35,127,129,133,137],{"class":37,"line":128},16,[35,130,132],{"class":131},"svdQ7","func",[35,134,136],{"class":135},"sIsaT"," clocks",[35,138,140],{"class":139},"ssxIu","() {\n",[35,142,144,147,150,153,156,159],{"class":37,"line":143},17,[35,145,146],{"class":139},"    t1 ",[35,148,149],{"class":131},":=",[35,151,152],{"class":139}," time.",[35,154,155],{"class":135},"Now",[35,157,158],{"class":139},"()        ",[35,160,161],{"class":41},"\u002F\u002F has wall + monotonic\n",[35,163,165,168,171,174,178,181],{"class":37,"line":164},18,[35,166,167],{"class":139},"    time.",[35,169,170],{"class":135},"Sleep",[35,172,173],{"class":139},"(",[35,175,177],{"class":176},"snvgF","100",[35,179,180],{"class":131}," *",[35,182,183],{"class":139}," time.Millisecond)\n",[35,185,187,190,192,194,196,198],{"class":37,"line":186},19,[35,188,189],{"class":139},"    t2 ",[35,191,149],{"class":131},[35,193,152],{"class":139},[35,195,155],{"class":135},[35,197,158],{"class":139},[35,199,161],{"class":41},[35,201,203],{"class":37,"line":202},20,[35,204,125],{"emptyLinePlaceholder":124},[35,206,208,211,213,216,219,222],{"class":37,"line":207},21,[35,209,210],{"class":139},"    elapsed ",[35,212,149],{"class":131},[35,214,215],{"class":139}," t2.",[35,217,218],{"class":135},"Sub",[35,220,221],{"class":139},"(t1)   ",[35,223,224],{"class":41},"\u002F\u002F uses monotonic clock — accurate even if NTP jumps\n",[35,226,228,231,234,237],{"class":37,"line":227},22,[35,229,230],{"class":139},"    fmt.",[35,232,233],{"class":135},"Println",[35,235,236],{"class":139},"(elapsed)     ",[35,238,239],{"class":41},"\u002F\u002F ~100ms (unaffected by wall clock changes)\n",[35,241,243],{"class":37,"line":242},23,[35,244,125],{"emptyLinePlaceholder":124},[35,246,248],{"class":37,"line":247},24,[35,249,250],{"class":41},"    \u002F\u002F Parsed times have NO monotonic clock:\n",[35,252,254,257,259,261,264,267,271],{"class":37,"line":253},25,[35,255,256],{"class":139},"    parsed, _ ",[35,258,149],{"class":131},[35,260,152],{"class":139},[35,262,263],{"class":135},"Parse",[35,265,266],{"class":139},"(time.RFC3339, ",[35,268,270],{"class":269},"sJ6F3","\"2024-03-15T14:30:00Z\"",[35,272,273],{"class":139},")\n",[35,275,277],{"class":37,"line":276},26,[35,278,279],{"class":41},"    \u002F\u002F parsed.Sub(t1) uses the wall clock — less reliable for elapsed time\n",[35,281,283],{"class":37,"line":282},27,[35,284,285],{"class":139},"}\n",[14,287,289],{"id":288},"the-reference-time-format-by-example","The Reference Time — Format by Example",[23,291,292,657,668],{"language":25},[27,293,295],{"className":29,"code":294,"language":25,"meta":31,"style":31},"\u002F\u002F Go formats dates by writing an EXAMPLE of the reference time:\n\u002F\u002F   Mon Jan 2 15:04:05 MST 2006  (= 1\u002F2 3:04:05PM '06 -0700)\n\u002F\u002F\n\u002F\u002F Mnemonic: 1 2 3 4 5 6 7\n\u002F\u002F   1 = month (January)\n\u002F\u002F   2 = day\n\u002F\u002F   3 = hour (15 = 24h, 3 = 12h with PM)\n\u002F\u002F   4 = minute\n\u002F\u002F   5 = second\n\u002F\u002F   6 = year (2006)\n\u002F\u002F   7 = timezone (-0700)\n\nfunc formatting() {\n    t := time.Date(2024, 3, 15, 14, 30, 45, 0, time.UTC)\n\n    t.Format(\"2006-01-02\")           \u002F\u002F \"2024-03-15\"\n    t.Format(\"2006-01-02 15:04:05\")  \u002F\u002F \"2024-03-15 14:30:45\"\n    t.Format(time.RFC3339)           \u002F\u002F \"2024-03-15T14:30:45Z\"\n    t.Format(\"Mon Jan _2 15:04:05 2006\")  \u002F\u002F \"Fri Mar 15 14:30:45 2024\"\n    t.Format(\"01\u002F02\u002F2006 3:04 PM\")  \u002F\u002F \"03\u002F15\u002F2024 2:30 PM\"\n    t.Format(\"2006-01-02T15:04:05.999999-07:00\")  \u002F\u002F with microseconds\n\n    \u002F\u002F Predefined formats:\n    \u002F\u002F time.RFC3339     = \"2006-01-02T15:04:05Z07:00\"\n    \u002F\u002F time.RFC1123     = \"Mon, 02 Jan 2006 15:04:05 MST\"\n    \u002F\u002F time.Kitchen     = \"3:04PM\"\n    \u002F\u002F time.Stamp       = \"Jan _2 15:04:05\"\n}\n\n\u002F\u002F ─── Parsing ───\nfunc parsing() {\n    t, err := time.Parse(time.RFC3339, \"2024-03-15T14:30:45Z\")\n    t, err = time.Parse(\"2006-01-02\", \"2024-03-15\")\n    t, err = time.ParseInLocation(\"2006-01-02\", \"2024-03-15\", time.UTC)\n\n    \u002F\u002F ⚠️ Layout errors are runtime (not compile-time) — a wrong layout\n    \u002F\u002F silently produces a wrong result or an error. Always check err.\n}\n",[18,296,297,302,307,312,317,322,327,332,337,342,347,352,356,365,416,420,439,456,468,484,500,516,520,525,530,535,540,545,550,555,561,571,590,613,635,640,646,652],{"__ignoreMap":31},[35,298,299],{"class":37,"line":38},[35,300,301],{"class":41},"\u002F\u002F Go formats dates by writing an EXAMPLE of the reference time:\n",[35,303,304],{"class":37,"line":45},[35,305,306],{"class":41},"\u002F\u002F   Mon Jan 2 15:04:05 MST 2006  (= 1\u002F2 3:04:05PM '06 -0700)\n",[35,308,309],{"class":37,"line":51},[35,310,311],{"class":41},"\u002F\u002F\n",[35,313,314],{"class":37,"line":57},[35,315,316],{"class":41},"\u002F\u002F Mnemonic: 1 2 3 4 5 6 7\n",[35,318,319],{"class":37,"line":63},[35,320,321],{"class":41},"\u002F\u002F   1 = month (January)\n",[35,323,324],{"class":37,"line":69},[35,325,326],{"class":41},"\u002F\u002F   2 = day\n",[35,328,329],{"class":37,"line":75},[35,330,331],{"class":41},"\u002F\u002F   3 = hour (15 = 24h, 3 = 12h with PM)\n",[35,333,334],{"class":37,"line":81},[35,335,336],{"class":41},"\u002F\u002F   4 = minute\n",[35,338,339],{"class":37,"line":86},[35,340,341],{"class":41},"\u002F\u002F   5 = second\n",[35,343,344],{"class":37,"line":92},[35,345,346],{"class":41},"\u002F\u002F   6 = year (2006)\n",[35,348,349],{"class":37,"line":98},[35,350,351],{"class":41},"\u002F\u002F   7 = timezone (-0700)\n",[35,353,354],{"class":37,"line":103},[35,355,125],{"emptyLinePlaceholder":124},[35,357,358,360,363],{"class":37,"line":109},[35,359,132],{"class":131},[35,361,362],{"class":135}," formatting",[35,364,140],{"class":139},[35,366,367,370,372,374,377,379,382,385,388,390,393,395,398,400,403,405,408,410,413],{"class":37,"line":115},[35,368,369],{"class":139},"    t ",[35,371,149],{"class":131},[35,373,152],{"class":139},[35,375,376],{"class":135},"Date",[35,378,173],{"class":139},[35,380,381],{"class":176},"2024",[35,383,384],{"class":139},", ",[35,386,387],{"class":176},"3",[35,389,384],{"class":139},[35,391,392],{"class":176},"15",[35,394,384],{"class":139},[35,396,397],{"class":176},"14",[35,399,384],{"class":139},[35,401,402],{"class":176},"30",[35,404,384],{"class":139},[35,406,407],{"class":176},"45",[35,409,384],{"class":139},[35,411,412],{"class":176},"0",[35,414,415],{"class":139},", time.UTC)\n",[35,417,418],{"class":37,"line":121},[35,419,125],{"emptyLinePlaceholder":124},[35,421,422,425,428,430,433,436],{"class":37,"line":128},[35,423,424],{"class":139},"    t.",[35,426,427],{"class":135},"Format",[35,429,173],{"class":139},[35,431,432],{"class":269},"\"2006-01-02\"",[35,434,435],{"class":139},")           ",[35,437,438],{"class":41},"\u002F\u002F \"2024-03-15\"\n",[35,440,441,443,445,447,450,453],{"class":37,"line":143},[35,442,424],{"class":139},[35,444,427],{"class":135},[35,446,173],{"class":139},[35,448,449],{"class":269},"\"2006-01-02 15:04:05\"",[35,451,452],{"class":139},")  ",[35,454,455],{"class":41},"\u002F\u002F \"2024-03-15 14:30:45\"\n",[35,457,458,460,462,465],{"class":37,"line":164},[35,459,424],{"class":139},[35,461,427],{"class":135},[35,463,464],{"class":139},"(time.RFC3339)           ",[35,466,467],{"class":41},"\u002F\u002F \"2024-03-15T14:30:45Z\"\n",[35,469,470,472,474,476,479,481],{"class":37,"line":186},[35,471,424],{"class":139},[35,473,427],{"class":135},[35,475,173],{"class":139},[35,477,478],{"class":269},"\"Mon Jan _2 15:04:05 2006\"",[35,480,452],{"class":139},[35,482,483],{"class":41},"\u002F\u002F \"Fri Mar 15 14:30:45 2024\"\n",[35,485,486,488,490,492,495,497],{"class":37,"line":202},[35,487,424],{"class":139},[35,489,427],{"class":135},[35,491,173],{"class":139},[35,493,494],{"class":269},"\"01\u002F02\u002F2006 3:04 PM\"",[35,496,452],{"class":139},[35,498,499],{"class":41},"\u002F\u002F \"03\u002F15\u002F2024 2:30 PM\"\n",[35,501,502,504,506,508,511,513],{"class":37,"line":207},[35,503,424],{"class":139},[35,505,427],{"class":135},[35,507,173],{"class":139},[35,509,510],{"class":269},"\"2006-01-02T15:04:05.999999-07:00\"",[35,512,452],{"class":139},[35,514,515],{"class":41},"\u002F\u002F with microseconds\n",[35,517,518],{"class":37,"line":227},[35,519,125],{"emptyLinePlaceholder":124},[35,521,522],{"class":37,"line":242},[35,523,524],{"class":41},"    \u002F\u002F Predefined formats:\n",[35,526,527],{"class":37,"line":247},[35,528,529],{"class":41},"    \u002F\u002F time.RFC3339     = \"2006-01-02T15:04:05Z07:00\"\n",[35,531,532],{"class":37,"line":253},[35,533,534],{"class":41},"    \u002F\u002F time.RFC1123     = \"Mon, 02 Jan 2006 15:04:05 MST\"\n",[35,536,537],{"class":37,"line":276},[35,538,539],{"class":41},"    \u002F\u002F time.Kitchen     = \"3:04PM\"\n",[35,541,542],{"class":37,"line":282},[35,543,544],{"class":41},"    \u002F\u002F time.Stamp       = \"Jan _2 15:04:05\"\n",[35,546,548],{"class":37,"line":547},28,[35,549,285],{"class":139},[35,551,553],{"class":37,"line":552},29,[35,554,125],{"emptyLinePlaceholder":124},[35,556,558],{"class":37,"line":557},30,[35,559,560],{"class":41},"\u002F\u002F ─── Parsing ───\n",[35,562,564,566,569],{"class":37,"line":563},31,[35,565,132],{"class":131},[35,567,568],{"class":135}," parsing",[35,570,140],{"class":139},[35,572,574,577,579,581,583,585,588],{"class":37,"line":573},32,[35,575,576],{"class":139},"    t, err ",[35,578,149],{"class":131},[35,580,152],{"class":139},[35,582,263],{"class":135},[35,584,266],{"class":139},[35,586,587],{"class":269},"\"2024-03-15T14:30:45Z\"",[35,589,273],{"class":139},[35,591,593,595,598,600,602,604,606,608,611],{"class":37,"line":592},33,[35,594,576],{"class":139},[35,596,597],{"class":131},"=",[35,599,152],{"class":139},[35,601,263],{"class":135},[35,603,173],{"class":139},[35,605,432],{"class":269},[35,607,384],{"class":139},[35,609,610],{"class":269},"\"2024-03-15\"",[35,612,273],{"class":139},[35,614,616,618,620,622,625,627,629,631,633],{"class":37,"line":615},34,[35,617,576],{"class":139},[35,619,597],{"class":131},[35,621,152],{"class":139},[35,623,624],{"class":135},"ParseInLocation",[35,626,173],{"class":139},[35,628,432],{"class":269},[35,630,384],{"class":139},[35,632,610],{"class":269},[35,634,415],{"class":139},[35,636,638],{"class":37,"line":637},35,[35,639,125],{"emptyLinePlaceholder":124},[35,641,643],{"class":37,"line":642},36,[35,644,645],{"class":41},"    \u002F\u002F ⚠️ Layout errors are runtime (not compile-time) — a wrong layout\n",[35,647,649],{"class":37,"line":648},37,[35,650,651],{"class":41},"    \u002F\u002F silently produces a wrong result or an error. Always check err.\n",[35,653,655],{"class":37,"line":654},38,[35,656,285],{"class":139},[14,658,660,663,664,667],{"id":659},"vs-equal-the-comparison-trap",[18,661,662],{},"=="," vs ",[18,665,666],{},"Equal"," — The Comparison Trap",[23,669,670,912,916],{"language":25},[27,671,673],{"className":29,"code":672,"language":25,"meta":31,"style":31},"\u002F\u002F ❌ == compares wall clock AND monotonic clock AND location:\nfunc badCompare() {\n    t1, _ := time.Parse(time.RFC3339, \"2024-03-15T14:30:00Z\")        \u002F\u002F UTC\n    t2, _ := time.Parse(time.RFC3339, \"2024-03-15T09:30:00-05:00\")   \u002F\u002F EST\n    \u002F\u002F t1 and t2 are the SAME INSTANT (14:30 UTC = 09:30 EST)\n    fmt.Println(t1 == t2)      \u002F\u002F false — different locations\n}\n\n\u002F\u002F ✅ Equal compares only the INSTANT (the moment in time):\nfunc goodCompare() {\n    t1, _ := time.Parse(time.RFC3339, \"2024-03-15T14:30:00Z\")\n    t2, _ := time.Parse(time.RFC3339, \"2024-03-15T09:30:00-05:00\")\n    fmt.Println(t1.Equal(t2))  \u002F\u002F true — same instant, different timezones\n}\n\n\u002F\u002F Before\u002FAfter also compare the instant:\nfunc beforeAfter() {\n    t1 := time.Now()\n    t2 := t1.Add(time.Hour)\n    fmt.Println(t1.Before(t2))  \u002F\u002F true\n    fmt.Println(t2.After(t1))   \u002F\u002F true\n}\n",[18,674,675,680,689,710,732,737,754,758,762,767,776,792,808,825,829,833,838,847,860,875,891,908],{"__ignoreMap":31},[35,676,677],{"class":37,"line":38},[35,678,679],{"class":41},"\u002F\u002F ❌ == compares wall clock AND monotonic clock AND location:\n",[35,681,682,684,687],{"class":37,"line":45},[35,683,132],{"class":131},[35,685,686],{"class":135}," badCompare",[35,688,140],{"class":139},[35,690,691,694,696,698,700,702,704,707],{"class":37,"line":51},[35,692,693],{"class":139},"    t1, _ ",[35,695,149],{"class":131},[35,697,152],{"class":139},[35,699,263],{"class":135},[35,701,266],{"class":139},[35,703,270],{"class":269},[35,705,706],{"class":139},")        ",[35,708,709],{"class":41},"\u002F\u002F UTC\n",[35,711,712,715,717,719,721,723,726,729],{"class":37,"line":57},[35,713,714],{"class":139},"    t2, _ ",[35,716,149],{"class":131},[35,718,152],{"class":139},[35,720,263],{"class":135},[35,722,266],{"class":139},[35,724,725],{"class":269},"\"2024-03-15T09:30:00-05:00\"",[35,727,728],{"class":139},")   ",[35,730,731],{"class":41},"\u002F\u002F EST\n",[35,733,734],{"class":37,"line":63},[35,735,736],{"class":41},"    \u002F\u002F t1 and t2 are the SAME INSTANT (14:30 UTC = 09:30 EST)\n",[35,738,739,741,743,746,748,751],{"class":37,"line":69},[35,740,230],{"class":139},[35,742,233],{"class":135},[35,744,745],{"class":139},"(t1 ",[35,747,662],{"class":131},[35,749,750],{"class":139}," t2)      ",[35,752,753],{"class":41},"\u002F\u002F false — different locations\n",[35,755,756],{"class":37,"line":75},[35,757,285],{"class":139},[35,759,760],{"class":37,"line":81},[35,761,125],{"emptyLinePlaceholder":124},[35,763,764],{"class":37,"line":86},[35,765,766],{"class":41},"\u002F\u002F ✅ Equal compares only the INSTANT (the moment in time):\n",[35,768,769,771,774],{"class":37,"line":92},[35,770,132],{"class":131},[35,772,773],{"class":135}," goodCompare",[35,775,140],{"class":139},[35,777,778,780,782,784,786,788,790],{"class":37,"line":98},[35,779,693],{"class":139},[35,781,149],{"class":131},[35,783,152],{"class":139},[35,785,263],{"class":135},[35,787,266],{"class":139},[35,789,270],{"class":269},[35,791,273],{"class":139},[35,793,794,796,798,800,802,804,806],{"class":37,"line":103},[35,795,714],{"class":139},[35,797,149],{"class":131},[35,799,152],{"class":139},[35,801,263],{"class":135},[35,803,266],{"class":139},[35,805,725],{"class":269},[35,807,273],{"class":139},[35,809,810,812,814,817,819,822],{"class":37,"line":109},[35,811,230],{"class":139},[35,813,233],{"class":135},[35,815,816],{"class":139},"(t1.",[35,818,666],{"class":135},[35,820,821],{"class":139},"(t2))  ",[35,823,824],{"class":41},"\u002F\u002F true — same instant, different timezones\n",[35,826,827],{"class":37,"line":115},[35,828,285],{"class":139},[35,830,831],{"class":37,"line":121},[35,832,125],{"emptyLinePlaceholder":124},[35,834,835],{"class":37,"line":128},[35,836,837],{"class":41},"\u002F\u002F Before\u002FAfter also compare the instant:\n",[35,839,840,842,845],{"class":37,"line":143},[35,841,132],{"class":131},[35,843,844],{"class":135}," beforeAfter",[35,846,140],{"class":139},[35,848,849,851,853,855,857],{"class":37,"line":164},[35,850,146],{"class":139},[35,852,149],{"class":131},[35,854,152],{"class":139},[35,856,155],{"class":135},[35,858,859],{"class":139},"()\n",[35,861,862,864,866,869,872],{"class":37,"line":186},[35,863,189],{"class":139},[35,865,149],{"class":131},[35,867,868],{"class":139}," t1.",[35,870,871],{"class":135},"Add",[35,873,874],{"class":139},"(time.Hour)\n",[35,876,877,879,881,883,886,888],{"class":37,"line":202},[35,878,230],{"class":139},[35,880,233],{"class":135},[35,882,816],{"class":139},[35,884,885],{"class":135},"Before",[35,887,821],{"class":139},[35,889,890],{"class":41},"\u002F\u002F true\n",[35,892,893,895,897,900,903,906],{"class":37,"line":207},[35,894,230],{"class":139},[35,896,233],{"class":135},[35,898,899],{"class":139},"(t2.",[35,901,902],{"class":135},"After",[35,904,905],{"class":139},"(t1))   ",[35,907,890],{"class":41},[35,909,910],{"class":37,"line":227},[35,911,285],{"class":139},[14,913,915],{"id":914},"time-zones","Time Zones",[23,917,918,1147,1154],{"language":25},[27,919,921],{"className":29,"code":920,"language":25,"meta":31,"style":31},"func timeZones() {\n    \u002F\u002F Load an IANA timezone (requires the tz database):\n    loc, err := time.LoadLocation(\"America\u002FNew_York\")\n    if err != nil {\n        \u002F\u002F On systems without the tz database, embed it:\n        \u002F\u002F import _ \"time\u002Ftzdata\"  \u002F\u002F adds ~450KB to binary\n        panic(err)\n    }\n\n    now := time.Now().In(loc)  \u002F\u002F display current time in NYC\n    fmt.Println(now)           \u002F\u002F 2024-03-15 10:30:00 -0400 EDT\n\n    \u002F\u002F UTC and Local conversions (change DISPLAY, not instant):\n    utcTime := now.UTC()       \u002F\u002F 2024-03-15 14:30:00 +0000 UTC\n    localTime := now.Local()   \u002F\u002F in the system's local timezone\n\n    \u002F\u002F ⚠️ Use IANA names (\"America\u002FNew_York\"), NOT abbreviations (\"EST\"):\n    \u002F\u002F   \"EST\" has no DST rules — it's always UTC-5, even in summer.\n    \u002F\u002F   \"America\u002FNew_York\" handles DST automatically.\n    loc, _ = time.LoadLocation(\"EST\")  \u002F\u002F ❌ fixed offset, no DST\n    loc, _ = time.LoadLocation(\"America\u002FNew_York\")  \u002F\u002F ✅ handles DST\n}\n",[18,922,923,932,937,956,973,978,986,994,999,1003,1026,1038,1042,1047,1066,1084,1088,1093,1098,1103,1124,1143],{"__ignoreMap":31},[35,924,925,927,930],{"class":37,"line":38},[35,926,132],{"class":131},[35,928,929],{"class":135}," timeZones",[35,931,140],{"class":139},[35,933,934],{"class":37,"line":45},[35,935,936],{"class":41},"    \u002F\u002F Load an IANA timezone (requires the tz database):\n",[35,938,939,942,944,946,949,951,954],{"class":37,"line":51},[35,940,941],{"class":139},"    loc, err ",[35,943,149],{"class":131},[35,945,152],{"class":139},[35,947,948],{"class":135},"LoadLocation",[35,950,173],{"class":139},[35,952,953],{"class":269},"\"America\u002FNew_York\"",[35,955,273],{"class":139},[35,957,958,961,964,967,970],{"class":37,"line":57},[35,959,960],{"class":131},"    if",[35,962,963],{"class":139}," err ",[35,965,966],{"class":131},"!=",[35,968,969],{"class":176}," nil",[35,971,972],{"class":139}," {\n",[35,974,975],{"class":37,"line":63},[35,976,977],{"class":41},"        \u002F\u002F On systems without the tz database, embed it:\n",[35,979,980,983],{"class":37,"line":69},[35,981,982],{"class":41},"        \u002F\u002F import _ \"time\u002Ftzdata\"",[35,984,985],{"class":41},"  \u002F\u002F adds ~450KB to binary\n",[35,987,988,991],{"class":37,"line":75},[35,989,990],{"class":135},"        panic",[35,992,993],{"class":139},"(err)\n",[35,995,996],{"class":37,"line":81},[35,997,998],{"class":139},"    }\n",[35,1000,1001],{"class":37,"line":86},[35,1002,125],{"emptyLinePlaceholder":124},[35,1004,1005,1008,1010,1012,1014,1017,1020,1023],{"class":37,"line":92},[35,1006,1007],{"class":139},"    now ",[35,1009,149],{"class":131},[35,1011,152],{"class":139},[35,1013,155],{"class":135},[35,1015,1016],{"class":139},"().",[35,1018,1019],{"class":135},"In",[35,1021,1022],{"class":139},"(loc)  ",[35,1024,1025],{"class":41},"\u002F\u002F display current time in NYC\n",[35,1027,1028,1030,1032,1035],{"class":37,"line":98},[35,1029,230],{"class":139},[35,1031,233],{"class":135},[35,1033,1034],{"class":139},"(now)           ",[35,1036,1037],{"class":41},"\u002F\u002F 2024-03-15 10:30:00 -0400 EDT\n",[35,1039,1040],{"class":37,"line":103},[35,1041,125],{"emptyLinePlaceholder":124},[35,1043,1044],{"class":37,"line":109},[35,1045,1046],{"class":41},"    \u002F\u002F UTC and Local conversions (change DISPLAY, not instant):\n",[35,1048,1049,1052,1054,1057,1060,1063],{"class":37,"line":115},[35,1050,1051],{"class":139},"    utcTime ",[35,1053,149],{"class":131},[35,1055,1056],{"class":139}," now.",[35,1058,1059],{"class":135},"UTC",[35,1061,1062],{"class":139},"()       ",[35,1064,1065],{"class":41},"\u002F\u002F 2024-03-15 14:30:00 +0000 UTC\n",[35,1067,1068,1071,1073,1075,1078,1081],{"class":37,"line":121},[35,1069,1070],{"class":139},"    localTime ",[35,1072,149],{"class":131},[35,1074,1056],{"class":139},[35,1076,1077],{"class":135},"Local",[35,1079,1080],{"class":139},"()   ",[35,1082,1083],{"class":41},"\u002F\u002F in the system's local timezone\n",[35,1085,1086],{"class":37,"line":128},[35,1087,125],{"emptyLinePlaceholder":124},[35,1089,1090],{"class":37,"line":143},[35,1091,1092],{"class":41},"    \u002F\u002F ⚠️ Use IANA names (\"America\u002FNew_York\"), NOT abbreviations (\"EST\"):\n",[35,1094,1095],{"class":37,"line":164},[35,1096,1097],{"class":41},"    \u002F\u002F   \"EST\" has no DST rules — it's always UTC-5, even in summer.\n",[35,1099,1100],{"class":37,"line":186},[35,1101,1102],{"class":41},"    \u002F\u002F   \"America\u002FNew_York\" handles DST automatically.\n",[35,1104,1105,1108,1110,1112,1114,1116,1119,1121],{"class":37,"line":202},[35,1106,1107],{"class":139},"    loc, _ ",[35,1109,597],{"class":131},[35,1111,152],{"class":139},[35,1113,948],{"class":135},[35,1115,173],{"class":139},[35,1117,1118],{"class":269},"\"EST\"",[35,1120,452],{"class":139},[35,1122,1123],{"class":41},"\u002F\u002F ❌ fixed offset, no DST\n",[35,1125,1126,1128,1130,1132,1134,1136,1138,1140],{"class":37,"line":207},[35,1127,1107],{"class":139},[35,1129,597],{"class":131},[35,1131,152],{"class":139},[35,1133,948],{"class":135},[35,1135,173],{"class":139},[35,1137,953],{"class":269},[35,1139,452],{"class":139},[35,1141,1142],{"class":41},"\u002F\u002F ✅ handles DST\n",[35,1144,1145],{"class":37,"line":227},[35,1146,285],{"class":139},[14,1148,1150,1153],{"id":1149},"duration-arithmetic",[18,1151,1152],{},"Duration"," — Arithmetic",[23,1155,1156,1421,1425],{"language":25},[27,1157,1159],{"className":29,"code":1158,"language":25,"meta":31,"style":31},"func durationArithmetic() {\n    \u002F\u002F Duration is int64 nanoseconds. Constants:\n    \u002F\u002F time.Nanosecond, Microsecond, Millisecond, Second, Minute, Hour\n\n    d := 5 * time.Second\n    d.Seconds()      \u002F\u002F 5.0 (float64)\n    d.Milliseconds() \u002F\u002F 5000 (int64)\n    d.String()       \u002F\u002F \"5s\"\n\n    \u002F\u002F Add\u002Fsubtract durations:\n    t := time.Now()\n    t2 := t.Add(2 * time.Hour)      \u002F\u002F 2 hours later\n    t3 := t.Add(-30 * time.Minute)  \u002F\u002F 30 minutes earlier\n\n    \u002F\u002F Sub gives a Duration:\n    diff := t2.Sub(t)  \u002F\u002F 2h0m0s\n\n    \u002F\u002F ⚠️ Don't use Add for calendar months (different number of days):\n    \u002F\u002F t.Add(30 * 24 * time.Hour) is NOT \"one month\" — months vary.\n    \u002F\u002F Use AddDate for calendar units:\n    t4 := t.AddDate(0, 1, 0)  \u002F\u002F add 1 calendar month\n    t5 := t.AddDate(1, 0, 0)  \u002F\u002F add 1 calendar year\n    \u002F\u002F AddDate(0, 1, 0) on Jan 31 → Feb 28\u002F29 (normalized)\n}\n",[18,1160,1161,1170,1175,1180,1184,1199,1213,1226,1238,1242,1247,1259,1283,1309,1313,1318,1335,1339,1344,1349,1354,1384,1412,1417],{"__ignoreMap":31},[35,1162,1163,1165,1168],{"class":37,"line":38},[35,1164,132],{"class":131},[35,1166,1167],{"class":135}," durationArithmetic",[35,1169,140],{"class":139},[35,1171,1172],{"class":37,"line":45},[35,1173,1174],{"class":41},"    \u002F\u002F Duration is int64 nanoseconds. Constants:\n",[35,1176,1177],{"class":37,"line":51},[35,1178,1179],{"class":41},"    \u002F\u002F time.Nanosecond, Microsecond, Millisecond, Second, Minute, Hour\n",[35,1181,1182],{"class":37,"line":57},[35,1183,125],{"emptyLinePlaceholder":124},[35,1185,1186,1189,1191,1194,1196],{"class":37,"line":63},[35,1187,1188],{"class":139},"    d ",[35,1190,149],{"class":131},[35,1192,1193],{"class":176}," 5",[35,1195,180],{"class":131},[35,1197,1198],{"class":139}," time.Second\n",[35,1200,1201,1204,1207,1210],{"class":37,"line":69},[35,1202,1203],{"class":139},"    d.",[35,1205,1206],{"class":135},"Seconds",[35,1208,1209],{"class":139},"()      ",[35,1211,1212],{"class":41},"\u002F\u002F 5.0 (float64)\n",[35,1214,1215,1217,1220,1223],{"class":37,"line":75},[35,1216,1203],{"class":139},[35,1218,1219],{"class":135},"Milliseconds",[35,1221,1222],{"class":139},"() ",[35,1224,1225],{"class":41},"\u002F\u002F 5000 (int64)\n",[35,1227,1228,1230,1233,1235],{"class":37,"line":81},[35,1229,1203],{"class":139},[35,1231,1232],{"class":135},"String",[35,1234,1062],{"class":139},[35,1236,1237],{"class":41},"\u002F\u002F \"5s\"\n",[35,1239,1240],{"class":37,"line":86},[35,1241,125],{"emptyLinePlaceholder":124},[35,1243,1244],{"class":37,"line":92},[35,1245,1246],{"class":41},"    \u002F\u002F Add\u002Fsubtract durations:\n",[35,1248,1249,1251,1253,1255,1257],{"class":37,"line":98},[35,1250,369],{"class":139},[35,1252,149],{"class":131},[35,1254,152],{"class":139},[35,1256,155],{"class":135},[35,1258,859],{"class":139},[35,1260,1261,1263,1265,1268,1270,1272,1275,1277,1280],{"class":37,"line":103},[35,1262,189],{"class":139},[35,1264,149],{"class":131},[35,1266,1267],{"class":139}," t.",[35,1269,871],{"class":135},[35,1271,173],{"class":139},[35,1273,1274],{"class":176},"2",[35,1276,180],{"class":131},[35,1278,1279],{"class":139}," time.Hour)      ",[35,1281,1282],{"class":41},"\u002F\u002F 2 hours later\n",[35,1284,1285,1288,1290,1292,1294,1296,1299,1301,1303,1306],{"class":37,"line":109},[35,1286,1287],{"class":139},"    t3 ",[35,1289,149],{"class":131},[35,1291,1267],{"class":139},[35,1293,871],{"class":135},[35,1295,173],{"class":139},[35,1297,1298],{"class":131},"-",[35,1300,402],{"class":176},[35,1302,180],{"class":131},[35,1304,1305],{"class":139}," time.Minute)  ",[35,1307,1308],{"class":41},"\u002F\u002F 30 minutes earlier\n",[35,1310,1311],{"class":37,"line":115},[35,1312,125],{"emptyLinePlaceholder":124},[35,1314,1315],{"class":37,"line":121},[35,1316,1317],{"class":41},"    \u002F\u002F Sub gives a Duration:\n",[35,1319,1320,1323,1325,1327,1329,1332],{"class":37,"line":128},[35,1321,1322],{"class":139},"    diff ",[35,1324,149],{"class":131},[35,1326,215],{"class":139},[35,1328,218],{"class":135},[35,1330,1331],{"class":139},"(t)  ",[35,1333,1334],{"class":41},"\u002F\u002F 2h0m0s\n",[35,1336,1337],{"class":37,"line":143},[35,1338,125],{"emptyLinePlaceholder":124},[35,1340,1341],{"class":37,"line":164},[35,1342,1343],{"class":41},"    \u002F\u002F ⚠️ Don't use Add for calendar months (different number of days):\n",[35,1345,1346],{"class":37,"line":186},[35,1347,1348],{"class":41},"    \u002F\u002F t.Add(30 * 24 * time.Hour) is NOT \"one month\" — months vary.\n",[35,1350,1351],{"class":37,"line":202},[35,1352,1353],{"class":41},"    \u002F\u002F Use AddDate for calendar units:\n",[35,1355,1356,1359,1361,1363,1366,1368,1370,1372,1375,1377,1379,1381],{"class":37,"line":207},[35,1357,1358],{"class":139},"    t4 ",[35,1360,149],{"class":131},[35,1362,1267],{"class":139},[35,1364,1365],{"class":135},"AddDate",[35,1367,173],{"class":139},[35,1369,412],{"class":176},[35,1371,384],{"class":139},[35,1373,1374],{"class":176},"1",[35,1376,384],{"class":139},[35,1378,412],{"class":176},[35,1380,452],{"class":139},[35,1382,1383],{"class":41},"\u002F\u002F add 1 calendar month\n",[35,1385,1386,1389,1391,1393,1395,1397,1399,1401,1403,1405,1407,1409],{"class":37,"line":227},[35,1387,1388],{"class":139},"    t5 ",[35,1390,149],{"class":131},[35,1392,1267],{"class":139},[35,1394,1365],{"class":135},[35,1396,173],{"class":139},[35,1398,1374],{"class":176},[35,1400,384],{"class":139},[35,1402,412],{"class":176},[35,1404,384],{"class":139},[35,1406,412],{"class":176},[35,1408,452],{"class":139},[35,1410,1411],{"class":41},"\u002F\u002F add 1 calendar year\n",[35,1413,1414],{"class":37,"line":242},[35,1415,1416],{"class":41},"    \u002F\u002F AddDate(0, 1, 0) on Jan 31 → Feb 28\u002F29 (normalized)\n",[35,1418,1419],{"class":37,"line":247},[35,1420,285],{"class":139},[14,1422,1424],{"id":1423},"tickers-and-timers","Tickers and Timers",[23,1426,1427,1768,1772],{"language":25},[27,1428,1430],{"className":29,"code":1429,"language":25,"meta":31,"style":31},"func tickersAndTimers() {\n    \u002F\u002F ─── Ticker — fires repeatedly at intervals ───\n    ticker := time.NewTicker(1 * time.Second)\n    defer ticker.Stop()  \u002F\u002F ⚠️ always Stop to release the goroutine\n\n    go func() {\n        for t := range ticker.C {  \u002F\u002F channel sends a Time each tick\n            fmt.Println(\"tick:\", t)\n        }\n    }()\n\n    \u002F\u002F ─── Timer — fires once after a duration ───\n    timer := time.NewTimer(5 * time.Second)\n    defer timer.Stop()\n\n    select {\n    case \u003C-timer.C:\n        fmt.Println(\"timer fired\")\n    case \u003C-ctx.Done():\n        fmt.Println(\"cancelled before timer fired\")\n    }\n\n    \u002F\u002F ─── time.After — one-shot timer (leaks if not fired) ───\n    \u002F\u002F ⚠️ time.After leaks the timer goroutine if the select takes another case.\n    \u002F\u002F Use time.NewTimer + Stop in tight loops (see chapter 18).\n    select {\n    case v := \u003C-ch:\n        _ = v\n    case \u003C-time.After(5 * time.Second):\n        fmt.Println(\"timeout\")\n    }\n\n    \u002F\u002F ─── time.Sleep — blocks the current goroutine ───\n    time.Sleep(100 * time.Millisecond)  \u002F\u002F no cancel, no select — rarely right\n}\n",[18,1431,1432,1441,1446,1467,1484,1488,1498,1517,1532,1537,1542,1546,1551,1572,1583,1587,1594,1605,1619,1634,1647,1651,1655,1660,1665,1670,1676,1690,1700,1720,1733,1737,1741,1746,1764],{"__ignoreMap":31},[35,1433,1434,1436,1439],{"class":37,"line":38},[35,1435,132],{"class":131},[35,1437,1438],{"class":135}," tickersAndTimers",[35,1440,140],{"class":139},[35,1442,1443],{"class":37,"line":45},[35,1444,1445],{"class":41},"    \u002F\u002F ─── Ticker — fires repeatedly at intervals ───\n",[35,1447,1448,1451,1453,1455,1458,1460,1462,1464],{"class":37,"line":51},[35,1449,1450],{"class":139},"    ticker ",[35,1452,149],{"class":131},[35,1454,152],{"class":139},[35,1456,1457],{"class":135},"NewTicker",[35,1459,173],{"class":139},[35,1461,1374],{"class":176},[35,1463,180],{"class":131},[35,1465,1466],{"class":139}," time.Second)\n",[35,1468,1469,1472,1475,1478,1481],{"class":37,"line":57},[35,1470,1471],{"class":131},"    defer",[35,1473,1474],{"class":139}," ticker.",[35,1476,1477],{"class":135},"Stop",[35,1479,1480],{"class":139},"()  ",[35,1482,1483],{"class":41},"\u002F\u002F ⚠️ always Stop to release the goroutine\n",[35,1485,1486],{"class":37,"line":63},[35,1487,125],{"emptyLinePlaceholder":124},[35,1489,1490,1493,1496],{"class":37,"line":69},[35,1491,1492],{"class":131},"    go",[35,1494,1495],{"class":131}," func",[35,1497,140],{"class":139},[35,1499,1500,1503,1506,1508,1511,1514],{"class":37,"line":75},[35,1501,1502],{"class":131},"        for",[35,1504,1505],{"class":139}," t ",[35,1507,149],{"class":131},[35,1509,1510],{"class":131}," range",[35,1512,1513],{"class":139}," ticker.C {  ",[35,1515,1516],{"class":41},"\u002F\u002F channel sends a Time each tick\n",[35,1518,1519,1522,1524,1526,1529],{"class":37,"line":81},[35,1520,1521],{"class":139},"            fmt.",[35,1523,233],{"class":135},[35,1525,173],{"class":139},[35,1527,1528],{"class":269},"\"tick:\"",[35,1530,1531],{"class":139},", t)\n",[35,1533,1534],{"class":37,"line":86},[35,1535,1536],{"class":139},"        }\n",[35,1538,1539],{"class":37,"line":92},[35,1540,1541],{"class":139},"    }()\n",[35,1543,1544],{"class":37,"line":98},[35,1545,125],{"emptyLinePlaceholder":124},[35,1547,1548],{"class":37,"line":103},[35,1549,1550],{"class":41},"    \u002F\u002F ─── Timer — fires once after a duration ───\n",[35,1552,1553,1556,1558,1560,1563,1565,1568,1570],{"class":37,"line":109},[35,1554,1555],{"class":139},"    timer ",[35,1557,149],{"class":131},[35,1559,152],{"class":139},[35,1561,1562],{"class":135},"NewTimer",[35,1564,173],{"class":139},[35,1566,1567],{"class":176},"5",[35,1569,180],{"class":131},[35,1571,1466],{"class":139},[35,1573,1574,1576,1579,1581],{"class":37,"line":115},[35,1575,1471],{"class":131},[35,1577,1578],{"class":139}," timer.",[35,1580,1477],{"class":135},[35,1582,859],{"class":139},[35,1584,1585],{"class":37,"line":121},[35,1586,125],{"emptyLinePlaceholder":124},[35,1588,1589,1592],{"class":37,"line":128},[35,1590,1591],{"class":131},"    select",[35,1593,972],{"class":139},[35,1595,1596,1599,1602],{"class":37,"line":143},[35,1597,1598],{"class":131},"    case",[35,1600,1601],{"class":131}," \u003C-",[35,1603,1604],{"class":139},"timer.C:\n",[35,1606,1607,1610,1612,1614,1617],{"class":37,"line":164},[35,1608,1609],{"class":139},"        fmt.",[35,1611,233],{"class":135},[35,1613,173],{"class":139},[35,1615,1616],{"class":269},"\"timer fired\"",[35,1618,273],{"class":139},[35,1620,1621,1623,1625,1628,1631],{"class":37,"line":186},[35,1622,1598],{"class":131},[35,1624,1601],{"class":131},[35,1626,1627],{"class":139},"ctx.",[35,1629,1630],{"class":135},"Done",[35,1632,1633],{"class":139},"():\n",[35,1635,1636,1638,1640,1642,1645],{"class":37,"line":202},[35,1637,1609],{"class":139},[35,1639,233],{"class":135},[35,1641,173],{"class":139},[35,1643,1644],{"class":269},"\"cancelled before timer fired\"",[35,1646,273],{"class":139},[35,1648,1649],{"class":37,"line":207},[35,1650,998],{"class":139},[35,1652,1653],{"class":37,"line":227},[35,1654,125],{"emptyLinePlaceholder":124},[35,1656,1657],{"class":37,"line":242},[35,1658,1659],{"class":41},"    \u002F\u002F ─── time.After — one-shot timer (leaks if not fired) ───\n",[35,1661,1662],{"class":37,"line":247},[35,1663,1664],{"class":41},"    \u002F\u002F ⚠️ time.After leaks the timer goroutine if the select takes another case.\n",[35,1666,1667],{"class":37,"line":253},[35,1668,1669],{"class":41},"    \u002F\u002F Use time.NewTimer + Stop in tight loops (see chapter 18).\n",[35,1671,1672,1674],{"class":37,"line":276},[35,1673,1591],{"class":131},[35,1675,972],{"class":139},[35,1677,1678,1680,1683,1685,1687],{"class":37,"line":282},[35,1679,1598],{"class":131},[35,1681,1682],{"class":139}," v ",[35,1684,149],{"class":131},[35,1686,1601],{"class":131},[35,1688,1689],{"class":139},"ch:\n",[35,1691,1692,1695,1697],{"class":37,"line":547},[35,1693,1694],{"class":139},"        _ ",[35,1696,597],{"class":131},[35,1698,1699],{"class":139}," v\n",[35,1701,1702,1704,1706,1709,1711,1713,1715,1717],{"class":37,"line":552},[35,1703,1598],{"class":131},[35,1705,1601],{"class":131},[35,1707,1708],{"class":139},"time.",[35,1710,902],{"class":135},[35,1712,173],{"class":139},[35,1714,1567],{"class":176},[35,1716,180],{"class":131},[35,1718,1719],{"class":139}," time.Second):\n",[35,1721,1722,1724,1726,1728,1731],{"class":37,"line":557},[35,1723,1609],{"class":139},[35,1725,233],{"class":135},[35,1727,173],{"class":139},[35,1729,1730],{"class":269},"\"timeout\"",[35,1732,273],{"class":139},[35,1734,1735],{"class":37,"line":563},[35,1736,998],{"class":139},[35,1738,1739],{"class":37,"line":573},[35,1740,125],{"emptyLinePlaceholder":124},[35,1742,1743],{"class":37,"line":592},[35,1744,1745],{"class":41},"    \u002F\u002F ─── time.Sleep — blocks the current goroutine ───\n",[35,1747,1748,1750,1752,1754,1756,1758,1761],{"class":37,"line":615},[35,1749,167],{"class":139},[35,1751,170],{"class":135},[35,1753,173],{"class":139},[35,1755,177],{"class":176},[35,1757,180],{"class":131},[35,1759,1760],{"class":139}," time.Millisecond)  ",[35,1762,1763],{"class":41},"\u002F\u002F no cancel, no select — rarely right\n",[35,1765,1766],{"class":37,"line":637},[35,1767,285],{"class":139},[14,1769,1771],{"id":1770},"production-pattern-scheduled-cleanup","Production Pattern — Scheduled Cleanup",[23,1773,1774,2060,2064,2158,2162,2289,2293],{"language":25},[27,1775,1777],{"className":29,"code":1776,"language":25,"meta":31,"style":31},"func startCleanup(ctx context.Context, interval time.Duration) {\n    ticker := time.NewTicker(interval)\n    defer ticker.Stop()\n\n    for {\n        select {\n        case \u003C-ticker.C:\n            if err := cleanupExpiredSessions(ctx); err != nil {\n                log.Printf(\"cleanup error: %v\", err)\n                \u002F\u002F continue running — don't stop on error\n            }\n        case \u003C-ctx.Done():\n            log.Println(\"cleanup goroutine shutting down\")\n            return  \u002F\u002F graceful exit on cancellation\n        }\n    }\n}\n\nfunc main() {\n    ctx, cancel := signal.NotifyContext(context.Background(),\n        syscall.SIGINT, syscall.SIGTERM)\n    defer cancel()\n\n    go startCleanup(ctx, 5*time.Minute)\n\n    \u002F\u002F ... main server loop ...\n    \u003C-ctx.Done()\n}\n",[18,1778,1779,1816,1829,1839,1843,1850,1857,1867,1888,1910,1915,1920,1932,1946,1954,1958,1962,1966,1970,1979,2001,2006,2015,2019,2036,2040,2045,2056],{"__ignoreMap":31},[35,1780,1781,1783,1786,1788,1792,1795,1798,1801,1803,1806,1809,1811,1813],{"class":37,"line":38},[35,1782,132],{"class":131},[35,1784,1785],{"class":135}," startCleanup",[35,1787,173],{"class":139},[35,1789,1791],{"class":1790},"sCrzJ","ctx",[35,1793,1794],{"class":135}," context",[35,1796,1797],{"class":139},".",[35,1799,1800],{"class":135},"Context",[35,1802,384],{"class":139},[35,1804,1805],{"class":1790},"interval",[35,1807,1808],{"class":135}," time",[35,1810,1797],{"class":139},[35,1812,1152],{"class":135},[35,1814,1815],{"class":139},") {\n",[35,1817,1818,1820,1822,1824,1826],{"class":37,"line":45},[35,1819,1450],{"class":139},[35,1821,149],{"class":131},[35,1823,152],{"class":139},[35,1825,1457],{"class":135},[35,1827,1828],{"class":139},"(interval)\n",[35,1830,1831,1833,1835,1837],{"class":37,"line":51},[35,1832,1471],{"class":131},[35,1834,1474],{"class":139},[35,1836,1477],{"class":135},[35,1838,859],{"class":139},[35,1840,1841],{"class":37,"line":57},[35,1842,125],{"emptyLinePlaceholder":124},[35,1844,1845,1848],{"class":37,"line":63},[35,1846,1847],{"class":131},"    for",[35,1849,972],{"class":139},[35,1851,1852,1855],{"class":37,"line":69},[35,1853,1854],{"class":131},"        select",[35,1856,972],{"class":139},[35,1858,1859,1862,1864],{"class":37,"line":75},[35,1860,1861],{"class":131},"        case",[35,1863,1601],{"class":131},[35,1865,1866],{"class":139},"ticker.C:\n",[35,1868,1869,1872,1874,1876,1879,1882,1884,1886],{"class":37,"line":81},[35,1870,1871],{"class":131},"            if",[35,1873,963],{"class":139},[35,1875,149],{"class":131},[35,1877,1878],{"class":135}," cleanupExpiredSessions",[35,1880,1881],{"class":139},"(ctx); err ",[35,1883,966],{"class":131},[35,1885,969],{"class":176},[35,1887,972],{"class":139},[35,1889,1890,1893,1896,1898,1901,1904,1907],{"class":37,"line":86},[35,1891,1892],{"class":139},"                log.",[35,1894,1895],{"class":135},"Printf",[35,1897,173],{"class":139},[35,1899,1900],{"class":269},"\"cleanup error: ",[35,1902,1903],{"class":176},"%v",[35,1905,1906],{"class":269},"\"",[35,1908,1909],{"class":139},", err)\n",[35,1911,1912],{"class":37,"line":92},[35,1913,1914],{"class":41},"                \u002F\u002F continue running — don't stop on error\n",[35,1916,1917],{"class":37,"line":98},[35,1918,1919],{"class":139},"            }\n",[35,1921,1922,1924,1926,1928,1930],{"class":37,"line":103},[35,1923,1861],{"class":131},[35,1925,1601],{"class":131},[35,1927,1627],{"class":139},[35,1929,1630],{"class":135},[35,1931,1633],{"class":139},[35,1933,1934,1937,1939,1941,1944],{"class":37,"line":109},[35,1935,1936],{"class":139},"            log.",[35,1938,233],{"class":135},[35,1940,173],{"class":139},[35,1942,1943],{"class":269},"\"cleanup goroutine shutting down\"",[35,1945,273],{"class":139},[35,1947,1948,1951],{"class":37,"line":115},[35,1949,1950],{"class":131},"            return",[35,1952,1953],{"class":41},"  \u002F\u002F graceful exit on cancellation\n",[35,1955,1956],{"class":37,"line":121},[35,1957,1536],{"class":139},[35,1959,1960],{"class":37,"line":128},[35,1961,998],{"class":139},[35,1963,1964],{"class":37,"line":143},[35,1965,285],{"class":139},[35,1967,1968],{"class":37,"line":164},[35,1969,125],{"emptyLinePlaceholder":124},[35,1971,1972,1974,1977],{"class":37,"line":186},[35,1973,132],{"class":131},[35,1975,1976],{"class":135}," main",[35,1978,140],{"class":139},[35,1980,1981,1984,1986,1989,1992,1995,1998],{"class":37,"line":202},[35,1982,1983],{"class":139},"    ctx, cancel ",[35,1985,149],{"class":131},[35,1987,1988],{"class":139}," signal.",[35,1990,1991],{"class":135},"NotifyContext",[35,1993,1994],{"class":139},"(context.",[35,1996,1997],{"class":135},"Background",[35,1999,2000],{"class":139},"(),\n",[35,2002,2003],{"class":37,"line":207},[35,2004,2005],{"class":139},"        syscall.SIGINT, syscall.SIGTERM)\n",[35,2007,2008,2010,2013],{"class":37,"line":227},[35,2009,1471],{"class":131},[35,2011,2012],{"class":135}," cancel",[35,2014,859],{"class":139},[35,2016,2017],{"class":37,"line":242},[35,2018,125],{"emptyLinePlaceholder":124},[35,2020,2021,2023,2025,2028,2030,2033],{"class":37,"line":247},[35,2022,1492],{"class":131},[35,2024,1785],{"class":135},[35,2026,2027],{"class":139},"(ctx, ",[35,2029,1567],{"class":176},[35,2031,2032],{"class":131},"*",[35,2034,2035],{"class":139},"time.Minute)\n",[35,2037,2038],{"class":37,"line":253},[35,2039,125],{"emptyLinePlaceholder":124},[35,2041,2042],{"class":37,"line":276},[35,2043,2044],{"class":41},"    \u002F\u002F ... main server loop ...\n",[35,2046,2047,2050,2052,2054],{"class":37,"line":282},[35,2048,2049],{"class":131},"    \u003C-",[35,2051,1627],{"class":139},[35,2053,1630],{"class":135},[35,2055,859],{"class":139},[35,2057,2058],{"class":37,"line":547},[35,2059,285],{"class":139},[14,2061,2063],{"id":2062},"tips-tricks","💡 Tips & Tricks",[2065,2066,2067,2088,2103,2112,2120,2144],"ul",{},[2068,2069,2070,2074,2075,2078,2079,2081,2082,2084,2085,2087],"li",{},[2071,2072,2073],"strong",{},"Idiom",": use ",[18,2076,2077],{},"t.Equal(t2)"," to compare times, not ",[18,2080,662],{}," — ",[18,2083,666],{}," compares the instant, ignoring location and monotonic differences. ",[18,2086,662],{}," compares all three and gives false for the same instant in different timezones.",[2068,2089,2090,2074,2092,2094,2095,2098,2099,2102],{},[2071,2091,2073],{},[18,2093,1365],{}," for calendar arithmetic (months, years) — ",[18,2096,2097],{},"t.AddDate(0, 1, 0)"," adds a calendar month (handles Feb 28\u002F29). ",[18,2100,2101],{},"t.Add(30 * 24 * time.Hour)"," is NOT a month — months have different day counts.",[2068,2104,2105,2107,2108,2111],{},[2071,2106,2073],{},": use IANA timezone names (\"America\u002FNew_York\"), not abbreviations (\"EST\") — abbreviations have no DST rules. ",[18,2109,2110],{},"time.LoadLocation(\"America\u002FNew_York\")"," handles DST automatically.",[2068,2113,2114,2074,2116,2119],{},[2071,2115,2073],{},[18,2117,2118],{},"time.Now().Sub(t)"," (monotonic clock) for measuring elapsed time — it's unaffected by NTP adjustments or DST changes. Parsed times have no monotonic clock.",[2068,2121,2122,2124,2125,2128,2129,2132,2133,2136,2137,2139,2140,2143],{},[2071,2123,2073],{},": always ",[18,2126,2127],{},"defer ticker.Stop()"," \u002F ",[18,2130,2131],{},"defer timer.Stop()"," — without Stop, the timer goroutine lingers (resource leak). In tight loops, use ",[18,2134,2135],{},"time.NewTimer"," + ",[18,2138,1477],{}," instead of ",[18,2141,2142],{},"time.After"," (which leaks).",[2068,2145,2146,2149,2150,2153,2154,2157],{},[2071,2147,2148],{},"Portability",": import ",[18,2151,2152],{},"_ \"time\u002Ftzdata\""," to embed the timezone database — needed on systems without ",[18,2155,2156],{},"\u002Fusr\u002Fshare\u002Fzoneinfo"," (some minimal Docker images, Windows). Adds ~450KB to the binary.",[14,2159,2161],{"id":2160},"️-edge-cases-gotchas","⚠️ Edge Cases & Gotchas",[2065,2163,2164,2182,2194,2205,2227,2242,2254,2268,2283],{},[2068,2165,2166,2172,2173,2175,2176,2178,2179,2181],{},[2071,2167,2168,663,2170],{},[18,2169,662],{},[18,2171,666],{},": ",[18,2174,662],{}," compares wall + monotonic + location; ",[18,2177,666],{}," compares only the instant. Use ",[18,2180,666],{}," for \"same moment.\"",[2068,2183,2184,2172,2187,2190,2191,2193],{},[2071,2185,2186],{},"Parsed times have no monotonic clock",[18,2188,2189],{},"time.Parse"," returns a time with only the wall clock. ",[18,2192,218],{}," uses the wall clock (less reliable for elapsed time).",[2068,2195,2196,2172,2201,2204],{},[2071,2197,2198,2200],{},[18,2199,1365],{}," normalizes",[18,2202,2203],{},"time.Date(2024, 1, 31, 0, 0, 0, 0, UTC).AddDate(0, 1, 0)"," → Feb 29 (2024 is a leap year). Adding a month to the 31st normalizes to the last day of the target month.",[2068,2206,2207,2172,2213,2216,2217,2136,2219,2222,2223,2226],{},[2071,2208,2209,2212],{},[18,2210,2211],{},"time.Sleep"," can't be cancelled",[18,2214,2215],{},"time.Sleep(d)"," blocks the goroutine for d, ignoring context. Use ",[18,2218,2135],{},[18,2220,2221],{},"select"," with ",[18,2224,2225],{},"ctx.Done()"," for cancellable waits.",[2068,2228,2229,2234,2235,2237,2238,2136,2240,1797],{},[2071,2230,2231,2233],{},[18,2232,2142],{}," leaks",": the timer goroutine lives until the duration elapses, even if the ",[18,2236,2221],{}," took another case. In hot loops, use ",[18,2239,2135],{},[18,2241,1477],{},[2068,2243,2244,2250,2251,2253],{},[2071,2245,2246,2249],{},[18,2247,2248],{},"time.LoadLocation"," can fail",": on systems without the tz database, it returns an error. Import ",[18,2252,2152],{}," to embed the database.",[2068,2255,2256,2259,2260,2263,2264,2267],{},[2071,2257,2258],{},"DST changes",": adding ",[18,2261,2262],{},"24 * time.Hour"," across a DST boundary gives 23 or 25 hours of wall-clock time (but 24 hours of monotonic time). Use ",[18,2265,2266],{},"AddDate(0, 0, 1)"," for \"next day at the same wall-clock time.\"",[2068,2269,2270,2172,2276,2278,2279,2282],{},[2071,2271,2272,2275],{},[18,2273,2274],{},"time.Now()"," is monotonic",[18,2277,2274],{}," includes the monotonic clock. Subtracting two ",[18,2280,2281],{},"Now()"," values gives accurate elapsed time regardless of NTP.",[2068,2284,2285,2288],{},[2071,2286,2287],{},"Timezone abbreviations are ambiguous",": \"CST\" can be Central Standard Time (US), China Standard Time, or Cuba Standard Time. Always use IANA names.",[14,2290,2292],{"id":2291},"quick-quiz","🧠 Quick Quiz",[23,2294,2295,2365],{"language":25},[27,2296,2298],{"className":29,"code":2297,"language":25,"meta":31,"style":31},"t1, _ := time.Parse(time.RFC3339, \"2024-03-15T14:30:00Z\")\nt2, _ := time.Parse(time.RFC3339, \"2024-03-15T14:30:00Z\")\n\nfmt.Println(t1 == t2)\nfmt.Println(t1.Equal(t2))\n",[18,2299,2300,2317,2334,2338,2352],{"__ignoreMap":31},[35,2301,2302,2305,2307,2309,2311,2313,2315],{"class":37,"line":38},[35,2303,2304],{"class":139},"t1, _ ",[35,2306,149],{"class":131},[35,2308,152],{"class":139},[35,2310,263],{"class":135},[35,2312,266],{"class":139},[35,2314,270],{"class":269},[35,2316,273],{"class":139},[35,2318,2319,2322,2324,2326,2328,2330,2332],{"class":37,"line":45},[35,2320,2321],{"class":139},"t2, _ ",[35,2323,149],{"class":131},[35,2325,152],{"class":139},[35,2327,263],{"class":135},[35,2329,266],{"class":139},[35,2331,270],{"class":269},[35,2333,273],{"class":139},[35,2335,2336],{"class":37,"line":51},[35,2337,125],{"emptyLinePlaceholder":124},[35,2339,2340,2343,2345,2347,2349],{"class":37,"line":57},[35,2341,2342],{"class":139},"fmt.",[35,2344,233],{"class":135},[35,2346,745],{"class":139},[35,2348,662],{"class":131},[35,2350,2351],{"class":139}," t2)\n",[35,2353,2354,2356,2358,2360,2362],{"class":37,"line":63},[35,2355,2342],{"class":139},[35,2357,233],{"class":135},[35,2359,816],{"class":139},[35,2361,666],{"class":135},[35,2363,2364],{"class":139},"(t2))\n",[2366,2367,2368],"p",{},"What's printed?",[2370,2371,2372,2376,2384,2404,2416,2484,2490],"details",{},[2373,2374,2375],"summary",{},"Answer",[27,2377,2382],{"className":2378,"code":2380,"language":2381},[2379],"language-text","true\ntrue\n","text",[18,2383,2380],{"__ignoreMap":31},[2366,2385,2386,2387,2389,2390,2392,2393,2396,2397,2389,2400,2403],{},"Both ",[18,2388,662],{}," and ",[18,2391,666],{}," return ",[18,2394,2395],{},"true"," here — ",[18,2398,2399],{},"t1",[18,2401,2402],{},"t2"," are parsed from the same string, so they have the same wall clock, same location (UTC), and both lack a monotonic clock (parsed times don't have one).",[2366,2405,2406,2407,2389,2409,2411,2412,2415],{},"The difference between ",[18,2408,662],{},[18,2410,666],{}," appears when the times are in ",[2071,2413,2414],{},"different locations",":",[27,2417,2419],{"className":29,"code":2418,"language":25,"meta":31,"style":31},"t1, _ := time.Parse(time.RFC3339, \"2024-03-15T14:30:00Z\")\nt2, _ := time.Parse(time.RFC3339, \"2024-03-15T09:30:00-05:00\")\nfmt.Println(t1 == t2)      \u002F\u002F false (different locations)\nfmt.Println(t1.Equal(t2)) \u002F\u002F true  (same instant)\n",[18,2420,2421,2437,2453,2468],{"__ignoreMap":31},[35,2422,2423,2425,2427,2429,2431,2433,2435],{"class":37,"line":38},[35,2424,2304],{"class":139},[35,2426,149],{"class":131},[35,2428,152],{"class":139},[35,2430,263],{"class":135},[35,2432,266],{"class":139},[35,2434,270],{"class":269},[35,2436,273],{"class":139},[35,2438,2439,2441,2443,2445,2447,2449,2451],{"class":37,"line":45},[35,2440,2321],{"class":139},[35,2442,149],{"class":131},[35,2444,152],{"class":139},[35,2446,263],{"class":135},[35,2448,266],{"class":139},[35,2450,725],{"class":269},[35,2452,273],{"class":139},[35,2454,2455,2457,2459,2461,2463,2465],{"class":37,"line":51},[35,2456,2342],{"class":139},[35,2458,233],{"class":135},[35,2460,745],{"class":139},[35,2462,662],{"class":131},[35,2464,750],{"class":139},[35,2466,2467],{"class":41},"\u002F\u002F false (different locations)\n",[35,2469,2470,2472,2474,2476,2478,2481],{"class":37,"line":57},[35,2471,2342],{"class":139},[35,2473,233],{"class":135},[35,2475,816],{"class":139},[35,2477,666],{"class":135},[35,2479,2480],{"class":139},"(t2)) ",[35,2482,2483],{"class":41},"\u002F\u002F true  (same instant)\n",[2366,2485,2486,2487,2489],{},"Or when comparing ",[18,2488,2274],{}," values (which have monotonic clocks):",[27,2491,2493],{"className":29,"code":2492,"language":25,"meta":31,"style":31},"t1 := time.Now()\nt2 := t1.In(time.UTC)  \u002F\u002F same instant, different location\nfmt.Println(t1 == t2)      \u002F\u002F false (monotonic clock is stripped by In())\nfmt.Println(t1.Equal(t2)) \u002F\u002F true\n",[18,2494,2495,2508,2525,2540],{"__ignoreMap":31},[35,2496,2497,2500,2502,2504,2506],{"class":37,"line":38},[35,2498,2499],{"class":139},"t1 ",[35,2501,149],{"class":131},[35,2503,152],{"class":139},[35,2505,155],{"class":135},[35,2507,859],{"class":139},[35,2509,2510,2513,2515,2517,2519,2522],{"class":37,"line":45},[35,2511,2512],{"class":139},"t2 ",[35,2514,149],{"class":131},[35,2516,868],{"class":139},[35,2518,1019],{"class":135},[35,2520,2521],{"class":139},"(time.UTC)  ",[35,2523,2524],{"class":41},"\u002F\u002F same instant, different location\n",[35,2526,2527,2529,2531,2533,2535,2537],{"class":37,"line":51},[35,2528,2342],{"class":139},[35,2530,233],{"class":135},[35,2532,745],{"class":139},[35,2534,662],{"class":131},[35,2536,750],{"class":139},[35,2538,2539],{"class":41},"\u002F\u002F false (monotonic clock is stripped by In())\n",[35,2541,2542,2544,2546,2548,2550,2552],{"class":37,"line":57},[35,2543,2342],{"class":139},[35,2545,233],{"class":135},[35,2547,816],{"class":139},[35,2549,666],{"class":135},[35,2551,2480],{"class":139},[35,2553,890],{"class":41},[14,2555,2557],{"id":2556},"whats-next","📚 What's Next",[2366,2559,2560,2561,2566],{},"→ ",[2562,2563,2565],"a",{"href":2564},"\u002Fgo\u002F25-testing-and-benchmarking","25 — Testing & Benchmarking"," — table-driven tests, benchmarks, fuzzing, httptest, and coverage.",[2568,2569,2570],"style",{},"html pre.shiki code .sdCPZ, html code.shiki .sdCPZ{--shiki-default:#6A737D;--shiki-github-dark:#6A737D}html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-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 .github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html.github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html pre.shiki code .sCrzJ, html code.shiki .sCrzJ{--shiki-default:#E36209;--shiki-github-dark:#FFAB70}",{"title":31,"searchDepth":45,"depth":45,"links":2572},[2573,2575,2576],{"id":16,"depth":45,"text":2574},"time.Time — Wall Clock + Monotonic Clock",{"id":288,"depth":45,"text":289},{"id":2556,"depth":45,"text":2557},"Monotonic vs wall clock, the reference time format, time zone handling, the == vs Equal trap, and tickers\u002Ftimers for scheduling.","md",{},"\u002Fgo\u002F24-time-and-dates",{"title":5,"description":2577},"go\u002F24-time-and-dates","rBFD6R97zXrrih8gqaK7sHYWnuQpA2R2xNdbBsyrlcw",1789924648759]