unisbadri.com » Python Java Golang Typescript Kotlin Ruby Rust Dart PHP

Date & Time #

Package time di Go menyimpan satu keunikan yang mengejutkan hampir setiap developer baru: format waktu tidak menggunakan YYYY-MM-DD HH:mm:ss seperti kebanyakan bahasa lain, melainkan menggunakan reference time — tanggal dan waktu spesifik yang dijadikan template. Mengapa 2006-01-02 dan bukan YYYY-MM-DD? Karena desainer Go ingin format yang bisa dibaca sekaligus sebagai contoh output-nya, bukan simbol abstrak yang harus diingat. Selain keunikan ini, package time Go sangat kaya: tipe Duration yang ekspresif, timezone handling yang explicit, dan primitif Timer/Ticker untuk scheduling.

time.Time — Tipe Dasar #

time.Time adalah tipe utama yang merepresentasikan satu titik waktu dengan presisi nanosecond. Ia menyimpan informasi zona waktu secara internal:

import "time"

// Zero value — 1 Januari tahun 1, 00:00:00 UTC
var t time.Time
fmt.Println(t)          // 0001-01-01 00:00:00 +0000 UTC
fmt.Println(t.IsZero()) // true

// Cek apakah time sudah diset
func processOrder(order Order) {
    if order.PaidAt.IsZero() {
        fmt.Println("Order belum dibayar")
        return
    }
    fmt.Println("Dibayar pada:", order.PaidAt)
}

Membuat Time #

Waktu Saat Ini #

now := time.Now()          // waktu lokal sistem
fmt.Println(now)            // 2024-07-28 15:30:45.123456789 +0700 WIB

nowUTC := time.Now().UTC() // waktu saat ini dalam UTC
fmt.Println(nowUTC)         // 2024-07-28 08:30:45.123456789 +0000 UTC

Waktu Spesifik #

// time.Date(year, month, day, hour, min, sec, nanosec, location)
hut79RI := time.Date(2024, time.August, 17, 0, 0, 0, 0, time.UTC)
fmt.Println(hut79RI)  // 2024-08-17 00:00:00 +0000 UTC

// Gunakan konstanta time.Month untuk kejelasan
t := time.Date(2024, time.December, 31, 23, 59, 59, 0, time.Local)

Dari Unix Timestamp #

// Unix timestamp — detik sejak 1 Januari 1970 UTC
ts := int64(1722157845)
t := time.Unix(ts, 0)
fmt.Println(t)  // 2024-07-28 15:30:45 +0700 WIB

// Unix timestamp dalam milidetik (umum dari JavaScript/API)
tsMs := int64(1722157845000)
t2 := time.UnixMilli(tsMs)
fmt.Println(t2)

// Konversi balik ke timestamp
fmt.Println(t.Unix())      // detik
fmt.Println(t.UnixMilli()) // milidetik
fmt.Println(t.UnixNano())  // nanosecond

Sistem Format Unik Go — Reference Time #

Ini adalah hal yang paling membingungkan sekaligus paling elegan di package time Go. Alih-alih simbol abstrak seperti YYYY untuk tahun atau HH untuk jam, Go menggunakan tanggal dan waktu referensi yang spesifik:

Senin, 2 Januari 2006, 15:04:05, -0700

Dalam angka: 01/02 03:04:05PM '06 -0700

Tanggal referensi ini dipilih karena setiap komponennya adalah urutan 1-7:

  • 2006 = tahun
  • 01 = bulan (Januari = bulan ke-1)
  • 02 = hari
  • 15 = jam (format 24 jam, atau 03 untuk 12 jam)
  • 04 = menit
  • 05 = detik
  • -07 atau -0700 = timezone offset
now := time.Now()

// Format berbagai gaya menggunakan reference time
fmt.Println(now.Format("2006-01-02"))                    // 2024-07-28
fmt.Println(now.Format("02/01/2006"))                    // 28/07/2024
fmt.Println(now.Format("2006-01-02 15:04:05"))           // 2024-07-28 15:30:45
fmt.Println(now.Format("Monday, 02 January 2006"))       // Sunday, 28 July 2024
fmt.Println(now.Format("Jan 2, 2006 at 3:04pm"))         // Jul 28, 2024 at 3:30pm
fmt.Println(now.Format("15:04:05.000"))                  // 15:30:45.123 (milidetik)
fmt.Println(now.Format("2006-01-02T15:04:05Z07:00"))     // ISO 8601 / RFC3339

