tanggal-modern.py

Download
import customtkinter as ctk
import datetime
import tkinter.messagebox as messagebox
from typing import Tuple, Dict

# Konfigurasi tema awal CustomTkinter
ctk.set_appearance_mode("Dark")
ctk.set_default_color_theme("blue")

class AplikasiTanggalLive(ctk.CTk):
    """
    Kelas utama aplikasi GUI menggunakan CustomTkinter dengan paradigma OOP.
    Menampilkan waktu (live) dan tanggal saat ini dalam bahasa Indonesia dengan UI modern.
    """
    def __init__(self) -> None:
        super().__init__()

        # Setup properti window utama
        self.title("Jam & Tanggal Live - Modern UI")
        self.geometry("450x320")
        self.configure(fg_color="#1a1a24")  # Background utama: Midnight Blue
        self.resizable(False, False)

        # Memanggil metode inisialisasi UI
        self._setup_ui()
        
        # Memulai siklus pembaruan waktu secara real-time
        self._jalankan_jam_live()

    def _setup_ui(self) -> None:
        """Membangun dan mengatur tata letak (layout) seluruh elemen UI."""
        
        # Frame Utama: Memberikan efek elevasi dari background window
        self.main_frame = ctk.CTkFrame(
            self, 
            fg_color="#252530",  # Background frame: Charcoal / Dark Grey
            corner_radius=15
        )
        self.main_frame.pack(padx=20, pady=20, fill="both", expand=True)

        # Label Judul (Header)
        self.lbl_header = ctk.CTkLabel(
            self.main_frame,
            text="WAKTU SAAT INI",
            font=("Segoe UI", 14, "bold"),
            text_color="#4DA8DA"  # Aksen warna biru muda
        )
        self.lbl_header.pack(pady=(20, 0))

        # Label Waktu (Jam) - Hierarki tipografi terbesar untuk fokus utama
        self.lbl_waktu = ctk.CTkLabel(
            self.main_frame,
            text="00:00:00",
            font=("Segoe UI", 54, "bold"),
            text_color="#FFFFFF"
        )
        self.lbl_waktu.pack(pady=(5, 0))

        # Label Tanggal (Teks sekunder)
        self.lbl_tanggal = ctk.CTkLabel(
            self.main_frame,
            text="Memuat tanggal...",
            font=("Segoe UI", 16),
            text_color="#A0A0B0"  # Warna abu-abu terang agar kontras tetap nyaman
        )
        self.lbl_tanggal.pack(pady=(0, 25))

        # Frame pembungkus untuk tombol-tombol agar presisi
        self.btn_frame = ctk.CTkFrame(self.main_frame, fg_color="transparent")
        self.btn_frame.pack(pady=(0, 20))

        # Primary Button: Tombol Salin Info
        self.btn_copy = ctk.CTkButton(
            self.btn_frame,
            text="Salin Teks",
            font=("Segoe UI", 14, "bold"),
            fg_color="#0066CC",
            hover_color="#004C99",
            corner_radius=8,
            command=self._salin_ke_clipboard
        )
        self.btn_copy.grid(row=0, column=0, padx=10)

        # Secondary Button: Tombol Tutup
        self.btn_close = ctk.CTkButton(
            self.btn_frame,
            text="Tutup",
            font=("Segoe UI", 14, "bold"),
            fg_color="#4A4A5A",
            hover_color="#3A3A4A",
            corner_radius=8,
            command=self.destroy
        )
        self.btn_close.grid(row=0, column=1, padx=10)

    def _dapatkan_waktu_indo(self) -> Tuple[str, str]:
        """Logika backend untuk mengambil waktu sistem dan menerjemahkan ke bahasa Indonesia."""
        nama_hari: Dict[str, str] = {
            'Monday': 'Senin', 'Tuesday': 'Selasa', 'Wednesday': 'Rabu',
            'Thursday': 'Kamis', 'Friday': 'Jumat', 'Saturday': 'Sabtu', 'Sunday': 'Minggu'
        }
        
        nama_bulan: Dict[int, str] = {
            1: 'Januari', 2: 'Februari', 3: 'Maret', 4: 'April', 5: 'Mei', 6: 'Juni',
            7: 'Juli', 8: 'Agustus', 9: 'September', 10: 'Oktober', 11: 'November', 12: 'Desember'
        }

        sekarang = datetime.datetime.now()
        
        hari_en = sekarang.strftime("%A")
        hari_id = nama_hari.get(hari_en, hari_en)
        tanggal = sekarang.day
        bulan_id = nama_bulan.get(sekarang.month, str(sekarang.month))
        tahun = sekarang.year
        
        teks_waktu = sekarang.strftime("%H:%M:%S")
        teks_tanggal = f"{hari_id}, {tanggal} {bulan_id} {tahun}"

        return teks_waktu, teks_tanggal

    def _jalankan_jam_live(self) -> None:
        """Memperbarui label waktu dan tanggal setiap 1000 milidetik (1 detik)."""
        try:
            waktu_baru, tanggal_baru = self._dapatkan_waktu_indo()
            
            # Update teks pada UI
            self.lbl_waktu.configure(text=waktu_baru)
            self.lbl_tanggal.configure(text=tanggal_baru)
            
            # Looping pemanggilan fungsi ini sendiri setelah 1000 ms
            self.after(1000, self._jalankan_jam_live)
            
        except Exception as e:
            self.lbl_tanggal.configure(text="Error sistem.", text_color="#FF4C4C")
            print(f"Error pada loop waktu: {e}")

    def _salin_ke_clipboard(self) -> None:
        """Menyalin teks waktu dan tanggal saat ini ke clipboard sistem."""
        waktu, tanggal = self._dapatkan_waktu_indo()
        teks_salinan = f"{waktu} - {tanggal}"
        
        self.clipboard_clear()
        self.clipboard_append(teks_salinan)
        self.update() # Memastikan clipboard terupdate di beberapa OS
        
        # Feedback visual singkat untuk pengguna
        self.btn_copy.configure(text="Tersalin!", fg_color="#28A745", hover_color="#218838")
        self.after(2000, lambda: self.btn_copy.configure(text="Salin Teks", fg_color="#0066CC", hover_color="#004C99"))

# Titik masuk program (Entry point)
if __name__ == "__main__":
    app = AplikasiTanggalLive()
    app.mainloop()