Time & Duration

Time & Duration #

Hampir setiap program yang cukup kompleks perlu berurusan dengan waktu — mengukur berapa lama suatu operasi berjalan, menentukan apakah suatu deadline sudah terlewat, menerapkan timeout pada network request, atau mencatat kapan suatu kejadian terjadi. Rust menyediakan dua konsep waktu yang sengaja dipisahkan di standard library: Instant untuk pengukuran durasi yang monotonic (selalu maju, tidak terpengaruh perubahan jam sistem), dan SystemTime untuk waktu kalender yang bisa dibandingkan dengan waktu dunia nyata. Perbedaan ini bukan kebetulan — mencampurnya adalah sumber bug yang umum di bahasa lain. Artikel ini membahas keduanya beserta Duration sebagai representasi interval waktu, pola idiomatik penggunaannya, dan cara menangani waktu kalender yang lebih lengkap dengan crate chrono.

Duration — Merepresentasikan Interval Waktu #

Duration adalah tipe yang merepresentasikan interval waktu yang tidak negatif. Ia menyimpan data sebagai jumlah detik dan nanodetik, memberikan presisi hingga satu nanodetik.

use std::time::Duration;

fn main() {
    // Membuat Duration dari berbagai unit
    let satu_detik = Duration::from_secs(1);
    let setengah_detik = Duration::from_millis(500);
    let satu_menit = Duration::from_secs(60);
    let satu_jam = Duration::from_secs(3600);
    let presisi_tinggi = Duration::from_nanos(1_500_000);  // 1.5 milidetik
    let dari_float = Duration::from_secs_f64(1.5);         // 1.5 detik

    // Konstanta yang berguna
    let nol = Duration::ZERO;
    let maks = Duration::MAX;

    println!("Satu detik: {:?}", satu_detik);         // 1s
    println!("Setengah detik: {:?}", setengah_detik); // 500ms

    // Mengakses komponen
    let durasi = Duration::from_millis(1_500);  // 1.5 detik
    println!("Detik: {}", durasi.as_secs());           // 1
    println!("Subsecond nanos: {}", durasi.subsec_nanos()); // 500_000_000
    println!("Total milidetik: {}", durasi.as_millis()); // 1500
    println!("Total nanodetik: {}", durasi.as_nanos());  // 1_500_000_000
    println!("Sebagai f64 detik: {}", durasi.as_secs_f64()); // 1.5

    // Aritmatika Duration
    let d1 = Duration::from_secs(10);
    let d2 = Duration::from_secs(3);

    let penjumlahan = d1 + d2;       // 13 detik
    let pengurangan = d1 - d2;       // 7 detik
    let perkalian = d1 * 3;          // 30 detik
    let pembagian = d1 / 2;          // 5 detik

    println!("{:?}", penjumlahan);  // 13s
    println!("{:?}", pembagian);    // 5s

    // Checked arithmetic — mengembalikan None jika overflow atau underflow
    let hasil = d2.checked_sub(d1);  // None — hasil negatif tidak valid
    println!("{:?}", hasil);          // None

    let hasil = d1.checked_sub(d2);  // Some(7s)
    println!("{:?}", hasil);          // Some(7s)

    // Saturating arithmetic — hasil dibatasi antara ZERO dan MAX
    let hasil = d2.saturating_sub(d1);  // Duration::ZERO, bukan underflow
    println!("{:?}", hasil);             // 0ns

    // Perbandingan
    println!("{}", d1 > d2);   // true
    println!("{}", d1 == Duration::from_millis(10_000));  // true
}

Instant — Pengukuran Waktu Monotonic #

Instant merepresentasikan titik waktu yang dijamin monotonic — nilainya selalu bertambah, tidak pernah mundur. Ini yang harus digunakan untuk mengukur durasi operasi, bukan SystemTime yang bisa mundur saat jam sistem disetel ulang.

use std::time::Instant;
use std::thread;
use std::time::Duration;

