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ị | Magic | Ví dụ ngày Mon Jan 2 15:04:05 MST 2006 |
|---|---|---|
| Năm 4-chữ | 2006 | 2006 |
| Năm 2-chữ | 06 | 06 |
| Tháng số (pad) | 01 | 01 (Jan) |
| Tháng số (no pad) | 1 | 1 |
| Tháng chữ ngắn | Jan | Jan |
| Tháng chữ dài | January | January |
| Ngày (pad) | 02 | 02 |
| Thứ ngắn | Mon | Mon |
| Thứ dài | Monday | Monday |
| Giờ 24h | 15 | 15 (3 PM) |
| Giờ 12h | 03 | 03 |
| Phút | 04 | 04 |
| Giây | 05 | 05 |
| Mili-giây | .000 | 05.000 → 05.123 |
| AM/PM | PM | PM |
| Zone tên | MST | MST → UTC, +07 |
| Zone offset | -0700 | -0700 → +0700 |
| Zone ISO | Z07:00 | Z (UTC) hoặc +07:00 |
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ộ.
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.
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.
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**.
•
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.
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
- Layout của Go = chính ngày
Mon Jan 2 15:04:05 MST 2006viết theo format mong muốn. Magic theo thứ tự "1 2 3 4 5 6 7". - Timezone là view, không phải property của instant. Lưu UTC, hiển thị Local.
- Đo elapsed luôn dùng
time.Since(start)— monotonic clock không bị NTP adjust. - So sánh time bằng
Equal/Before/After, KHÔNG dùng==. - Ticker phải
defer Stop(); Sleep trong loop dài có drift → dùng Ticker.
Code Go đầy đủ: solutions.go. Lý thuyết + bài tập: README.md.