Dalam pengembangan aplikasi web, seringkali kita perlu menghitung hari kerja antara dua tanggal. Misalnya, untuk menghitung tenggat waktu proyek, estimasi pengiriman barang, SLA (Service Level Agreement), atau durasi pengerjaan tugas. Perhitungan hari kerja berbeda dengan perhitungan hari kalender biasa karena kita perlu mengecualikan hari Sabtu, Minggu, dan hari libur nasional. Dalam artikel ini, kita akan membahas berbagai cara menghitung hari kerja menggunakan PHP, dari cara manual hingga menggunakan library Carbon.
Hari kerja (business days atau working days) adalah hari-hari dalam seminggu yang dianggap sebagai hari aktivitas bisnis, yaitu hari Senin sampai Jumat. Namun, di beberapa negara seperti Indonesia, hari kerja bisa juga mencakup hari Sabtu atau bahkan hanya Senin sampai Jumat. Dalam perhitungan hari kerja, kita perlu:
Cara paling dasar untuk menghitung hari kerja adalah dengan melakukan iterasi pada setiap hari antara dua tanggal dan menghitung hari-hari yang bukan weekend. Berikut adalah implementasinya:
<?php
function hitungHariKerja($tanggalMulai, $tanggalSelesai) {
$start = new DateTime($tanggalMulai);
$end = new DateTime($tanggalSelesai);
$hariKerja = 0;
while ($start <= $end) {
$dayOfWeek = (int) $start->format('N');
// 1 = Senin, 5 = Jumat, 6 = Sabtu, 7 = Minggu
if ($dayOfWeek < 6) {
$hariKerja++;
}
$start->modify('+1 day');
}
return $hariKerja;
}
// Contoh penggunaan
$tanggalMulai = '2024-01-01';
$tanggalSelesai = '2024-01-31';
echo "Jumlah hari kerja: " . hitungHariKerja($tanggalMulai, $tanggalSelesai);
// Output: Jumlah hari kerja: 23
?>
Pada contoh di atas, kita menggunakan class DateTime bawaan PHP untuk memanipulasi tanggal. Metode format('N') mengembalikan nomor hari dalam seminggu (1 untuk Senin sampai 7 untuk Minggu). Dengan memeriksa apakah nomor hari kurang dari 6, kita dapat menentukan apakah hari tersebut merupakan hari kerja.
<?php
function getTanggalHariKerja($tanggalMulai, $tanggalSelesai) {
$start = new DateTime($tanggalMulai);
$end = new DateTime($tanggalSelesai);
$hariKerja = [];
while ($start <= $end) {
$dayOfWeek = (int) $start->format('N');
if ($dayOfWeek < 6) {
$hariKerja[] = $start->format('Y-m-d');
}
$start->modify('+1 day');
}
return $hariKerja;
}
$tanggalKerja = getTanggalHariKerja('2024-01-01', '2024-01-15');
print_r($tanggalKerja);
?>
Untuk perhitungan yang lebih akurat, kita perlu mengecualikan hari libur nasional. Berikut adalah fungsi yang memperhitungkan hari libur:
<?php
function hitungHariKerjaDenganLibur($tanggalMulai, $tanggalSelesai, $hariLibur = []) {
$start = new DateTime($tanggalMulai);
$end = new DateTime($tanggalSelesai);
$hariKerja = 0;
// Konversi array hari libur ke format yang konsisten
$liburFormatted = array_map(function($date) {
return (new DateTime($date))->format('Y-m-d');
}, $hariLibur);
while ($start <= $end) {
$dayOfWeek = (int) $start->format('N');
$currentDate = $start->format('Y-m-d');
// Cek apakah bukan weekend DAN bukan hari libur
if ($dayOfWeek < 6 && !in_array($currentDate, $liburFormatted)) {
$hariKerja++;
}
$start->modify('+1 day');
}
return $hariKerja;
}
// Daftar hari libur nasional Indonesia 2024
$hariLibur = [
'2024-01-01', // Tahun Baru
'2024-02-08', // Isra Mikraj
'2024-02-10', // Tahun Baru Imlek
'2024-03-11', // Nyepi
'2024-03-29', // Wafat Isa Almasih
'2024-04-10', // Hari Raya Idul Fitri
'2024-04-11', // Hari Raya Idul Fitri
'2024-05-01', // Hari Buruh
'2024-05-09', // Kenaikan Isa Almasih
'2024-05-23', // Hari Raya Waisak
'2024-06-01', // Hari Lahir Pancasila
'2024-06-17', // Hari Raya Idul Adha
'2024-07-07', // Tahun Baru Islam
'2024-08-17', // Kemerdekaan RI
'2024-09-16', // Maulid Nabi
'2024-12-25', // Natal
];
$tanggalMulai = '2024-01-01';
$tanggalSelesai = '2024-12-31';
$hariKerja = hitungHariKerjaDenganLibur($tanggalMulai, $tanggalSelesai, $hariLibur);
echo "Jumlah hari kerja di 2024: " . $hariKerja;
?>
Untuk perhitungan yang lebih efisien, terutama untuk rentang tanggal yang sangat panjang, kita dapat menggunakan pendekatan matematis:
<?php
function hitungHariKerjaEfisien($tanggalMulai, $tanggalSelesai, $hariLibur = []) {
$start = new DateTime($tanggalMulai);
$end = new DateTime($tanggalSelesai);
// Hitung total hari
$totalHari = (int) $start->diff($end)->days + 1;
// Hitung jumlah minggu lengkap
$jumlahMinggu = intdiv($totalHari, 7);
$sisaHari = $totalHari % 7;
// Hitung hari kerja dari minggu lengkap
$hariKerja = $jumlahMinggu * 5;
// Hitung hari kerja dari sisa hari
$startDay = (int) $start->format('N');
for ($i = 0; $i < $sisaHari; $i++) {
$currentDay = ($startDay + $i - 1) % 7 + 1;
if ($currentDay < 6) {
$hariKerja++;
}
}
// Kurangi hari libur yang jatuh pada hari kerja
foreach ($hariLibur as $libur) {
$liburDate = new DateTime($libur);
if ($liburDate >= $start && $liburDate <= $end) {
$dayOfWeek = (int) $liburDate->format('N');
if ($dayOfWeek < 6) {
$hariKerja--;
}
}
}
return max(0, $hariKerja);
}
?>
Carbon adalah library manipulasi tanggal yang sangat populer di ekosistem PHP, terutama dalam framework Laravel. Carbon menyediakan metode built-in yang sangat mudah digunakan untuk menghitung hari kerja.
composer require nesbot/carbon
<?php
use CarbonCarbon;
use CarbonCarbonPeriod;
// Menghitung hari kerja antara dua tanggal
$start = Carbon::parse('2024-01-01');
$end = Carbon::parse('2024-01-31');
// Cara 1: Menggunakan isWeekday()
$hariKerja = 0;
$period = CarbonPeriod::create($start, $end);
foreach ($period as $date) {
if ($date->isWeekday()) {
$hariKerja++;
}
}
echo "Hari kerja: " . $hariKerja;
// Cara 2: Menggunakan filter
$weekdays = CarbonPeriod::create($start, $end)
->filter(function ($date) {
return $date->isWeekday();
});
echo "Hari kerja: " . iterator_count($weekdays);
?>
<?php
use CarbonCarbon;
// Menambah 5 hari kerja dari tanggal tertentu
$tanggal = Carbon::parse('2024-01-15');
$tambahHariKerja = $tanggal->addWeekdays(5);
echo "5 hari kerja dari 15 Jan: " . $tambahHariKerja->format('Y-m-d');
// Mengurangi 3 hari kerja
$tanggal = Carbon::parse('2024-01-15');
$kurangHariKerja = $tanggal->subWeekdays(3);
echo "3 hari kerja sebelum 15 Jan: " . $kurangHariKerja->format('Y-m-d');
// Mendapatkan hari kerja berikutnya (bukan weekend)
$tanggal = Carbon::parse('2024-01-13'); // Sabtu
$nextBusinessDay = $tanggal->nextBusinessDay();
echo "Hari kerja berikutnya: " . $nextBusinessDay->format('Y-m-d');
// Output: 2024-01-15 (Senin)
?>
<?php
use CarbonCarbon;
use CarbonCarbonPeriod;
class BusinessDayCalculator {
private $holidays = [];
public function __construct(array $holidays = []) {
$this->holidays = array_map(function ($date) {
return Carbon::parse($date)->format('Y-m-d');
}, $holidays);
}
public function isBusinessDay(Carbon $date): bool {
return $date->isWeekday() &&
!in_array($date->format('Y-m-d'), $this->holidays);
}
public function countBusinessDays(Carbon $start, Carbon $end): int {
$count = 0;
$period = CarbonPeriod::create($start, $end);
foreach ($period as $date) {
if ($this->isBusinessDay($date)) {
$count++;
}
}
return $count;
}
public function addBusinessDays(Carbon $date, int $days): Carbon {
$result = $date->copy();
while ($days > 0) {
$result->addDay();
if ($this->isBusinessDay($result)) {
$days--;
}
}
return $result;
}
public function getNextBusinessDay(Carbon $date): Carbon {
$result = $date->copy();
do {
$result->addDay();
} while (!$this->isBusinessDay($result));
return $result;
}
}
// Contoh penggunaan
$holidays = [
'2024-01-01', '2024-02-10', '2024-03-11',
'2024-04-10', '2024-04-11', '2024-05-01',
'2024-08-17', '2024-12-25',
];
$calculator = new BusinessDayCalculator($holidays);
$start = Carbon::parse('2024-01-01');
$end = Carbon::parse('2024-01-31');
echo "Hari kerja Januari 2024: " . $calculator->countBusinessDays($start, $end);
$tenggat = $calculator->addBusinessDays(Carbon::parse('2024-01-15'), 10);
echo "
10 hari kerja dari 15 Jan: " . $tenggat->format('Y-m-d');
?>
<?php
function hitungSLA($tanggalLaporan, $hariSLA, $hariLibur = []) {
$start = Carbon::parse($tanggalLaporan);
$calculator = new BusinessDayCalculator($hariLibur);
$endDate = $calculator->addBusinessDays($start, $hariSLA);
return [
'tanggal_laporan' => $start->format('Y-m-d'),
'hari_sla' => $hariSLA,
'tanggal_deadline' => $endDate->format('Y-m-d'),
'hari_kerja' => $hariSLA,
];
}
// Contoh: SLA 5 hari kerja
$result = hitungSLA('2024-01-15', 5, ['2024-01-17']);
print_r($result);
?>
<?php
function hitungDurasiProyek($tanggalMulai, $tanggalSelesai, $hariLibur = []) {
$calculator = new BusinessDayCalculator($hariLibur);
$start = Carbon::parse($tanggalMulai);
$end = Carbon::parse($tanggalSelesai);
$totalHari = $start->diffInDays($end) + 1;
$hariKerja = $calculator->countBusinessDays($start, $end);
$hariLiburTerhitung = $totalHari - $hariKerja -
($totalHari - $hariKerja - count(array_filter($hariLibur, function($d) use ($start, $end) {
$date = Carbon::parse($d);
return $date->between($start, $end) && $date->isWeekday();
})));
return [
'tanggal_mulai' => $start->format('Y-m-d'),
'tanggal_selesai' => $end->format('Y-m-d'),
'total_hari' => $totalHari,
'hari_kerja' => $hariKerja,
'hari_libur' => $totalHari - $hariKerja,
'persentase_hari_kerja' => round(($hariKerja / $totalHari) * 100, 1) . '%',
];
}
?>
date_default_timezone_set().Menghitung hari kerja dengan PHP dapat dilakukan dengan berbagai cara, dari perhitungan manual menggunakan class DateTime bawaan PHP hingga menggunakan library Carbon yang menyediakan fitur yang lebih lengkap dan mudah digunakan. Pemilihan metode tergantung pada kebutuhan proyek Anda. Untuk perhitungan sederhana, fungsi manual sudah cukup. Namun, untuk aplikasi yang lebih kompleks dengan kebutuhan manipulasi tanggal yang beragam, Carbon adalah pilihan yang sangat baik. Pastikan selalu memperhitungkan hari libur dan menggunakan timezone yang benar untuk hasil yang akurat.