fn main() {
    // Ambil titik waktu sekarang
    let mulai = Instant::now();

    // Lakukan operasi yang ingin diukur
    operasi_yang_ingin_diukur();

    // Hitung elapsed time
    let durasi = mulai.elapsed();
    println!("Operasi memakan waktu: {:?}", durasi);
    println!("Dalam milidetik: {}", durasi.as_millis());

    // elapsed() ekuivalen dengan Instant::now() - mulai
    let sekarang = Instant::now();
    let manual = sekarang - mulai;

    // Instant bisa digunakan untuk deadline
    let batas_waktu = Instant::now() + Duration::from_secs(5);
    while Instant::now() < batas_waktu {
        // kerjakan sesuatu sampai waktu habis
        thread::sleep(Duration::from_millis(100));
        if kondisi_selesai() {
            break;
        }
    }

    // Mengukur banyak operasi
    let operasi = vec!["kecil", "sedang", "besar"];
    for nama in &operasi {
        let t = Instant::now();
        simulasi_operasi(nama);
        println!("{}: {:?}", nama, t.elapsed());
    }
}

fn operasi_yang_ingin_diukur() {
    thread::sleep(Duration::from_millis(50));
}

fn kondisi_selesai() -> bool { false }

fn simulasi_operasi(nama: &str) {
    let durasi = match nama {
        &"kecil" => Duration::from_millis(10),
        &"sedang" => Duration::from_millis(50),
        _ => Duration::from_millis(100),
    };
    thread::sleep(durasi);
}

Mengapa Instant, Bukan SystemTime, untuk Pengukuran #

use std::time::{Instant, SystemTime};

fn main() {
    // ANTI-PATTERN: menggunakan SystemTime untuk mengukur durasi
    let mulai = SystemTime::now();
    operasi_lambat();
    let durasi = SystemTime::now().duration_since(mulai);
    // duration_since mengembalikan Result karena SystemTime bisa mundur!
    // Jika jam sistem disetel ke masa lalu selama operasi, hasilnya Err

    // BENAR: Instant selalu monotonic, tidak pernah mundur
    let mulai = Instant::now();
    operasi_lambat();
    let durasi = mulai.elapsed();  // selalu berhasil, tidak perlu unwrap
    println!("{:?}", durasi);
}

fn operasi_lambat() {
    std::thread::sleep(std::time::Duration::from_millis(10));
}
flowchart TD
    A{Kebutuhan waktu?} --> B{Perlu waktu kalender?}
    B -- Ya --> C["SystemTime\nWaktu sejak UNIX epoch\nBisa dibandingkan dengan tanggal"]
    B -- Tidak --> D{Mengukur durasi operasi?}
    D -- Ya --> E["Instant::now()\nMonotonic, tidak bisa mundur\nGunakan .elapsed()"]
    D -- Tidak --> F{Interval tetap?}
    F -- Ya --> G["Duration::from_secs(n)\nInterval waktu yang fix"]
    F -- Tidak --> H["Kombinasi Instant + Duration\nDeadline dan timeout"]

    style C fill:#fff3e0
    style E fill:#e8f5e9
    style G fill:#e3f2fd
    style H fill:#e8f5e9

SystemTime — Waktu Kalender #

SystemTime merepresentasikan titik waktu berdasarkan jam sistem. Gunakan saat kamu perlu waktu yang bisa dikomunikasikan ke dunia luar — timestamp file, expiry token, logging dengan waktu.

use std::time::{SystemTime, UNIX_EPOCH, Duration};

fn main() {
    // Waktu sekarang
    let sekarang = SystemTime::now();

    // Konversi ke UNIX timestamp (detik sejak 1 Januari 1970 UTC)
    let unix_timestamp = sekarang
        .duration_since(UNIX_EPOCH)
        .expect("Waktu sebelum UNIX epoch");

    println!("UNIX timestamp: {}", unix_timestamp.as_secs());
    println!("Dengan milidetik: {}", unix_timestamp.as_millis());

    // Membuat SystemTime dari UNIX timestamp
    let timestamp: u64 = 1_700_000_000;  // contoh timestamp
    let waktu = UNIX_EPOCH + Duration::from_secs(timestamp);
    println!("{:?}", waktu);

    // Aritmatika SystemTime
    let satu_jam_lalu = SystemTime::now() - Duration::from_secs(3600);
    let satu_jam_lagi = SystemTime::now() + Duration::from_secs(3600);

    // duration_since mengembalikan Result — bisa gagal jika urutan waktu salah
    match satu_jam_lagi.duration_since(SystemTime::now()) {
        Ok(durasi) => println!("Dalam {} detik lagi", durasi.as_secs()),
        Err(e) => println!("Waktu sudah lewat {} detik yang lalu", e.duration().as_secs()),
    }

    // Pengecekan apakah suatu waktu sudah lewat
    fn sudah_kadaluarsa(expiry: SystemTime) -> bool {
        SystemTime::now() > expiry
    }

    let token_expiry = SystemTime::now() + Duration::from_secs(3600);
    println!("Token kadaluarsa: {}", sudah_kadaluarsa(token_expiry));  // false

    // Metadata file — waktu modifikasi
    use std::fs;
    if let Ok(metadata) = fs::metadata("Cargo.toml") {
        if let Ok(waktu_modif) = metadata.modified() {
            let umur = SystemTime::now()
                .duration_since(waktu_modif)
                .unwrap_or(Duration::ZERO);
            println!("File terakhir dimodifikasi {} detik lalu", umur.as_secs());
        }
    }
}

