Tanggal dan Waktu

DateTimeImmutable, DateInterval, dan pemformatan tanggal.

Daftar isi

Pengolahan tanggal dalam PHP ditangani oleh kelas berorientasi objek, yaitu DateTime dan DateTimeImmutable, beserta kelas DateInterval untuk selisih waktu. Topik ini membahas perbedaan perilaku kedua kelas tanggal, cara menambah dan mengurangi waktu dengan interval, perhitungan selisih antara dua tanggal, serta pemformatan tanggal untuk keperluan tampilan. Setelah menyelesaikan topik ini, tanggal jatuh tempo dan jarak waktu antara dua tanggal dapat dihitung dengan kode yang mudah diuji karena seluruh contohnya memakai tanggal tetap.

Objek tanggal yang dapat diubah dan yang tidak#

Kelas DateTime bersifat dapat diubah (mutable), artinya metode seperti add dan modify mengubah nilai objek yang sama. Kelas DateTimeImmutable mengikuti prinsip sebaliknya, yakni setiap metode pengubahan mengembalikan objek baru dan objek aslinya tetap bernilai lama. Perbedaan ini penting karena tanggal yang tidak sengaja berubah nilainya menimbulkan error yang sulit dilacak, sedangkan objek yang tetap nilainya dapat dibagikan ke banyak bagian program dengan aman.

Diagram berikut membandingkan akibat pemanggilan add pada kedua kelas tersebut.

DateTime, dapat diubah$tanggal = 2026-03-15add(P10D)$tanggal = 2026-03-25Objek yang sama berubah nilainya.DateTimeImmutable, tetap$a = 2026-03-15add(P10D)$b = 2026-03-25Objek $a tetap, hasilnya objek baru $b.
Perbandingan perilaku DateTime dan DateTimeImmutable
php
<?php

$mudahUbah = new DateTime('2026-03-15');
$mudahUbah->add(new DateInterval('P10D'));
echo $mudahUbah->format('Y-m-d') . PHP_EOL;

$teguh = new DateTimeImmutable('2026-03-15');
$teguh->add(new DateInterval('P10D'));
echo $teguh->format('Y-m-d') . PHP_EOL;

$baru = $teguh->add(new DateInterval('P10D'));
echo $teguh->format('Y-m-d') . " dan " . $baru->format('Y-m-d') . PHP_EOL;
text Keluaran
2026-03-25
2026-03-15
2026-03-15 dan 2026-03-25

Blok pertama memperlihatkan $mudahUbah berubah menjadi 2026-03-25 karena metode add pada DateTime mengubah objek yang sama. Blok kedua memanggil add pada objek DateTimeImmutable tanpa menampung hasilnya, dan nilainya tetap 2026-03-15 karena hasil pengubahan berada pada objek baru yang tidak dipakai. Blok ketiga menampung hasil tersebut ke variabel $baru, sehingga kedua nilai dapat dipakai bersamaan.

Kedua kelas memiliki metode yang sama dan dapat saling menggantikan pada sebagian besar kode. Pilihan yang lebih aman untuk kode baru adalah DateTimeImmutable, karena tanggal yang tetap nilainya mencegah perubahan tidak disengaja saat objek yang sama dibaca di beberapa tempat. Kelas DateTime masih banyak dipakai pada kode lama, sehingga keduanya tetap perlu dikenali.

Menambah dan mengurangi waktu dengan DateInterval#

Kelas DateInterval menyatakan durasi dengan notasi yang dimulai huruf P diikuti satuan tanggal, sedangkan satuan jam dan seterusnya mengikuti huruf T. Contohnya P10D berarti sepuluh hari, P1M berarti satu bulan, dan PT6H berarti enam jam, sedangkan P1M2D menggabungkan satu bulan dan dua hari dalam satu interval. Interval tersebut diberikan kepada metode add untuk penambahan dan sub untuk pengurangan.

php
<?php

$tanggal = new DateTimeImmutable('2026-03-15');

echo $tanggal->add(new DateInterval('P10D'))->format('Y-m-d') . PHP_EOL;
echo $tanggal->sub(new DateInterval('P7D'))->format('Y-m-d') . PHP_EOL;
echo $tanggal->add(new DateInterval('P1M2D'))->format('Y-m-d') . PHP_EOL;
echo $tanggal->add(new DateInterval('PT6H'))->format('Y-m-d H:i') . PHP_EOL;
text Keluaran
2026-03-25
2026-03-08
2026-04-17
2026-03-15 06:00

Setiap baris memproses tanggal asal 2026-03-15 secara terpisah karena objek asalnya tidak pernah berubah. Interval PT6H menambah enam jam pada pukul 00.00, sehingga hasilnya ditampilkan dengan format Y-m-d H:i menjadi 2026-03-15 06:00.

Metode diff menghitung selisih dua tanggal dan mengembalikan objek DateInterval yang berisi rinciannya. Format %a menampilkan total hari, sedangkan kombinasi %y, %m, dan %d menampilkan selisih yang sudah diuraikan menjadi tahun, bulan, dan hari.

php
<?php

$mulai = new DateTimeImmutable('2026-03-15');
$akhir = new DateTimeImmutable('2026-06-20');
$sisa = $mulai->diff($akhir);

echo $sisa->format('%a hari') . PHP_EOL;
echo $sisa->format('%y tahun, %m bulan, %d hari') . PHP_EOL;
text Keluaran
97 hari
0 tahun, 3 bulan, 5 hari