Konstanta Format Siap Pakai #

Package time menyediakan konstanta format yang umum dipakai — tidak perlu ingat formatnya sendiri:

now := time.Now()

fmt.Println(now.Format(time.RFC3339))        // 2024-07-28T15:30:45+07:00
fmt.Println(now.Format(time.RFC3339Nano))    // 2024-07-28T15:30:45.123456789+07:00
fmt.Println(now.Format(time.RFC822))         // 28 Jul 24 15:30 WIB
fmt.Println(now.Format(time.RFC1123))        // Sun, 28 Jul 2024 15:30:45 WIB
fmt.Println(now.Format(time.Kitchen))        // 3:30PM
fmt.Println(now.Format(time.DateTime))       // 2024-07-28 15:30:45 (Go 1.20+)
fmt.Println(now.Format(time.DateOnly))       // 2024-07-28 (Go 1.20+)
fmt.Println(now.Format(time.TimeOnly))       // 15:30:45 (Go 1.20+)

Parsing String ke time.Time #

time.Parse — Parsing Tanpa Timezone #

// Parse menggunakan layout yang sama dengan Format
layout := "2006-01-02"
t, err := time.Parse(layout, "2024-07-28")
if err != nil {
    log.Fatal(err)
}
fmt.Println(t)  // 2024-07-28 00:00:00 +0000 UTC

// Parse dengan waktu lengkap
layout2 := "2006-01-02 15:04:05"
t2, err := time.Parse(layout2, "2024-07-28 15:30:45")
if err != nil {
    log.Fatal(err)
}
fmt.Println(t2)  // 2024-07-28 15:30:45 +0000 UTC

// Parse RFC3339 (format API yang paling umum)
t3, err := time.Parse(time.RFC3339, "2024-07-28T15:30:45+07:00")

time.ParseInLocation — Parsing dengan Timezone Eksplisit #

// ANTI-PATTERN: time.Parse tanpa timezone info menghasilkan UTC
layout := "2006-01-02 15:04:05"
t, _ := time.Parse(layout, "2024-07-28 15:30:45")
fmt.Println(t.Location())  // UTC — bukan WIB!

// BENAR: gunakan ParseInLocation ketika string tidak punya info timezone
wib, _ := time.LoadLocation("Asia/Jakarta")
t2, err := time.ParseInLocation(layout, "2024-07-28 15:30:45", wib)
if err != nil {
    log.Fatal(err)
}
fmt.Println(t2.Location())  // Asia/Jakarta ✓
fmt.Println(t2.UTC())       // 2024-07-28 08:30:45 +0000 UTC (dikurangi 7 jam)
time.Parse selalu mengasumsikan UTC jika string tidak mengandung informasi timezone. Untuk input dari user atau database yang tidak punya timezone marker, selalu gunakan time.ParseInLocation dengan timezone yang benar. Ini adalah sumber bug yang sangat umum pada aplikasi yang beroperasi di timezone non-UTC.

Komponen Waktu #

t := time.Now()

// Komponen individual
fmt.Println(t.Year())        // 2024
fmt.Println(t.Month())       // July (tipe time.Month)
fmt.Println(int(t.Month()))  // 7
fmt.Println(t.Day())         // 28
fmt.Println(t.Hour())        // 15
fmt.Println(t.Minute())      // 30
fmt.Println(t.Second())      // 45
fmt.Println(t.Nanosecond())  // 123456789
fmt.Println(t.Weekday())     // Sunday (tipe time.Weekday)

// Komponen gabungan
year, month, day := t.Date()           // 2024, July, 28
hour, min, sec := t.Clock()            // 15, 30, 45

// Nama hari dan bulan
fmt.Println(t.Weekday().String())  // "Sunday"
fmt.Println(t.Month().String())    // "July"

// Day of year
fmt.Println(t.YearDay())  // 210 (hari ke-210 dalam tahun)

// Unix timestamps
fmt.Println(t.Unix())      // 1722157845
fmt.Println(t.UnixMilli()) // 1722157845123
fmt.Println(t.UnixNano())  // 1722157845123456789

time.Duration — Merepresentasikan Durasi #

time.Duration adalah tipe int64 yang merepresentasikan durasi dalam nanosecond. Package time menyediakan konstanta yang sangat ekspresif:

// Konstanta durasi
fmt.Println(time.Nanosecond)   // 1ns
fmt.Println(time.Microsecond)  // 1µs
fmt.Println(time.Millisecond)  // 1ms
fmt.Println(time.Second)       // 1s
fmt.Println(time.Minute)       // 1m0s
fmt.Println(time.Hour)         // 1h0m0s

