Chapter sebelumnya ditutup dengan teka-teki: log mencatat Jan 15, padahal kita orang Indonesia — siapa yang memutuskan tanggal itu ditulis dalam bahasa Inggris? Jawabannya ada dua pengaturan yang sering tertukar: locale mengatur bahasa dan format (nama hari, format angka, urutan sort), sedangkan timezone mengatur jam dinding yang diikuti sistem. Dua-duanya bisa berbeda antar mesin dan dua-duanya menentukan apa yang kita lihat di layar. Chapter ini membedah keduanya satu per satu, dari prioritas variabel lingkungan hingga zona waktu Indonesia yang membentang tiga jam.

Locale: Aturan Bahasa dan Format #

Locale bukan sekadar penerjemah pesan sistem. Satu locale adalah sekelompok aturan yang mengatur bagaimana software memformat hampir semua yang berhadapan dengan manusia:

KategoriYang diatur
LC_CTYPEklasifikasi huruf, huruf besar-kecil
LC_NUMERICpemisah desimal dan ribuan (1.000,50 vs 1000.50)
LC_TIMEnama hari dan bulan, urutan tanggal
LC_COLLATEurutan sort string
LC_MONETARYformat mata uang
LC_MESSAGESbahasa pesan program

Nilai-nilai itu dibaca dari variabel lingkungan dengan urutan prioritas yang ketat: LC_ALL menimpa kategori LC_* satu per satu, dan LANG hanya menjadi nilai bawaan untuk kategori yang variabel LC_*-nya tidak di-set. Perintah locale menampilkan keadaan lengkapnya:

bash
locale

Output yang Dihasilkan:

text
LANG=C.UTF-8
LANGUAGE=
LC_CTYPE="C.UTF-8"
LC_NUMERIC="C.UTF-8"
LC_TIME="C.UTF-8"
LC_COLLATE="C.UTF-8"
LC_MONETARY="C.UTF-8"
LC_MESSAGES="C.UTF-8"
LC_PAPER="C.UTF-8"
LC_NAME="C.UTF-8"
LC_ADDRESS="C.UTF-8"
LC_TELEPHONE="C.UTF-8"
LC_MEASUREMENT="C.UTF-8"
LC_IDENTIFICATION="C.UTF-8"
LC_ALL=C.UTF-8

Tampilan itu memuat tiga lapis informasi yang layak dibaca cermat:

  1. LANG=C.UTF-8: nilai bawaan sistem latihan ini — locale netral C dengan pengodean UTF-8, satu-satunya yang dijamin ada di semua instalasi.
  2. LANGUAGE=: kosong — variabel tambahan milik GNU untuk daftar preferensi bahasa, dipakai oleh program berbasis GNU gettext.
  3. LC_CTYPE="C.UTF-8" dan kawan-kawannya dalam tanda kutip: variabel LC_* ini tidak di-set satu per satu; nilai di dalam kutip adalah nilai efektif yang mereka terima dari LC_ALL. Bandingkan LC_ALL=C.UTF-8 di baris terakhir yang tampil tanpa kutip karena variabelnya memang di-set langsung.

Untuk melihat semua locale yang tersedia di sistem, kita pakai locale -a:

bash
locale -a

Output yang Dihasilkan:

text
C
C.utf8
POSIX

Sistem latihan minimal ini hanya mengenal C, C.utf8, dan POSIX — tiga nama untuk keluarga locale netral yang sama. Desktop dan server yang kita kelola biasanya jauh lebih kaya.

Memasang Locale Baru dengan locale-gen #

Locale tambahan di Debian datang dari paket locales. Caranya: buka file /etc/locale.gen, hapus tanda # di depan baris yang diinginkan (misalnya id_ID.UTF-8 UTF-8), lalu jalankan sudo locale-gen — perintah ini men-generate data locale dari template dan menambahkannya ke daftar locale -a. Cara interaktifnya adalah sudo dpkg-reconfigure locales, sedangkan pengaturan permanen untuk seluruh sistem disimpan di /etc/default/locale.

Setelah id_ID.UTF-8 tersedia, efeknya langsung terasa di semua program yang patuh locale. Berikut contoh tampilan date yang sama dijalankan dengan locale Indonesia:

console
$ LC_ALL=id_ID.UTF-8 date -d "2026-01-15" "+%A, %d %B %Y"
Kamis, 15 Januari 2026

Bandingkan dengan locale C yang menghasilkan Thursday, 15 January 2026 — tanggal yang sama, dinding yang sama, hanya bahasanya yang berganti. Prefix LC_ALL=... di depan perintah berlaku untuk perintah itu saja, pola yang sama dengan TZ= yang akan kita pakai sebentar lagi.

Timezone: zoneinfo dan /etc/localtime #

