あらまし
例えば退職された方が、その会社に何か月在籍していたのかを計算する際に「25ヶ月在籍してた」というのはとても簡単に計算出来るけど、日数まで含めて「24.67ヶ月在籍してた」という計算の仕方は意外とサンプルコードが転がっていないようです。
無ければ作れば良いという事で作成したので誰かの何かの役に立てれば。
考え方
年と月は簡単です。
上記の例では退職日と入社日の差分を取ったうえで"年"は12をかけて"月"と足すだけです。
"日"をどうやって小数点にするかですが、退職日から入社日の差分を取り、退職月の日数を取得して割り算をしています。(1月の場合は31日で割り、2024年2月の場合は29日で割ります)
これをせず雑に30で割ると、小数点以下が若干おかしな事になってしまいます。
……と思ってコード書いて完成したつもりでしたが見直してたらバグがありました。
2/2入社、2/29退職 0.97ヶ月 → OK
2/1入社、2/29退職 1.0ヶ月 → OK
1/31入社、2/29退職 0.93ヶ月 → NG (本来1.03になってほしい)
修正版 考え方
結構困りました。どうやって直したものかと思案していたのですが、
入社した月の在籍日数と退職した月の在籍日数をまとめて足してしまう事自体が駄目でした。よく考えたら
2024年1月は31日まであるので1日あたり約0.0322なのに対して
2024年2月は29日までなので、1日あたり約0.0344となるわけで、月によって1日の重みが異なるのです。
つまり同じ"日"という単位とはいえ、この2つは異なるものなので重みを考慮せずに足したり割ったりしてはいけませんでした。
最初にバグがあったのは、重みを考慮していなかったので最終的に0.0xズレていたのですね。
というわけで別々に計算する事で回避できました。
計算式
(入社月の末日 - 入社日)+1 / 入社月の末日
(退職月の末日 - 退職日) / 退職月の末日
このように入社月と、退職した月の在籍日数を重みを考慮したうえでそれぞれ計算した後に、2つの差を取る事で正確な小数点を出すことができました。
ちなみに、この計算では月の途中で入社して月の途中で退職すると直感と合わない数値が出る事があります。
2023年12月16日入社
2024年1月15日退職の場合は1.0ヶ月在籍した事になります。
2024年1月16日入社
2024年2月15日に退職の場合、1.03ヶ月在籍した事になります。
直感的にはどちらも1.0ヶ月な気がしますが、2月という29日までしか無い月に15日まで在籍していたので1.03になるのは正しい結果です。
サンプルコードは久しぶりにRubyで書きました。
コード
require "date"
#入社日と退職日を設定
nyuusya = [2024,2, 1]
taisyoku = [2024, 2, 29]
#初期化
nyuusya_dt = DateTime.new(nyuusya[0], nyuusya[1], nyuusya[2])
taisyoku_dt = DateTime.new(taisyoku[0], taisyoku[1], taisyoku[2])
#入社月と退職月が何日まであるのか確認(うるう年を含めると28日~31日までありえる)
nyuusya_month_last_day = Date.new(nyuusya[0], nyuusya[1], -1)
taisyoku_month_last_day = Date.new(taisyoku[0], taisyoku[1], -1)
#整数部分(経過月数)
month = ((taisyoku_dt.year - nyuusya_dt.year) * 12) + (taisyoku_dt.month - nyuusya_dt.month)
#小数点部分(端数部分)
days1 = ((nyuusya_month_last_day.day - nyuusya_dt.day)+1) / (nyuusya_month_last_day.day).to_f
days2 = (taisyoku_month_last_day.day - taisyoku_dt.day) / (taisyoku_month_last_day.day).to_f
days = days1 - days2
#小数点第2位で四捨五入する
print "この方の在籍月数は" , (month + days).round(2), "ヶ月です\n"
計算結果のサンプル
nyuusya = [1985,4, 1]
taisyoku = [2024, 3, 31]
この方の在籍月数は468.0ヶ月です
nyuusya = [2024,2, 1]
taisyoku = [2024, 2, 29]
→この方の在籍月数は1.0ヶ月です
nyuusya = [2024,1, 1]
taisyoku = [2024,3, 31]
→この方の在籍月数は3.0ヶ月です
nyuusya = [2024,1, 31]
taisyoku = [2024, 2, 29]
→この方の在籍月数は1.03ヶ月です
nyuusya = [2024,1, 16]
taisyoku = [2024, 2, 15]
→この方の在籍月数は1.03ヶ月です
※なお、小数点第二位で四捨五入なので絶対大丈夫だと思いますが、浮動小数点の演算で丸め誤差が気になる場合はfloorメソッドを使用せず、bigdecimalという浮動小数点数演算ライブラリを使用してください。