Timeout pada Operasi Konkuren #

Timeout adalah salah satu penggunaan Duration dan Instant yang paling sering di kode nyata — terutama saat bekerja dengan channel, lock, atau network.

use std::sync::mpsc;
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};
use std::thread;

fn main() {
    // Timeout pada channel recv
    let (tx, rx) = mpsc::channel::<String>();

    thread::spawn(move || {
        thread::sleep(Duration::from_millis(200));
        tx.send(String::from("pesan terlambat")).unwrap();
    });

    match rx.recv_timeout(Duration::from_millis(100)) {
        Ok(pesan) => println!("Diterima: {}", pesan),
        Err(mpsc::RecvTimeoutError::Timeout) => println!("Timeout — pesan tidak datang tepat waktu"),
        Err(mpsc::RecvTimeoutError::Disconnected) => println!("Sender sudah ter-drop"),
    }

    // Timeout pada Mutex lock
    let mutex = Arc::new(Mutex::new(0i32));
    let mutex_clone = Arc::clone(&mutex);

    // Simulasi thread yang memegang lock lama
    let _guard_holder = thread::spawn(move || {
        let _lock = mutex_clone.lock().unwrap();
        thread::sleep(Duration::from_millis(500));
        // lock dilepas saat thread selesai
    });

    thread::sleep(Duration::from_millis(10));  // beri waktu thread lain ambil lock

    // try_lock dengan retry loop dan deadline
    let deadline = Instant::now() + Duration::from_millis(100);
    let berhasil = loop {
        match mutex.try_lock() {
            Ok(mut nilai) => {
                *nilai += 1;
                break true;
            }
            Err(_) => {
                if Instant::now() >= deadline {
                    break false;
                }
                thread::sleep(Duration::from_millis(10));
            }
        }
    };
    println!("Lock berhasil diperoleh: {}", berhasil);

    // Retry dengan exponential backoff
    fn operasi_dengan_retry<F, T, E>(
        operasi: F,
        maks_percobaan: u32,
        backoff_awal: Duration,
    ) -> Result<T, E>
    where
        F: Fn() -> Result<T, E>,
    {
        let mut backoff = backoff_awal;
        for percobaan in 0..maks_percobaan {
            match operasi() {
                Ok(hasil) => return Ok(hasil),
                Err(e) if percobaan + 1 == maks_percobaan => return Err(e),
                Err(_) => {
                    println!("Percobaan {} gagal, menunggu {:?}", percobaan + 1, backoff);
                    thread::sleep(backoff);
                    backoff = backoff.saturating_mul(2);  // double setiap retry
                }
            }
        }
        unreachable!()
    }

    let mut percobaan = 0;
    let hasil = operasi_dengan_retry(
        || -> Result<i32, &str> {
            percobaan += 1;
            if percobaan < 3 { Err("gagal") } else { Ok(42) }
        },
        5,
        Duration::from_millis(10),
    );
    println!("Hasil setelah retry: {:?}", hasil);
}

Benchmarking Sederhana #

Instant adalah fondasi untuk mengukur performa kode. Meskipun untuk benchmarking serius kamu perlu crate seperti criterion, pengukuran cepat dengan Instant sudah berguna untuk validasi awal.

use std::time::{Instant, Duration};

// Helper sederhana untuk benchmarking
fn ukur_waktu<F: Fn()>(nama: &str, iterasi: u32, fungsi: F) {
    // Warm-up — biarkan CPU cache dan branch predictor beradaptasi
    for _ in 0..10 {
        fungsi();
    }

    let mulai = Instant::now();
    for _ in 0..iterasi {
        fungsi();
    }
    let total = mulai.elapsed();
    let per_iterasi = total / iterasi;

    println!("{}: total {:?}, per iterasi {:?}", nama, total, per_iterasi);
}