// Membuat durasi
timeout := 30 * time.Second    // 30s
delay := 500 * time.Millisecond // 500ms
ttl := 24 * time.Hour          // 24h0m0s
week := 7 * 24 * time.Hour     // 168h0m0s

// Parsing durasi dari string
d, err := time.ParseDuration("1h30m45s")
if err != nil {
    log.Fatal(err)
}
fmt.Println(d)             // 1h30m45s
fmt.Println(d.Hours())     // 1.5125
fmt.Println(d.Minutes())   // 90.75
fmt.Println(d.Seconds())   // 5445
fmt.Println(d.Milliseconds()) // 5445000

// Aritmatika durasi
fmt.Println(2*time.Hour + 30*time.Minute)  // 2h30m0s

Operasi Waktu #

Menambah dan Mengurangi Durasi #

now := time.Now()

// Add — tambah durasi (bisa negatif untuk mengurangi)
besok := now.Add(24 * time.Hour)
kemarin := now.Add(-24 * time.Hour)
tigaJamLagi := now.Add(3 * time.Hour)

// AddDate — tambah tahun, bulan, hari
bulanDepan := now.AddDate(0, 1, 0)   // tambah 1 bulan
tahunDepan := now.AddDate(1, 0, 0)   // tambah 1 tahun
duaMingguLagi := now.AddDate(0, 0, 14) // tambah 14 hari

Menghitung Selisih #

start := time.Date(2024, time.January, 1, 0, 0, 0, 0, time.UTC)
end := time.Date(2024, time.July, 28, 0, 0, 0, 0, time.UTC)

durasi := end.Sub(start)
fmt.Println(durasi)             // 5136h0m0s
fmt.Printf("%.0f hari\n", durasi.Hours()/24)  // 214 hari

// time.Since — selisih dari waktu lalu ke sekarang
elapsed := time.Since(start)

// time.Until — selisih dari sekarang ke waktu mendatang
remaining := time.Until(end)

Perbandingan Waktu #

t1 := time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)
t2 := time.Date(2024, 6, 1, 0, 0, 0, 0, time.UTC)

fmt.Println(t1.Before(t2))  // true — t1 sebelum t2
fmt.Println(t1.After(t2))   // false
fmt.Println(t1.Equal(t2))   // false

// Jangan gunakan == untuk membandingkan time.Time!
// == tidak memperhitungkan timezone
// Gunakan .Equal() yang timezone-aware
utc := time.Date(2024, 1, 1, 8, 0, 0, 0, time.UTC)
wib, _ := time.LoadLocation("Asia/Jakarta")
wibTime := time.Date(2024, 1, 1, 15, 0, 0, 0, wib)

fmt.Println(utc == wibTime)       // false — representasi berbeda
fmt.Println(utc.Equal(wibTime))   // true — momen yang sama

Truncate dan Round #

t := time.Date(2024, 7, 28, 15, 37, 45, 123456789, time.UTC)

// Truncate — bulatkan ke bawah
fmt.Println(t.Truncate(time.Hour))          // 2024-07-28 15:00:00 UTC
fmt.Println(t.Truncate(time.Minute))        // 2024-07-28 15:37:00 UTC
fmt.Println(t.Truncate(24 * time.Hour))     // 2024-07-28 00:00:00 UTC

// Round — bulatkan ke terdekat
fmt.Println(t.Round(time.Hour))             // 2024-07-28 16:00:00 UTC (37m > 30m)
fmt.Println(t.Round(time.Minute))           // 2024-07-28 15:38:00 UTC (45s > 30s)

// Berguna untuk: abaikan presisi milidetik saat menyimpan ke DB
createdAt := time.Now().Truncate(time.Second)

Timezone #

Konstanta Timezone Bawaan #

// UTC — selalu tersedia
t := time.Now().UTC()

// Local — timezone sistem operasi
tLocal := time.Now().In(time.Local)
fmt.Println(time.Local)  // nama timezone lokal

LoadLocation — Timezone by Name #

// Nama timezone mengikuti IANA Time Zone Database
wib, err := time.LoadLocation("Asia/Jakarta")
if err != nil {
    log.Fatal(err)
}

