Data waktu jarang datang sebagai object datetime. Ia datang sebagai teks: “15/06/2025” pada baris file CSV, “2025-06-15T10:30:00” pada respons API, atau “15 Juni 2025” yang diketik pengguna pada form. Chapter ini membahas dua arah transformasinya — formatting (object datetime menjadi teks) dan parsing (teks menjadi object datetime) — memakai pasangan method strftime()/strptime(), standar ISO 8601 lewat fromisoformat(), serta cara menghasilkan teks tanggal bergaya Indonesia.

Formatting dengan strftime #

Method strftime() menerima satu argumen berupa format string yang diisi directive — placeholder yang diawali tanda persen. Berikut directive yang paling sering dipakai, dinilai terhadap tanggal 15 Juni 2025 pukul 10:30:

DirectiveMaknaContoh hasil
%Ytahun empat digit2025
%mbulan dua digit06
%dtanggal dua digit15
%Hjam, format 24 jam10
%Mmenit dua digit30
%Sdetik dua digit00
%Anama hari lengkapSunday
%Bnama bulan lengkapJune
%Ijam, format 12 jam10
%ppenanda AM/PMAM
python
from datetime import datetime

rapat = datetime(2025, 6, 15, 10, 30)

print(rapat.strftime("%Y-%m-%d"))
print(rapat.strftime("%d/%m/%Y %H:%M"))
print(rapat.strftime("%A, %d %B %Y, pukul %H:%M"))
print(rapat.strftime("%I:%M %p"))

Output yang Dihasilkan:

text
2025-06-15
15/06/2025 10:30
Sunday, 15 June 2025, pukul 10:30
10:30 AM

Mari kita telaah apa yang terjadi pada baris-baris kode di atas:

  1. Baris 5 (strftime("%Y-%m-%d")): setiap directive diganti dengan nilai komponen milik rapat, sedangkan tanda hubung di antara directive dicetak apa adanya.
  2. Baris 6: directive boleh dicampur teks dan tanda baca lain sesuai kebutuhan, termasuk dipakai lebih dari sekali dalam satu format.
  3. Baris 7 (%A dan %B): nama hari dan bulan diambil dari pustaka C dalam bahasa Inggris — perilaku bawaan yang kita atasi pada bagian terakhir chapter ini.

Parsing dengan strptime #

Method strptime() bekerja ke arah sebaliknya: membaca teks beserta formatnya, lalu mengembalikan object datetime. Daftar directive yang dipakai sama persis dengan strftime():

python
from datetime import datetime

teks = "15/06/2025 10:30"
rapat = datetime.strptime(teks, "%d/%m/%Y %H:%M")

print(rapat)
print(type(rapat).__name__)

Output yang Dihasilkan:

text
2025-06-15 10:30:00
datetime

Pada baris ke-4, datetime.strptime() — sebuah classmethod — menerima dua argumen: teks mentah dan format yang menjelaskan susunannya. Interpreter Python mencocokkan teks dengan format karakter per karakter: %d menelan “15”, garis miring dicocokkan langsung, %m menelan “06”, dan seterusnya. Komponen yang tidak disebut format diisi nilai bawaan — pada contoh di atas detik menjadi 00.

Pasangan kedua method ini mendukung round-trip: teks hasil strftime() dapat dipulihkan menjadi object bernilai identik:

python
from datetime import datetime

asli = datetime(2025, 6, 15, 10, 30)
teks = asli.strftime("%A %d %B %Y %H:%M")
kembali = datetime.strptime(teks, "%A %d %B %Y %H:%M")

print(teks)
print(kembali == asli)

Output yang Dihasilkan:

text
Sunday 15 June 2025 10:30
True

Ketika Parsing Gagal #

Format string harus cocok dengan teks secara ketat. Simpan kode berikut sebagai parse_rapat.py, lalu jalankan dengan python3 parse_rapat.py:

python
from datetime import datetime

teks = "15-06-2025 10:30"
rapat = datetime.strptime(teks, "%d/%m/%Y %H:%M")

print(rapat)

Output yang Dihasilkan (dicetak interpreter Python ke stderr):