fn main() {
    let data: Vec<i32> = (0..10_000).collect();

    // Bandingkan dua pendekatan
    let data_clone = data.clone();
    ukur_waktu("iter sum", 1000, || {
        let _: i32 = data_clone.iter().sum();
    });

    let data_clone = data.clone();
    ukur_waktu("fold manual", 1000, || {
        let _: i32 = data_clone.iter().fold(0, |acc, &x| acc + x);
    });

    let data_clone = data.clone();
    ukur_waktu("loop manual", 1000, || {
        let mut total = 0i32;
        for &x in &data_clone {
            total += x;
        }
        let _ = total;
    });

    // Mengukur operasi yang tidak bisa di-loop trivially
    struct Timer {
        nama: String,
        mulai: Instant,
    }

    impl Timer {
        fn baru(nama: &str) -> Self {
            Timer {
                nama: nama.to_string(),
                mulai: Instant::now(),
            }
        }
    }

    impl Drop for Timer {
        fn drop(&mut self) {
            println!("[{}] selesai dalam {:?}", self.nama, self.mulai.elapsed());
        }
    }

    // Timer otomatis diprint saat keluar scope
    {
        let _t = Timer::baru("inisialisasi database");
        // simulasi kerja
        std::thread::sleep(Duration::from_millis(50));
    }  // "inisialisasi database: selesai dalam 50ms" tercetak di sini

    {
        let _t = Timer::baru("load konfigurasi");
        std::thread::sleep(Duration::from_millis(20));
    }
}

Formatting dan Parsing Waktu dengan Chrono #

Standard library Rust sengaja tidak menyertakan formatting tanggal dan parsing timezone karena kompleksitasnya. Untuk kebutuhan tersebut, crate chrono adalah pilihan standar di ekosistem Rust.

# Cargo.toml
[dependencies]
chrono = { version = "0.4", features = ["serde"] }
use chrono::{DateTime, Local, Utc, NaiveDate, NaiveDateTime, TimeZone, Duration};

fn main() {
    // Waktu sekarang
    let sekarang_utc: DateTime<Utc> = Utc::now();
    let sekarang_lokal: DateTime<Local> = Local::now();

    println!("UTC: {}", sekarang_utc);
    println!("Lokal: {}", sekarang_lokal);

    // Formatting — menggunakan format string seperti strftime
    println!("{}", sekarang_utc.format("%Y-%m-%d %H:%M:%S"));  // 2024-01-15 10:30:00
    println!("{}", sekarang_lokal.format("%d/%m/%Y"));           // 15/01/2024
    println!("{}", sekarang_utc.format("%A, %B %d, %Y"));       // Monday, January 15, 2024

    // Format RFC 3339 (ISO 8601) — untuk API dan serialisasi
    println!("{}", sekarang_utc.to_rfc3339());  // 2024-01-15T10:30:00+00:00

    // Parsing dari string
    let dari_string: DateTime<Utc> = "2024-01-15T10:30:00Z"
        .parse::<DateTime<Utc>>()
        .expect("Format tidak valid");

    let dari_format = DateTime::parse_from_str(
        "15/01/2024 10:30:00 +0700",
        "%d/%m/%Y %H:%M:%S %z"
    ).expect("Format tidak valid");

    // NaiveDate — tanggal tanpa timezone
    let tanggal = NaiveDate::from_ymd_opt(2024, 1, 15).unwrap();
    println!("{}", tanggal);  // 2024-01-15
    println!("Hari ke-{} dalam tahun ini", tanggal.ordinal());
    println!("Hari dalam seminggu: {}", tanggal.format("%A"));

    // Aritmatika tanggal dengan chrono::Duration
    let besok = tanggal + Duration::days(1);
    let minggu_depan = tanggal + Duration::weeks(1);
    let bulan_depan = tanggal + Duration::days(30);  // chrono tidak punya Duration::months

    println!("Besok: {}", besok);
    println!("Minggu depan: {}", minggu_depan);

    // Komponen tanggal
    use chrono::Datelike;
    println!("Tahun: {}", tanggal.year());
    println!("Bulan: {}", tanggal.month());
    println!("Hari: {}", tanggal.day());

    // Komponen waktu
    use chrono::Timelike;
    let waktu = sekarang_utc;
    println!("Jam: {}", waktu.hour());
    println!("Menit: {}", waktu.minute());
    println!("Detik: {}", waktu.second());
}