wita, _ := time.LoadLocation("Asia/Makassar")
wit, _  := time.LoadLocation("Asia/Jayapura")
tokyo, _ := time.LoadLocation("Asia/Tokyo")
london, _ := time.LoadLocation("Europe/London")
newYork, _ := time.LoadLocation("America/New_York")

now := time.Now()
fmt.Println("WIB:    ", now.In(wib))
fmt.Println("WITA:   ", now.In(wita))
fmt.Println("WIT:    ", now.In(wit))
fmt.Println("Tokyo:  ", now.In(tokyo))
fmt.Println("London: ", now.In(london))
fmt.Println("NY:     ", now.In(newYork))

FixedZone — Timezone Manual #

// Buat timezone dengan offset manual (tanpa database IANA)
wib := time.FixedZone("WIB", 7*60*60)   // UTC+7
wita := time.FixedZone("WITA", 8*60*60) // UTC+8
wit := time.FixedZone("WIT", 9*60*60)   // UTC+9

t := time.Now().In(wib)
fmt.Println(t.Format("2006-01-02 15:04:05 MST"))
Selalu simpan waktu dalam UTC di database. Konversi ke timezone lokal hanya dilakukan saat menampilkan ke pengguna. Ini mencegah berbagai masalah saat server berpindah timezone, daylight saving time berubah, atau aplikasi melayani pengguna dari berbagai timezone.

Timer dan Ticker #

time.Sleep — Tunda Eksekusi #

fmt.Println("Mulai")
time.Sleep(2 * time.Second)  // blokir selama 2 detik
fmt.Println("Setelah 2 detik")

time.After — Channel yang Menerima Setelah Durasi #

// Berguna untuk timeout
select {
case result := <-doWork():
    fmt.Println("Selesai:", result)
case <-time.After(5 * time.Second):
    fmt.Println("Timeout! Operasi terlalu lama")
}

time.NewTimer — Timer yang Bisa Dibatalkan #

timer := time.NewTimer(3 * time.Second)
defer timer.Stop()  // penting: selalu stop untuk mencegah goroutine leak

select {
case <-timer.C:
    fmt.Println("Timer fired!")
case <-cancel:
    fmt.Println("Dibatalkan sebelum timer")
}

time.NewTicker — Eksekusi Periodik #

// Jalankan setiap 1 detik, berhenti setelah 5 kali
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()  // selalu stop

count := 0
for range ticker.C {
    count++
    fmt.Printf("Tick %d: %s\n", count, time.Now().Format(time.TimeOnly))
    if count >= 5 {
        break
    }
}

// Pola umum: ticker dalam goroutine dengan stop channel
stopCh := make(chan struct{})
go func() {
    ticker := time.NewTicker(10 * time.Second)
    defer ticker.Stop()
    for {
        select {
        case <-ticker.C:
            doPeriodicWork()
        case <-stopCh:
            return
        }
    }
}()

Mengukur Durasi Eksekusi #

// Cara manual
start := time.Now()
doHeavyWork()
elapsed := time.Since(start)
fmt.Printf("Selesai dalam %v\n", elapsed)

// Dengan defer — elegan untuk profiling fungsi
func processLargeFile(path string) error {
    start := time.Now()
    defer func() {
        fmt.Printf("processLargeFile(%q) selesai dalam %v\n",
            path, time.Since(start))
    }()

    // ... proses file
    return nil
}

// Benchmark sederhana
func benchmark(name string, fn func()) time.Duration {
    start := time.Now()
    fn()
    d := time.Since(start)
    fmt.Printf("[BENCH] %s: %v\n", name, d)
    return d
}

benchmark("sortLargeSlice", func() {
    sort.Ints(bigSlice)
})

Contoh Program Lengkap #

Program berikut membangun sistem manajemen jadwal dan pengukur performa:

package main

import (
    "fmt"
    "sort"
    "time"
)

// ── Scheduler ─────────────────────────────────────────────────

type Priority int

const (
    PriorityLow Priority = iota
    PriorityNormal
    PriorityHigh
    PriorityCritical
)

type Task struct {
    ID          int
    Name        string
    ScheduledAt time.Time
    Deadline    time.Time
    Priority    Priority
    Duration    time.Duration
    CompletedAt time.Time
}

func (t Task) IsOverdue() bool {
    if t.CompletedAt.IsZero() {
        return time.Now().After(t.Deadline)
    }
    return t.CompletedAt.After(t.Deadline)
}

func (t Task) TimeUntilDeadline() time.Duration {
    return time.Until(t.Deadline)
}