text
Traceback (most recent call last):
  File "parse_rapat.py", line 4, in <module>
    rapat = datetime.strptime(teks, "%d/%m/%Y %H:%M")
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../python3.12/_strptime.py", line 653, in _strptime_datetime
    tt, fraction, gmtoff_fraction = _strptime(data_string, format)
                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../python3.12/_strptime.py", line 432, in _strptime
    raise ValueError("time data %r does not match format %r" %
ValueError: time data '15-06-2025 10:30' does not match format '%d/%m/%Y %H:%M'

Teks memakai tanda hubung sebagai pemisah tanggal, sementara format mengharapkan garis miring — interpreter Python menolak menebak dan membangkitkan ValueError. Selain ketidakcocokan format, tanggal mustahil juga ditolak meski formatnya benar:

python
from datetime import datetime

try:
    rapat = datetime.strptime("31/02/2025", "%d/%m/%Y")
except ValueError as galat:
    print("Input tidak valid:", galat)

Output yang Dihasilkan:

text
Input tidak valid: day is out of range for month

Format ISO 8601 dengan fromisoformat #

Untuk teks berformat ISO 8601 — standar 2025-06-15T10:30:00 — classmethod fromisoformat() jauh lebih ringkas karena tidak butuh format string:

python
from datetime import datetime

a = datetime.fromisoformat("2025-06-15T10:30:00")
b = datetime.fromisoformat("2025-06-15 10:30:00")
c = datetime.fromisoformat("2025-06-15T10:30:00+07:00")

print(a)
print(a == b)
print(c.isoformat())

Output yang Dihasilkan:

text
2025-06-15 10:30:00
True
2025-06-15T10:30:00+07:00

Huruf T pada string pertama adalah pemisah standar antara tanggal dan jam versi ISO 8601; sejak Python 3.11, fromisoformat() juga menerima variasi lain seperti spasi sebagai pemisah (string kedua), format tanpa pemisah seperti "20250615T1030", serta akhiran "Z" untuk UTC. Offset +07:00 pada string ketiga otomatis menghasilkan object aware sesuai materi Chapter Timezone-Aware datetime. Teks yang bukan ISO 8601 ditolak dengan pesan yang jelas:

python
from datetime import datetime

try:
    print(datetime.fromisoformat("15/06/2025"))
except ValueError as galat:
    print("Gagal parsing:", galat)

Output yang Dihasilkan:

text
Gagal parsing: Invalid isoformat string: '15/06/2025'

Format Tanggal Gaya Indonesia Tanpa locale #

Directive %A dan %B selalu menghasilkan bahasa Inggris karena keduanya dibaca dari pustaka C. Solusi tanpa dependensi apa pun adalah memetakan nama hari dan bulan secara manual lewat dictionary:

python
from datetime import datetime

NAMA_HARI = {
    "Monday": "Senin", "Tuesday": "Selasa", "Wednesday": "Rabu",
    "Thursday": "Kamis", "Friday": "Jumat", "Saturday": "Sabtu",
    "Sunday": "Minggu",
}
NAMA_BULAN = {
    1: "Januari", 2: "Februari", 3: "Maret", 4: "April",
    5: "Mei", 6: "Juni", 7: "Juli", 8: "Agustus",
    9: "September", 10: "Oktober", 11: "November", 12: "Desember",
}

def format_indonesia(dt):
    hari = NAMA_HARI[dt.strftime("%A")]
    bulan = NAMA_BULAN[dt.month]
    return f"{hari}, {dt.day} {bulan} {dt.year}"

print(format_indonesia(datetime(2025, 6, 15, 10, 30)))

Output yang Dihasilkan:

text
Minggu, 15 Juni 2025

Mari kita telaah function format_indonesia:

  1. Baris pertama (NAMA_HARI[dt.strftime("%A")]): mengambil nama hari Inggris dari strftime(), lalu menerjemahkannya lewat dictionary NAMA_HARI.
  2. Baris kedua (NAMA_BULAN[dt.month]): mengambil nama bulan langsung dari atribut numerik month melalui dictionary NAMA_BULAN.
  3. Baris ketiga: merangkai hasilnya dengan f-string — materi Chapter f-strings — menjadi format Indonesia yang akrab bagi pengguna.

Pendekatan manual ini memberi kendali penuh, tetapi menuntut kita mengelola daftar terjemahan sendiri. Dua alternatif lain — module locale yang bergantung pada sistem operasi dan pustaka babel — kita bandingkan pada Chapter Locale dan Formatting.