Konversi Antara std::time dan Chrono #

use std::time::{SystemTime, UNIX_EPOCH};
use chrono::{DateTime, Utc};

fn main() {
    // SystemTime → chrono DateTime
    let sys_time = SystemTime::now();
    let datetime: DateTime<Utc> = sys_time.into();
    println!("{}", datetime.to_rfc3339());

    // chrono DateTime → SystemTime
    let chrono_time: DateTime<Utc> = Utc::now();
    let sys_time: SystemTime = chrono_time.into();

    // UNIX timestamp → chrono
    let timestamp: i64 = 1_700_000_000;
    let datetime = DateTime::<Utc>::from_timestamp(timestamp, 0)
        .expect("Timestamp tidak valid");
    println!("{}", datetime.format("%Y-%m-%d %H:%M:%S UTC"));

    // chrono → UNIX timestamp
    let ts = Utc::now().timestamp();         // detik
    let ts_ms = Utc::now().timestamp_millis(); // milidetik
    let ts_ns = Utc::now().timestamp_nanos_opt().unwrap(); // nanodetik
    println!("Timestamp: {}", ts);
}

Pola Idiomatik dengan Waktu #

Beberapa pola yang sering muncul saat bekerja dengan waktu di kode Rust produksi.

use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
use std::thread;

fn main() {
    // 1. Rate limiting sederhana
    struct RateLimiter {
        interval: Duration,
        terakhir: Instant,
    }

    impl RateLimiter {
        fn baru(per_detik: u32) -> Self {
            RateLimiter {
                interval: Duration::from_secs(1) / per_detik,
                terakhir: Instant::now() - Duration::from_secs(1),
            }
        }

        fn izinkan(&mut self) -> bool {
            let sekarang = Instant::now();
            if sekarang.duration_since(self.terakhir) >= self.interval {
                self.terakhir = sekarang;
                true
            } else {
                false
            }
        }

        fn tunggu_dan_izinkan(&mut self) {
            let sekarang = Instant::now();
            let lewat = sekarang.duration_since(self.terakhir);
            if lewat < self.interval {
                thread::sleep(self.interval - lewat);
            }
            self.terakhir = Instant::now();
        }
    }

    let mut limiter = RateLimiter::baru(10);  // 10 request per detik
    for i in 0..5 {
        limiter.tunggu_dan_izinkan();
        println!("Request {} diizinkan", i);
    }

    // 2. Cache dengan TTL (Time To Live)
    struct EntriCache<T> {
        nilai: T,
        dibuat: Instant,
        ttl: Duration,
    }

    impl<T> EntriCache<T> {
        fn baru(nilai: T, ttl: Duration) -> Self {
            EntriCache {
                nilai,
                dibuat: Instant::now(),
                ttl,
            }
        }

        fn masih_valid(&self) -> bool {
            self.dibuat.elapsed() < self.ttl
        }

        fn nilai(&self) -> Option<&T> {
            if self.masih_valid() { Some(&self.nilai) } else { None }
        }
    }

    let cache = EntriCache::baru("data dari database", Duration::from_secs(300));
    match cache.nilai() {
        Some(data) => println!("Cache hit: {}", data),
        None => println!("Cache expired, perlu refresh"),
    }

    // 3. Mengukur performa bagian kode tertentu
    struct Stopwatch {
        checkpoints: Vec<(String, Duration)>,
        mulai: Instant,
        terakhir: Instant,
    }

    impl Stopwatch {
        fn mulai() -> Self {
            let sekarang = Instant::now();
            Stopwatch {
                checkpoints: Vec::new(),
                mulai: sekarang,
                terakhir: sekarang,
            }
        }

        fn lap(&mut self, nama: &str) {
            let sekarang = Instant::now();
            self.checkpoints.push((nama.to_string(), sekarang - self.terakhir));
            self.terakhir = sekarang;
        }

        fn cetak_laporan(&self) {
            println!("=== Laporan Performa ===");
            for (nama, durasi) in &self.checkpoints {
                println!("  {}: {:?}", nama, durasi);
            }
            println!("  Total: {:?}", self.mulai.elapsed());
        }
    }

    let mut sw = Stopwatch::mulai();

    // Simulasi tahap-tahap operasi
    thread::sleep(Duration::from_millis(20));
    sw.lap("koneksi database");

    thread::sleep(Duration::from_millis(50));
    sw.lap("query data");

    thread::sleep(Duration::from_millis(10));
    sw.lap("proses hasil");

    sw.cetak_laporan();
    // === Laporan Performa ===
    //   koneksi database: ~20ms
    //   query data: ~50ms
    //   proses hasil: ~10ms
    //   Total: ~80ms

    // 4. Timestamp untuk logging
    fn log(level: &str, pesan: &str) {
        let ts = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .unwrap()
            .as_millis();
        println!("[{}] [{}] {}", ts, level, pesan);
    }

    log("INFO", "Aplikasi dimulai");
    log("WARN", "Koneksi lambat");
    log("ERROR", "Gagal terhubung ke database");
}