func (t Task) Status() string {
    if !t.CompletedAt.IsZero() {
        if t.IsOverdue() {
            return "✗ Selesai (terlambat)"
        }
        return "✓ Selesai"
    }
    if t.IsOverdue() {
        return "⚠ Terlambat"
    }
    remaining := t.TimeUntilDeadline()
    if remaining < time.Hour {
        return fmt.Sprintf("⚡ Mendesak (%v lagi)", remaining.Round(time.Minute))
    }
    return fmt.Sprintf("○ Pending (%v lagi)", remaining.Round(time.Hour))
}

type Scheduler struct {
    tasks  []Task
    nextID int
    wib    *time.Location
}

func NewScheduler() *Scheduler {
    wib, _ := time.LoadLocation("Asia/Jakarta")
    return &Scheduler{wib: wib}
}

func (s *Scheduler) AddTask(name string, scheduledAt, deadline time.Time,
    priority Priority, duration time.Duration) Task {
    s.nextID++
    task := Task{
        ID:          s.nextID,
        Name:        name,
        ScheduledAt: scheduledAt,
        Deadline:    deadline,
        Priority:    priority,
        Duration:    duration,
    }
    s.tasks = append(s.tasks, task)
    return task
}

func (s *Scheduler) Complete(id int) error {
    for i := range s.tasks {
        if s.tasks[i].ID == id {
            s.tasks[i].CompletedAt = time.Now()
            return nil
        }
    }
    return fmt.Errorf("task ID %d tidak ditemukan", id)
}

func (s *Scheduler) TasksDueToday() []Task {
    now := time.Now().In(s.wib)
    todayStart := now.Truncate(24 * time.Hour)
    todayEnd := todayStart.Add(24 * time.Hour)

    var result []Task
    for _, t := range s.tasks {
        dl := t.Deadline.In(s.wib)
        if (dl.Equal(todayStart) || dl.After(todayStart)) &&
            dl.Before(todayEnd) {
            result = append(result, t)
        }
    }
    return result
}

func (s *Scheduler) SortByDeadline() {
    sort.Slice(s.tasks, func(i, j int) bool {
        return s.tasks[i].Deadline.Before(s.tasks[j].Deadline)
    })
}

// ── Performance Monitor ───────────────────────────────────────

type PerfMonitor struct {
    records map[string][]time.Duration
}

func NewPerfMonitor() *PerfMonitor {
    return &PerfMonitor{records: make(map[string][]time.Duration)}
}

func (pm *PerfMonitor) Measure(name string, fn func()) {
    start := time.Now()
    fn()
    d := time.Since(start)
    pm.records[name] = append(pm.records[name], d)
}

func (pm *PerfMonitor) Report() {
    fmt.Println("\n=== Laporan Performa ===")

    names := make([]string, 0, len(pm.records))
    for name := range pm.records { names = append(names, name) }
    sort.Strings(names)

    for _, name := range names {
        durations := pm.records[name]
        if len(durations) == 0 {
            continue
        }

        var total time.Duration
        min, max := durations[0], durations[0]
        for _, d := range durations {
            total += d
            if d < min { min = d }
            if d > max { max = d }
        }
        avg := total / time.Duration(len(durations))

        fmt.Printf("  %-25s n=%d  avg=%v  min=%v  max=%v\n",
            name, len(durations), avg.Round(time.Microsecond),
            min.Round(time.Microsecond), max.Round(time.Microsecond))
    }
}

// ── Main ──────────────────────────────────────────────────────

