ADT time
Latihan membuat instruksi pembelajaran untuk Abstract Data Type (ADT) time, dengan implementasi bahasa pemrograman Rust.
Mengenal dan mengimplementasikan Abstract Data Type (ADT) Time (jam:menit:detik) menggunakan Rust sebagai modul terpisah, lalu memakai modul itu dari program utama. Fokusnya: enkapsulasi data (field private), konstruktor, validator, pembacaan dari pengguna, tampilan (display), konversi ke detik (time_to_seconds) dan kebalikan (seconds_to_time).
Tujuan Pembelajaran
Setelah mempelajari modul ini Anda akan mampu:
Menjelaskan apa itu ADT dan mengapa enkapsulasi berguna.
Mengimplementasikan
struct Timedi Rust dengan API publik (metode).Menulis fungsi validasi rentang jam, menit, dan detik.
Membaca input pengguna (loop sampai valid) dan menampilkan waktu dengan format
HH:MM:SS.Mengonversi
Time⇄ detik dengan konsistensi (24 jam wrap-around).Menangani input invalid secara sederhana dan menjelaskan edge cases terkait representasi waktu.
Prasyarat
Dasar Rust:
struct,impl,mod,use,fn main().Membaca dari stdin (
std::io::stdin) dan parsing string ke integer.Pemahaman ringkas tentang integer dan operasi modulo.
Desain API Time secara ringkas
Time::new(h, m, s) -> Time— konstruktor (menganggap input valid).Time::is_valid(h, m, s) -> bool— validator rentang.Time::read_from_stdin() -> Time— baca berulang sampai valid.Time::display(&self)— cetakHH:MM:SS.Time::to_seconds(&self) -> i32— konversi ke detik dari 00:00:00.Time::from_seconds(n: i32) -> Time— konversi detik ke Time (wrap di 24 jam).
Field hours, minutes, seconds dibuat private agar hanya bisa diubah lewat metode — sesuai prinsip ADT (enkapsulasi).
Kode versi yang mudah dipahami
Buat project Rust (jika belum):
cargo new time_adtdemo
cd time_adtdemoBuat file src/time.rs dengan isi berikut:
// src/time.rs
// Modul Time: ADT sederhana untuk jam:menit:detik.
// Ditulis dengan gaya mudah dimengerti untuk pemula.
use std::io::{self, Write};
/// Tipe Time: fields private agar enkapsulasi terjaga.
#[derive(Debug, Clone, Copy)]
pub struct Time {
hours: i32, // 0..23
minutes: i32, // 0..59
seconds: i32, // 0..59
}
impl Time {
/// Konstruktor: asumsi input valid (gunakan is_valid sebelum memanggil jika perlu)
pub fn new(h: i32, m: i32, s: i32) -> Self {
Time { hours: h, minutes: m, seconds: s }
}
/// Validator: periksa rentang jam, menit, detik
pub fn is_valid(h: i32, m: i32, s: i32) -> bool {
(0..=23).contains(&h) && (0..=59).contains(&m) && (0..=59).contains(&s)
}
/// Baca Time dari stdin, ulangi sampai input valid.
/// Input dipisah spasi atau enter: misal "13 5 9" atau input interaktif.
pub fn read_from_stdin() -> Self {
loop {
print!("Masukkan jam menit detik (misal 13 05 09): ");
let _ = io::stdout().flush();
let mut line = String::new();
if io::stdin().read_line(&mut line).is_err() {
eprintln!("Gagal membaca input. Coba lagi.");
continue;
}
let parts: Vec<&str> = line.split_whitespace().collect();
if parts.len() < 3 {
eprintln!("Mohon masukkan tiga nilai: jam menit detik.");
continue;
}
// parsing sederhana; jika gagal, minta ulang
let h = parts[0].parse::<i32>();
let m = parts[1].parse::<i32>();
let s = parts[2].parse::<i32>();
match (h, m, s) {
(Ok(h), Ok(m), Ok(s)) => {
if Time::is_valid(h, m, s) {
return Time::new(h, m, s);
} else {
eprintln!("Nilai tidak valid. Jam 0-23, menit 0-59, detik 0-59.");
}
}
_ => {
eprintln!("Parsing gagal. Pastikan Anda memasukkan angka bulat.");
}
}
}
}
/// Cetak Time format HH:MM:SS (dua digit tiap komponen)
pub fn display(&self) {
println!("{:02}:{:02}:{:02}", self.hours, self.minutes, self.seconds);
}
/// Konversi Time ke total detik sejak 00:00:00
pub fn to_seconds(&self) -> i32 {
self.hours * 3600 + self.minutes * 60 + self.seconds
}
/// Konversi detik ke Time, dengan pembungkusan modulo 86400 (24 jam)
pub fn from_seconds(mut n: i32) -> Self {
const SECONDS_PER_DAY: i32 = 24 * 3600;
// pastikan n di rentang 0..86399; dukung n negatif juga dengan modulo sifatnya
n = ((n % SECONDS_PER_DAY) + SECONDS_PER_DAY) % SECONDS_PER_DAY;
let h = n / 3600;
let rem = n % 3600;
let m = rem / 60;
let s = rem % 60;
Time::new(h, m, s)
}
/// Getter sederhana (jika diperlukan)
pub fn hours(&self) -> i32 { self.hours }
pub fn minutes(&self) -> i32 { self.minutes }
pub fn seconds(&self) -> i32 { self.seconds }
}Lalu buat file src/main.rs:
// src/main.rs
mod time;
use time::Time;
fn main() {
// Baca time dari pengguna
let t1 = Time::read_from_stdin();
print!("Time yang dibaca: ");
t1.display();
// Konversi ke detik
let secs = t1.to_seconds();
println!("Konversi menjadi detik: {}", secs);
// Contoh dari detik -> time (misalnya 5000 detik)
let t2 = Time::from_seconds(5000);
print!("5000 detik sama dengan time: ");
t2.display();
// Contoh lain: handling nilai negatif dan lebih dari sehari
let t3 = Time::from_seconds(-1); // -1 => 23:59:59
print!("Contoh dari -1 detik => ");
t3.display();
let t4 = Time::from_seconds(90_000); // 90000 mod 86400 = 3600 => 01:00:00
print!("Contoh dari 90000 detik => ");
t4.display();
}Penjelasan singkat kode:
Time::read_from_stdin()membaca sebuah baris, mem-parsing tiga angka (jam menit detik). Jika input tidak valid, meminta ulang. Ini mudah bagi pemula (tidak menggunakan errorResultyang lebih advanced).to_seconds()mengubah jam-menit-detik menjadi jumlah detik sejak tengah malam.from_seconds()melakukann % 86400sehingga nilai detik dilipatkan ke rentang 0..86399—berguna bila input detik negatif atau melebihi 24 jam.Field
hours,minutes,secondsdiset private (tidakpub) sehingga pengguna hanya mengakses melalui metode, menjaga invariants ADT.
Penjelasan Konsep ADT & Keputusan Desain
Enkapsulasi: Field dibuat private untuk mencegah pengguna melakukan injeksi nilai invalid tanpa melewati
is_valid. ADT memberikan API publik yang menjaga invariants.Metode
read_from_stdin()disederhanakan agar pemula tidak perlu memahamiResult/error handling kompleks; di aplikasi produksi lebih baik mengembalikanResult<Time, Error>.from_secondsmenggunakan modulo sehingga waktu selalu berada dalam satu hari (24 jam). Ini sesuai definisi ADT di contoh aslinya (C) yang membatasi jam 0..23.
Edge Cases yang perlu diketahui
Input non-angka atau format berbeda: program menolak dan meminta ulang. Untuk format yang berbeda (mis.
13:05:09) perlu parsing tambahan.Nilai di luar rentang:
is_validakan menganggap tidak valid (mis. jam 25). Program akan meminta masukan ulang.Detik negatif:
from_seconds(-1)dipetakan ke23:59:59(menggunakan modulo ringkas yang mendukung negatif). Hal ini berguna bila menghitung selisih waktu.Overflow integer: dengan
i32batasnya ±2 miliar (~68 tahun detik); untuk penggunaan praktis durasi pendek aman. Untuk aplikasi dengan rentang besar gunakani64.Leap seconds: ADT ini tidak menangani detik tambahan (leap second). Jika lingkungan memerlukan akurasi astronomis, desain ADT harus diperluas.
Timezone / DST: ADT ini pure local clock; tidak mempertimbangkan zona waktu atau daylight saving time (DST). Untuk aplikasi dunia nyata, gunakan library waktu yang lengkap (chrono, time crate).
I/O locale: parsing angka mengharapkan pemisah spasi dan titik desimal tidak relevan karena integer; untuk pengguna memasukkan
13,05,09parsing gagal.
Latihan Singkat untuk pembelajaran
Ubah
read_from_stdinagar juga menerima formatHH:MM:SS(mis.09:05:03). Clue: pakaisplit(':')selainsplit_whitespace().Tambahkan metode
add_seconds(&mut self, n: i32)yang menambahkanndetik ke Time (mengupdate self). Clue: ubahto_seconds(), tambahkann, lalufrom_secondsdan set fields.Buat fungsi
duration_between(t1: Time, t2: Time) -> i32yang mengembalikan selisih detik t2 - t1 (bisa negatif). Clue: gunakanto_seconds()lalu selisih.
Pertanyaan Refleksi beserta petunjuk jawaban singkat
Mengapa field
hours/minutes/secondslebih baik dibuat private? Clue / jawaban singkat: agar hanya lewat metode kita bisa memastikan nilai valid; ini menjaga invariant ADT.Apa yang terjadi bila kita langsung membuat
Time { hours: 25, ... }jika field public? Clue / jawaban singkat: nilai invalid bisa tercipta—mengakibatkan perilaku tak terduga ketika mengkonversi ke detik.Kenapa
from_secondsmemakai modulo 86400? Clue / jawaban singkat: untuk memetakannya ke satu hari (24 jam), sehingga detik berlebih atau negatif tetap menghasilkan jam yang valid.Kapan ADT ini tidak cukup untuk aplikasi nyata? Clue / jawaban singkat: jika butuh zona waktu, leap seconds, kalender, atau dukungan waktu mutakhir—gunakan library waktu yang matang (mis.
chronocrate).
Referensi
Materi dan struktur ADT
Timeini mengikuti contoh dan konsep pengajaran ADT pada materi perkuliahan: Sekolah Teknik Elektro dan Informatika, Institut Teknologi Bandung. Contoh ADT Sederhana — ADT time (materi perkuliahan).Untuk pembaca yang ingin memperdalam implementasi waktu nyata/kompleks pada Rust, pertimbangkan dokumentasi crate waktu (mis.
chrono,time) dan buku resmi Rust: The Rust Programming Language.


