浜松のWEBシステム開発・スマートフォンアプリ開発・RTK-GNSS関連の開発はお任せください
株式会社シーポイントラボ
TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:静岡県浜松市中区富塚町1933-1 佐鳴湖パークタウンサウス2F

【PHP】出勤日、営業日単位で日付の操作をする

 ある程度、時間のかかる作業が積み重なっているときは仕事のスケジュールを立てることが多いはずです(少なくとも自分は必須)。この時、手計算よりもプログラムでスケジュールを計算できると楽ができます。最近あまり使っていませんが Excel では WORKDAY 関数を使うことで出勤日、営業日単位で日付の操作ができます。この記事では PHP を用いてこれを計算する方法を紹介します。
 まずは基本となる平日のみを数える方法です。これは次の様に strtotime 関数に weekday あるいは weekdays という書式を渡すことで実現できます。
PHP: strtotime – Manual
PHP: 相対的な書式 – Manual

<?php

/**
 * 日本らしい表記にして日付を返す
 * @param $timestamp
 * @return string
 */
function date_format_jp($timestamp):string{
    $youbi = [ "日", "月", "火", "水", "木", "金", "土" ];

    return date('Y年m月d日',$timestamp).'('.$youbi[date('w',$timestamp)].")";
}

echo '本日は'. date_format_jp(time())."\n";// 本日は2021年05月12日(水)
echo '平日を5回過ぎた後は'. date_format_jp(strtotime('+5 weekday'))."\n";// 平日を5回過ぎた後は2021年05月19日(水)
echo '平日を7回過ぎた後は'. date_format_jp(strtotime('+7 weekdays'))."\n";// 平日を7回過ぎた後は2021年05月21日(金)
[

 weekday は平日の意の語であり、文字通り平日を数えることができます。
 これに加えて、任意の日付をスキップできるようにしたくなります。これは祝日、創業記念日、設立記念日、有給取得日あたりを考慮した時に欲しくなります。これは次の様に平日をインクリメントする処理と、該当日付のスキップ処理を入れることで実現できます。

<?php

/**
 * 日本らしい表記にして日付を返す
 * @param  int  $timestamp
 * @return string
 */
function timestamp_to_jp_format(int $timestamp): string
{
    $youbi = ["日", "月", "火", "水", "木", "金", "土"];

    return date('Y年m月d日', $timestamp) . '(' . $youbi[date('w', $timestamp)] . ")";
}

/** @var string[] $holidayList 休業日リスト */
$holidayList = [
    '2021-05-14',// 金
    '2021-05-15',// 土
    '2021-05-19',// 水
];
echo '本日から2回目の営業日は' . timestamp_to_jp_format(plus_workday_timestamp(date('Y-m-d'), 2, $holidayList)) . "\n";// 本日から2回目の営業日は2021年05月17日(月)

/**
 * @param  string  $date 起点となる日時。 strtotime で解釈できる文字列
 * @param  int     $days 起点に追加する営業日の数
 * @param  array   $notWorkDays 働かない日のリスト
 * @return int 次営業日のタイムスタンプ
 */
function plus_workday_timestamp(string $date, int $days, array $notWorkDays): int
{
    /** @var int $timestamp 渡された日時文字列をタイムスタンプ化*/
    $timestamp = strtotime($date);
    for($i = $days; $i > 0; $i--) {
        // 要求された日分を満たすまで次営業日、次営業日からそのまた次の営業日へとタイムスタンプを回す
        $timestamp = next_workday_timestamp($timestamp, $notWorkDays);
    }

    return $timestamp;
}

/**
 * @param  int    $timestamp    起点となる日時のタイムスタンプ
 * @param  array  $notWorkDays  祝日などの働かない日
 * @return int 次営業日のタイムスタンプ
 */
function next_workday_timestamp(int $timestamp, array $notWorkDays): int
{
    /** @var int $nextTimestamp 次の平日のタイムスタンプを取得 */
    $nextTimestamp = strtotime(date('Y-m-d H:i:s', $timestamp) . '+ 1 weekday');
    if(!in_array(date('Y-m-d', $nextTimestamp), $notWorkDays, true)) {
        // 次の平日が働かない日に含まれていないのであれば、次の平日をそのまま返す
        return $nextTimestamp;
    }
    // 次の平日が働かない日に含まれているであれば、再帰によって起点を次の平日にして再び次営業日を探しに行く
    // 次の平日が働かない日に含まれるまでループし続ける
    return next_workday_timestamp($nextTimestamp, $notWorkDays);
}

 もし祝日を一律で休み扱いにしたい、といった時には azuyalabs/yasumi の様な日本の祝日を網羅したライブラリを用いて同様の処理を行うと楽です。
azuyalabs/yasumi: The easy PHP Library for calculating holidays

  • この記事いいね! (0)