Help us understand the problem. What is going on with this article?

kylekatarnls/business_dayライブラリのdiffInBusinessDaysメソッドの挙動について

Carbonに組み込んで利用できるPHPライブラリ、business-dayについてです。

diffInBusinessDays という、日数の差を取得するメソッドの境界について調べました。

各サンプルコードは、READMEにあったものをちょちょいと書き換えたものです。

0日と数時間のずれが生じるパターン

ドキュメントにあった、00:00:00 と 23:59:59 を比較するパターンです。
1日の差として計算されます。

$days = Carbon::parse('2019-06-10')->diffInBusinessDays(Carbon::parse('2019-06-10')->endOfDay());
echo "If you ask to leave from 2019-06-10 to 2019-06-10, it will cost to you $days days of paid vacation.\n";

> If you ask to leave from 2019-06-10 to 2019-06-10, it will cost to you 1 days of paid vacation.

完全一致パターン

時刻が完全に一致する場合は、0日と計算されます。

$days = Carbon::parse('2019-06-10')->diffInBusinessDays(Carbon::parse('2019-06-10'));
echo "If you ask to leave from 2019-06-10 to 2019-06-10, it will cost to you $days days of paid vacation.\n";

> If you ask to leave from 2019-06-10 to 2019-06-10, it will cost to you 0 days of paid vacation.

0日と数時間のずれが生じるパターン(負の方向)

ズレが負の方向、-1日などの方向に振れる場合についても確認します。
方向が正でも負でも、絶対値で日数が取得されることがわかります。

$days = Carbon::parse('2019-06-11')->diffInBusinessDays(Carbon::parse('2019-06-10')->endOfDay());
echo "If you ask to leave from 2019-06-11 to 2019-06-10, it will cost to you $days days of paid vacation.\n";

> If you ask to leave from 2019-06-11 to 2019-06-10, it will cost to you 1 days of paid vacation.

境界値を探る

時刻が一致する場合は差分としての日数はインクリメントされず、時刻が少しでも大きくなった場合に、日数がインクリメントされるようです。

つまり、境界線は以下のようになります。

-2 <= x < -1    : 2
-1 <= x < 0     : 1
0               : 0
0 < x <= 1      : 1
1 < x <= 2      : 2

図にすると以下のようになります。

2   1   0   1   2
|---|---|---|---|
≦  ≦  =   ≦  ≦

Carbonの diffInDays メソッドとは境界が異なるようですので、注意しましょう。

$days = Carbon::parse('2019-06-10')->diffInDays(Carbon::parse('2019-06-10')->endOfDay());
echo "If you ask to leave from 2019-06-10 to 2019-06-10, it will cost to you $days days of paid vacation.\n";

> If you ask to leave from 2019-06-10 to 2019-06-10, it will cost to you 0 days of paid vacation.

時刻に関係なく、カレンダー上の日数を比較したい場合は

単純にカレンダー上の日数の差を取得したい場合は、各日時の時刻を合わせて比較すると混乱がなくてよいです。
この方法に気づいてから、日時の比較において考えなければいけないことがグッと減りました。

$from_day = Carbon::parse('2019-06-10');
$to_day = Carbon::parse('2019-06-11')->endOfDay();
$days = (clone $from_day)->setTime(0,0,0)->diffInDays($to_day->setTime(0,0,0));
echo "If you ask to leave from 2019-06-10 to 2019-06-10, it will cost to you $days days of paid vacation.\n";

> If you ask to leave from 2019-06-10 to 2019-06-10, it will cost to you 1 days of paid vacation.

元の時刻が変わってしまうと不都合があるケースが多いので、クローンしたオブジェクトを操作しています。

x-trans
AWS、GCP、Azureの導入設計、環境構築、運用・保守までサポートするエンジニア軍団
https://x-trans.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away