Zona waktu Linux tidak diambil dari firasat — semuanya berasal dari database IANA yang tersimpan di /usr/share/zoneinfo: satu file biner per zona (misalnya Asia/Jakarta) berisi seluruh aturan sejarahnya, termasuk kapan Indonesia pernah berubah batas zona. Pilihan zona sistem ditandai oleh satu symlink, /etc/localtime, yang menunjuk ke file zona pilihan:

bash
readlink /etc/localtime
ls /usr/share/zoneinfo/Asia/ | grep -E 'Jakarta|Jayapura'

Output yang Dihasilkan:

text
/usr/share/zoneinfo/Etc/UTC
Jakarta
Jayapura

Baris pertama menunjukkan sistem latihan ini berjalan di zona Etc/UTC; di server produksi kita, symlink semacam ini yang kita ganti untuk memindahkan zona. Baris kedua memastikan dua zona Indonesia tersedia di database: Jakarta dan Jayapura. Zona ketiga untuk WITA bernama Makassar — ketiganya tinggal dipilih sesuai wilayah, dan daftar seluruh kota lainnya diperoleh dengan ls /usr/share/zoneinfo/Asia/. Mekanisme symlink ini sudah kita bahas di Symbolic Links dan Hard Links , dan Debian juga menyimpan salinan teks zona di file /etc/timezone sebagai referensi manusia.

Alat resmi systemd untuk mengatur semuanya adalah timedatectl. Berikut contoh tampilan statusnya di server dengan zona Jakarta:

text
               Local time: Thu 2026-01-15 15:30:05 WIB
           Universal time: Thu 2026-01-15 08:30:05 UTC
                 RTC time: Thu 2026-01-15 08:30:05
                Time zone: Asia/Jakarta (WIB, +0700)
System clock synchronized: yes
          NTP service: active
     RTC in local TZ: no

Perhatikan baris Local time dan Universal time: satu momen yang sama, dua jam dinding yang berbeda — persis topik penutup kita. Perintah pengaturannya lugas: timedatectl set-timezone Asia/Jakarta mengganti zona (dan otomatis memperbarui /etc/localtime serta /etc/timezone), timedatectl list-timezones menampilkan semua kandidat, dan timedatectl set-ntp true menyalakan sinkronisasi waktu otomatis. Di container latihan tanpa systemd sebagai PID 1, timedatectl menolak bekerja — persis kelakuan systemctl dan journalctl yang sudah kita jumpai di section Systemd dan Services .

Jam yang Sama, Dinding yang Berbeda #

Indonesia membentang tiga zona: WIB (UTC+7) untuk wilayah barat, WITA (UTC+8) untuk tengah, dan WIT (UTC+9) untuk timur. Satu momen ditampilkan dengan tiga jam dinding — dan date mampu menunjukkan ketiganya sekaligus untuk waktu contoh yang kita kunci:

bash
printf 'UTC:      %s\n' "$(date -u -d '2026-01-15 08:30' '+%F %T')"
printf 'Jakarta:  %s\n' "$(TZ=Asia/Jakarta date -d '2026-01-15 08:30 UTC' '+%F %T %Z')"
printf 'Jayapura: %s\n' "$(TZ=Asia/Jayapura date -d '2026-01-15 08:30 UTC' '+%F %T %Z')"

Output yang Dihasilkan:

text
UTC:      2026-01-15 08:30:00
Jakarta:  2026-01-15 15:30:00 WIB
Jayapura: 2026-01-15 17:30:00 WIT

Bedah ketiga barisnya:

  1. Baris 1: date -u menampilkan waktu dalam UTC — 08:30:00 tanpa zona, karena -u memaksa jam dinding UTC.
  2. Baris 2: prefix TZ=Asia/Jakarta menyetel zona untuk perintah date ini saja, dan sufiks UTC di dalam string tanggal memberi tahu date bahwa 08:30 yang kita tulis adalah jam UTC. Hasil konversinya: 15:30:00 WIB — tujuh jam lebih cepat.
  3. Baris 3: momen yang sama dengan zona Jayapura menghasilkan 17:30:00 WIT, sembilan jam di depan UTC.

Untuk zona yang menetap lebih lama, simpan export TZ=Asia/Jayapura di ~/.bashrc — hanya user itu yang terpengaruh, sistem tetap pada /etc/localtime. Referensi lengkap mekanisme locale ada di locale(7) , format output date di date(1) , dan sub-perintah timedatectl di timedatectl(1) .

Kita kini bisa mengatur jam dinding, tetapi satu pertanyaan masih tersisa: bagaimana sistem menjaga jam itu tetap akurat berhari-hari, dan bagaimana date dipakai untuk menampilkan serta menggeser waktu? Itu tugas chapter berikutnya tentang date dan sinkronisasi waktu NTP.