Perhitungan pada contoh menggabungkan add, diff, dan format dalam satu tugas nyata, yaitu menetapkan tanggal jatuh tempo pinjaman perpustakaan beserta sisa waktunya.

php jatuh-tempo.php
<?php

$pinjam = new DateTimeImmutable('2026-03-10');
$lamaPinjam = new DateInterval('P14D');
$jatuhTempo = $pinjam->add($lamaPinjam);
$perkiraanKembali = new DateTimeImmutable('2026-03-15');

echo 'Dipinjam    : ' . $pinjam->format('d F Y') . PHP_EOL;
echo 'Jatuh tempo : ' . $jatuhTempo->format('d F Y') . PHP_EOL;

$sisa = $jatuhTempo->diff($perkiraanKembali);
echo 'Sisa waktu  : ' . $sisa->format('%a hari') . PHP_EOL;
text Keluaran
Dipinjam    : 10 March 2026
Jatuh tempo : 24 March 2026
Sisa waktu  : 9 hari

Tanggal jatuh tempo diperoleh dengan menambah interval empat belas hari pada tanggal pinjam, kemudian metode diff menghitung jarak antara tanggal jatuh tempo dan perkiraan tanggal kembali. Penggunaan DateTimeImmutable membuat ketiga variabel tanggal saling terpisah, sehingga perubahan pada satu variabel tidak memengaruhi variabel lainnya.

Memformat tanggal dengan format#

Metode format mengubah objek tanggal menjadi string menurut huruf format tertentu. Huruf Y menghasilkan tahun empat digit, m bulan dua digit, d tanggal dua digit, sedangkan H, i, dan s menghasilkan jam, menit, dan detik. Huruf l menghasilkan nama hari dan F menghasilkan nama bulan, sementara j dan n menghasilkan tanggal serta bulan tanpa nol di depan. Nama hari dan bulan mengikuti pengaturan locale, dan tanpa pengaturan keduanya ditulis dalam bahasa Inggris.

php
<?php

$tanggal = new DateTimeImmutable('2026-03-15');

echo $tanggal->format('Y-m-d') . PHP_EOL;
echo $tanggal->format('d/m/Y') . PHP_EOL;
echo $tanggal->format('l, d F Y') . PHP_EOL;
echo $tanggal->format('n-j-Y') . PHP_EOL;

$dariFormulir = DateTimeImmutable::createFromFormat('d/m/Y', '15/03/2026');
echo $dariFormulir->format('Y-m-d') . PHP_EOL;
text Keluaran
2026-03-15
15/03/2026
Sunday, 15 March 2026
3-15-2026
2026-03-15

Dua baris terakhir menunjukkan arah sebaliknya, yaitu membaca string dari sumber luar menjadi objek tanggal melalui metode statis createFromFormat. Parameter pertamanya menyatakan bentuk masukan, sehingga string 15/03/2026 yang tersusun dari tanggal, bulan, lalu tahun dapat dibaca dengan benar. Metode ini penting karena masukan pengguna jarang mengikuti format Y-m-d.

Huruf format peka huruf besar dan kecil, misalnya m menghasilkan angka bulan sedangkan M menghasilkan nama bulan singkat seperti Mar. Rujukan lengkap huruf format terdapat pada dokumentasi format, dan membacanya lebih andal daripada menebak karakternya. Kombinasi dengan tanggal tetap seperti pada contoh membuat setiap keluaran format dapat direproduksi kapan pun.

Kesalahan umum#

Empat kesalahan berikut paling sering muncul saat mengolah tanggal.

  • Hasil add atau sub pada DateTimeImmutable diabaikan karena dianggap objek asalnya ikut berubah. Objek asal memang tetap, sehingga pengubahan terasa tidak berjalan. Perbaikannya adalah menampung nilai kembalian metode tersebut ke variabel baru.
  • new DateTime() dipanggil tanpa argumen pada contoh atau pengujian. Nilai yang dihasilkan mengikuti waktu berjalan, sehingga keluarannya berbeda setiap saat dan tidak dapat direproduksi. Perbaikannya adalah memakai tanggal tetap, misalnya new DateTimeImmutable('2026-03-15'), pada contoh dan pengujian.
  • Nilai kembalian createFromFormat langsung dipanggil dengan format tanpa pemeriksaan. Metode tersebut mengembalikan false apabila string tidak cocok dengan format yang dinyatakan, dan pemanggilan format pada false memicu error fatal. Perbaikannya adalah memeriksa hasilnya dengan === false sebelum dipakai.
  • Huruf format tertukar antara huruf besar dan kecil karena bentuknya mirip, misalnya m dengan M atau d dengan D. Kode tidak menghasilkan error, tetapi bentuk tanggalnya berbeda dari yang diharapkan. Perbaikannya adalah membaca tabel huruf format pada dokumentasi format saat menulis pola baru.

Ringkasan#

  • DateTime mengubah objek yang sama ketika diubah, sedangkan DateTimeImmutable mengembalikan objek baru dan objek asalnya tetap bernilai lama.
  • DateInterval menyatakan durasi dengan notasi P untuk bagian tanggal dan T untuk bagian waktu, serta diberikan kepada metode add dan sub.
  • diff menghitung selisih dua tanggal dan mengembalikan DateInterval yang diformat dengan %a untuk total hari atau %y, %m, %d untuk rinciannya.
  • format mengubah tanggal menjadi string menurut huruf format, sedangkan createFromFormat membaca string luar menjadi objek tanggal menurut format yang dinyatakan.

Referensi#