PHP

Menghitung hari kerja dengan PHP

Menghitung Hari Kerja dengan PHP

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.

Konsep Dasar Hari Kerja

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:

  • Mengecualikan hari weekend: Biasanya Sabtu dan Minggu.
  • Mengecualikan hari libur nasional: Seperti hari raya, hari kemerdekaan, dan hari libur lainnya yang ditetapkan pemerintah.
  • Menyesuaikan dengan zona waktu lokal: Pastikan perhitungan sesuai dengan zona waktu yang digunakan aplikasi Anda.

Menghitung Hari Kerja Secara Manual dengan PHP

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:

Fungsi Dasar Menghitung Hari Kerja

<?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.

Fungsi yang Mengembalikan Tanggal-tanggal 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);
?>

Menghitung Hari Kerja dengan Mengecualikan Hari Libur

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;
?>

Menghitung Hari Kerja dengan Fungsi yang Lebih Efisien

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);
}
?>

Menggunakan Library Carbon

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.

Instalasi Carbon

composer require nesbot/carbon

Contoh Penggunaan Carbon untuk Hari Kerja

<?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);
?>

Menambah atau Mengurangi Hari Kerja dengan Carbon

<?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)
?>

Carbon dengan Hari Libur Custom

<?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');
?>

Contoh Praktis: Menghitung SLA

<?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);
?>

Contoh Praktis: Menghitung Durasi Proyek

<?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) . '%',
    ];
}
?>

Tips dan Best Practices

  • Simpan hari libur di database: Daripada hardcode hari libur dalam kode, simpan di tabel database agar mudah diperbarui setiap tahun.
  • Cache perhitungan: Jika perhitungan hari kerja sering dilakukan dengan parameter yang sama, cache hasilnya untuk meningkatkan performa.
  • Gunakan timezone yang benar: Pastikan Anda menggunakan timezone yang sesuai dalam aplikasi dengan mengatur date_default_timezone_set().
  • Pertimbangkan hari kerja Sabtu: Di Indonesia, beberapa instansi atau perusahaan juga menghitung hari Sabtu sebagai hari kerja. Sesuaikan fungsi Anda sesuai kebutuhan.
  • Unit testing: Buat unit test untuk memastikan fungsi perhitungan hari kerja Anda bekerja dengan benar, terutama untuk edge case seperti pergantian tahun dan bulan.
  • Dokumentasikan asumsi: Dokumentasikan asumsi yang digunakan dalam perhitungan, misalnya apakah hari Sabtu termasuk hari kerja, apakah hari libur pengganti diperhitungkan, dll.
  • Gunakan library yang teruji: Untuk aplikasi produksi, gunakan library seperti Carbon yang sudah teruji dan memiliki komunitas besar.

Kesimpulan

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.



0 Comments


Leave a Reply

Scroll to Top