func main() {
    wib, _ := time.LoadLocation("Asia/Jakarta")
    now := time.Now().In(wib)

    scheduler := NewScheduler()
    perf := NewPerfMonitor()

    // Tambah task
    scheduler.AddTask("Review Pull Request",
        now,
        now.Add(2*time.Hour),
        PriorityHigh,
        30*time.Minute)

    scheduler.AddTask("Deploy ke Production",
        now.Add(3*time.Hour),
        now.Add(5*time.Hour),
        PriorityCritical,
        45*time.Minute)

    scheduler.AddTask("Update Dokumentasi",
        now.Add(time.Hour),
        now.Add(24*time.Hour),
        PriorityNormal,
        2*time.Hour)

    scheduler.AddTask("Rapat Sprint Planning",
        now.Add(-30*time.Minute), // sudah lewat
        now.Add(-15*time.Minute), // deadline sudah lewat
        PriorityHigh,
        time.Hour)

    scheduler.AddTask("Backup Database",
        now.Add(20*time.Hour),
        now.Add(22*time.Hour),
        PriorityNormal,
        15*time.Minute)

    // Selesaikan task 1
    _ = scheduler.Complete(1)

    // Sort berdasarkan deadline
    scheduler.SortByDeadline()

    fmt.Printf("=== Jadwal Task — %s ===\n\n",
        now.Format("Monday, 02 January 2006"))

    for _, t := range scheduler.tasks {
        dl := t.Deadline.In(wib)
        fmt.Printf("  [ID:%d] %s\n", t.ID, t.Name)
        fmt.Printf("    Deadline : %s\n", dl.Format("15:04 MST"))
        fmt.Printf("    Estimasi : %v\n", t.Duration)
        fmt.Printf("    Status   : %s\n", t.Status())
        fmt.Println()
    }

    // Task yang jatuh tempo hari ini
    today := scheduler.TasksDueToday()
    fmt.Printf("Task jatuh tempo hari ini: %d task\n", len(today))

    // Simulasi pengukuran performa
    fmt.Println("\n=== Simulasi Pengukuran Performa ===")

    for i := 0; i < 5; i++ {
        perf.Measure("parse tanggal", func() {
            for j := 0; j < 1000; j++ {
                t, _ := time.Parse("2006-01-02", "2024-07-28")
                _ = t
            }
        })
    }

    for i := 0; i < 5; i++ {
        perf.Measure("format tanggal", func() {
            for j := 0; j < 1000; j++ {
                s := now.Format("2006-01-02 15:04:05")
                _ = s
            }
        })
    }

    perf.Measure("parse RFC3339", func() {
        for j := 0; j < 1000; j++ {
            t, _ := time.Parse(time.RFC3339, "2024-07-28T15:30:45+07:00")
            _ = t
        }
    })

    perf.Report()

    // Demonstrasi timezone
    fmt.Println("\n=== Waktu di Berbagai Zona ===")
    zones := []struct {
        name     string
        location string
    }{
        {"WIB", "Asia/Jakarta"},
        {"WITA", "Asia/Makassar"},
        {"WIT", "Asia/Jayapura"},
        {"Tokyo", "Asia/Tokyo"},
        {"UTC", "UTC"},
        {"New York", "America/New_York"},
    }

    for _, z := range zones {
        loc, err := time.LoadLocation(z.location)
        if err != nil {
            continue
        }
        fmt.Printf("  %-10s %s\n", z.name+":", now.In(loc).Format("15:04:05 MST (UTC-07)"))
    }

    // Demonstrasi Duration parsing
    fmt.Println("\n=== Operasi Durasi ===")
    durations := []string{"1h30m", "45m", "2h", "90s", "1.5h"}
    for _, ds := range durations {
        d, err := time.ParseDuration(ds)
        if err != nil {
            fmt.Printf("  %s: error\n", ds)
            continue
        }
        fmt.Printf("  %-8s = %v (%.0f menit)\n", ds, d, d.Minutes())
    }
}

Ringkasan #

  • Reference time Go adalah 2006-01-02 15:04:05 -0700 — bukan simbol abstrak seperti YYYY, tapi nilai aktual yang setiap komponennya menunjukkan posisi dalam format.
  • Gunakan time.RFC3339 (2006-01-02T15:04:05Z07:00) sebagai format standar untuk API dan penyimpanan.
  • time.Parse selalu menghasilkan UTC jika string tidak punya timezone — gunakan time.ParseInLocation untuk string tanpa timezone yang sebenarnya bukan UTC.
  • time.Duration adalah int64 nanosecond — gunakan konstanta time.Second, time.Minute, dll untuk keterbacaan.
  • time.Until(t) dan time.Since(t) lebih ekspresif dari t.Sub(time.Now()).
  • Gunakan .Equal() bukan == untuk membandingkan time.Time== tidak memperhitungkan timezone.
  • Selalu simpan waktu dalam UTC di database; konversi ke timezone lokal hanya saat ditampilkan ke pengguna.
  • time.NewTicker untuk eksekusi periodik; time.NewTimer untuk one-time delay yang bisa dibatalkan — selalu panggil .Stop().
  • Ukur performa dengan start := time.Now() dan time.Since(start) — atau gunakan defer untuk mengukur seluruh durasi fungsi.
  • time.Truncate untuk membulatkan ke bawah (awal jam, awal hari); time.Round untuk membulatkan ke terdekat.

← Sebelumnya: Map   Berikutnya: Regex →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact