Lesson 25 — Time & Date

3 module dưới đây giúp bạn (1) thực hành layout magic-number của Go (nhập layout, thấy current time render real-time + cheat sheet 10 ví dụ); (2) cảm nhận timezone qua 4 đồng hồ analog song song — đổi instant ở một nơi, cả 4 sync cùng lúc; (3) so sánh Ticker vs Timer với animation trên track thời gian, log mỗi lần fire.

1. Format reference — viết layout, xem kết quả

Trong Go, layout không phải YYYY-MM-DD mà là chính ngày Mon Jan 2 15:04:05 MST 2006 viết theo format bạn muốn. Nhập layout vào ô dưới, kết quả render từ time.Now() ngay lập tức.

📖 Cheat sheet — bảng magic number
Đơn vịMagicVí dụ ngày Mon Jan 2 15:04:05 MST 2006
Năm 4-chữ20062006
Năm 2-chữ0606
Tháng số (pad)0101 (Jan)
Tháng số (no pad)11
Tháng chữ ngắnJanJan
Tháng chữ dàiJanuaryJanuary
Ngày (pad)0202
Thứ ngắnMonMon
Thứ dàiMondayMonday
Giờ 24h1515 (3 PM)
Giờ 12h0303
Phút0404
Giây0505
Mili-giây.00005.000 → 05.123
AM/PMPMPM
Zone tênMSTMST → UTC, +07
Zone offset-0700-0700 → +0700
Zone ISOZ07:00Z (UTC) hoặc +07:00
Mẹo nhớ: sắp theo thứ tự đơn vị → 01 02 03 04 05 06 07 = tháng, ngày, giờ 12h, phút, giây, năm 2-chữ, zone offset. Cứ đọc "1 2 3 4 5 6 7" là nhớ được toàn bộ.
⚠️ Sai phổ biến: viết YYYY-MM-DD → format trả về chuỗi literal "YYYY-MM-DD" (vì không ký tự nào match magic). Luôn dùng 2006-01-02.

2. Timezone converter — 1 instant, 4 view

Đổi instant ở bất kỳ ô nào (chỉnh ngày, giờ, hoặc bấm "Now"). 4 đồng hồ và 4 dòng date sync theo cùng một instant tuyệt đối, chỉ khác cách hiển thị do offset zone.

Unix: — · Instant: —
UTC (offset 0)
🌍 UTC
Asia/Ho_Chi_Minh (+07:00)
🇻🇳 Hà Nội / TP.HCM
America/New_York (-05:00 / -04:00 DST)
🇺🇸 New York
Asia/Tokyo (+09:00)
🇯🇵 Tokyo
Pattern thực tế: lưu instant này (vd user.created_at) vào DB ở dạng UTC. Khi hiển thị, chuyển sang zone của user (t.In(loc)). 4 dòng trên minh họa cùng instant nhìn từ 4 nơi.
⚠️ Pitfall: server log timestamp UTC, dashboard hiển thị Local — user thấy "lỗi xảy ra 17:30" nhưng tìm trong log "10:30" → tưởng lệch giờ. Luôn ghi chú rõ zone trong UI.

3. Ticker vs Timer — animation trên track thời gian

Track ngang đại diện 10 giây thời gian. Cursor đen di chuyển từ trái sang phải, đại diện "hiện tại". Mỗi lần Timer fire hoặc Ticker tick sẽ có chấm tròn nổi lên tại vị trí cursor lúc đó. Quan sát sự khác biệt: Timer fire **một lần**, Ticker fire **lặp đều**.

0
Lần fire
0.0s
Đã chạy
Mode
Bấm Start Ticker hoặc One-shot Timer để bắt đầu.
Khi nào dùng cái nào?
time.NewTimer(d): chờ một lần sau d, có Stop/Reset. Ví dụ: timeout cho request.
time.NewTicker(d): lặp đều mỗi d. Ví dụ: heartbeat, polling, rate limiter.
time.After(d): shortcut cho one-shot trong select, không cần Stop.
time.Sleep(d): block goroutine, không cancel được — chỉ dùng khi chắc chắn không cần dừng giữa chừng.
⚠️ Phải defer ticker.Stop(). Quên Stop = goroutine ngầm tiếp tục gửi vào channel → memory leak. Bug này hiếm khi crash ngay nhưng làm process phình bộ nhớ sau vài giờ.

4. Tổng kết

Code Go đầy đủ: solutions.go. Lý thuyết + bài tập: README.md.