sleep dan Presisi Waktu #

thread::sleep adalah cara paling sederhana untuk menunggu, tapi ada beberapa hal yang perlu dipahami tentang presisinya.

use std::thread;
use std::time::{Duration, Instant};

fn main() {
    // sleep tidak dijamin presisi — OS bisa menunda lebih lama
    let diminta = Duration::from_millis(10);
    let mulai = Instant::now();
    thread::sleep(diminta);
    let aktual = mulai.elapsed();
    println!("Diminta: {:?}, Aktual: {:?}", diminta, aktual);
    // Aktual bisa lebih dari diminta, tergantung scheduler OS

    // Spin-wait untuk presisi lebih tinggi (tapi menghabiskan CPU)
    fn sleep_presisi(durasi: Duration) {
        let deadline = Instant::now() + durasi;
        // Tidur sebagian besar waktu dengan sleep biasa
        let batas_spin = duration_from_millis_sat(1);
        if durasi > batas_spin {
            thread::sleep(durasi - batas_spin);
        }
        // Spin untuk sisa waktu
        while Instant::now() < deadline {
            std::hint::spin_loop();  // hint ke CPU bahwa ini busy-wait loop
        }
    }

    let mulai = Instant::now();
    sleep_presisi(Duration::from_millis(10));
    println!("Spin-sleep aktual: {:?}", mulai.elapsed());

    // yield_now — relinquish time slice ke thread lain tanpa tidur
    for _ in 0..1000 {
        thread::yield_now();  // beri kesempatan thread lain berjalan
    }

    // Interval loop yang tidak drift
    fn jalankan_pada_interval(interval: Duration, iterasi: u32) {
        let mut deadline = Instant::now();
        for i in 0..iterasi {
            deadline += interval;
            println!("Iterasi {} pada {:?}", i, Instant::now().elapsed());
            let sekarang = Instant::now();
            if deadline > sekarang {
                thread::sleep(deadline - sekarang);
            }
            // Jika sudah terlambat, langsung lanjut tanpa tidur
        }
    }

    jalankan_pada_interval(Duration::from_millis(50), 5);
}

fn duration_from_millis_sat(ms: u64) -> Duration {
    Duration::from_millis(ms)
}

Ringkasan #

  • Duration untuk interval, Instant untuk pengukuran, SystemTime untuk kalender — ketiganya punya peran berbeda. Mencampurnya adalah sumber bug yang umum.
  • Gunakan Instant::now() untuk mengukur performa — ia monotonic dan tidak terpengaruh perubahan jam sistem. elapsed() selalu berhasil tanpa unwrap.
  • SystemTime bisa mundurduration_since mengembalikan Result bukan Duration karena waktu sistem bisa disetel ulang. Selalu tangani error-nya.
  • Duration::checked_sub dan saturating_sub — hindari panic saat operasi aritmatika Duration bisa menghasilkan nilai negatif. saturating_sub mengembalikan ZERO alih-alih panic.
  • recv_timeout dan try_lock untuk timeout — gunakan Duration sebagai parameter timeout pada operasi blocking seperti channel recv dan Mutex lock.
  • thread::sleep tidak presisi — OS bisa menunda lebih lama dari yang diminta. Untuk aplikasi real-time, gunakan async runtime dengan timer yang lebih presisi, atau spin-wait untuk granularitas microsecond.
  • Gunakan chrono untuk tanggal kalender — formatting, parsing, timezone, dan aritmatika bulan/tahun yang benar. Standard library sengaja tidak menyertakannya karena kompleksitas timezone.
  • Interval loop tanpa drift — gunakan pola deadline += interval bukan sleep(interval). Yang kedua akan drift karena waktu eksekusi kode tidak nol.

← Sebelumnya: Sync   Berikutnya: Process →

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