養育費滞納額の遅延損害金をシミュレーション with python


<img src="https://media.giphy.com/media/ND6xkVPaj8tHO/giphy.gif" width="250">
# 養育費に遅延損害金は発生する？
養育費は金銭債権なので**遅延損害金は発生する**。

>第419条
1. 金銭の給付を目的とする債務の不履行については、その損害賠償の額は、法定利率によって定める。ただし、約定利率が法定利率を超えるときは、約定利率による。
2. 前項の損害賠償については、債権者は、損害の証明をすることを要しない。
3. 第一項の損害賠償については、債務者は、不可抗力をもって抗弁とすることができない。
https://ja.wikibooks.org/wiki/%E6%B0%91%E6%B3%95%E7%AC%AC419%E6%9D%A1


## 愛のコラム『養育費は収入が無ければ払わなくてもいいの？？』

もし相手が **収入に応じて支払うのだから無ければ払えない** と主張してきたとしましょう。
主張するのは自由ですが **請求権は失効しない** さらに **遅延損害金が発生する** ので気をつけましょう。
ちなみに、養育費はたいてい毎月支払うので **定期給付債権** になるそうです。
きっちりと金銭債権は回収していきましょう！
**子供の笑顔のために**。

<img src="https://media.giphy.com/media/xTiTncVep2khPGhK1i/giphy.gif" width="250">



# 法定利率はいくら？
2020年3月31日までは、取り決めがない場合は年5%が上限。（改正前）
2020年4月1日からは、取り決めがない場合は年3％が上限。（改正後）


>第404条
利息を生ずべき債権について別段の意思表示がないときは、その利率は、年五分とする。
https://ja.wikibooks.org/wiki/%E6%B0%91%E6%B3%95%E7%AC%AC404%E6%9D%A1

>民法の一部を改正する法律（債権法改正）について
http://www.moj.go.jp/MINJI/minji06_001070000.html

# どうやって計算する？
<img src="https://media.giphy.com/media/mBY0lSBpDda7G4GqRi/giphy.gif" width="250">
## 必要な情報を整理
利率　　　　　　：　2020年3月31日までは年5%、2020年4月1日からは年3%
1年の日数　　　 ：　通常は365日、うるう年は366日
起算日　　　　　：　支払い期日の翌日
遅延期間　　　　 :　起算日を含めて何年と何日遅延しているか

## ためしに電卓で計算してみる
2018年1月末日までに養育費3万円を支払わなかった場合をレッツシミュレーション！

<img src="https://media.giphy.com/media/3o7btObApReFdPILwk/giphy.gif" width="250">

### 遅延損害金を計算してみる。

<img src="https://media.giphy.com/media/3o7aCZlRncyDOY2JFK/giphy.gif" width="250">
さて、この場合の遅延損害金を計算してみましょう。

計算日　　　　　：　2020年5月17日
利率　　　　　　：　2020年3月31日までは年5%、2020年4月1日からは年3%
1年の日数　　　 ：　通常は365日、うるう年は366日
起算日　　　　　：　2018年2月1日
遅延期間　　　　 :　2年（2018年2月1日〜2020年1月31日）と107日（2020年2月1日〜2020年5月17日）


## ちょっぴり気になるポイント
<img src="https://media.giphy.com/media/8lQyyys3SGBoUUxrUp/giphy.gif" width="250">
### 1.法定利率が途中で変わってる場合は5%と3%のどっちを適用するの？
→起算日が2018年2月1日なので5%で良い。（たぶん）
>金銭の給付を目的とする債務の不履行については、その損害賠償の額は、債務者が遅滞の責任を負った最初の時点における法定利率によって定める。ただし、約定利率が法定利率を超えるときは、約定利率による。

>弁護士 雨のち晴れブログ : 民法419条（金銭債務の特則）民法改正勉強ノート64**
http://blog.livedoor.jp/kosekeito/archives/minpou419jou.html

### 2. うるう年が含まれるときはどう計算するの？
① 2018年2月1日〜2020年1月31日は　30000円　×　0.05　×　2年　＝　3000円
② 2020年2月1日〜2020年5月12日は　30000円　×　0.05　÷　366日　×　107日　＝　438円（端数切捨て）
③ 3000円　＋　438円　＝　3438円

>債務名義，登記(根抵当権の場合は，契約書)に閏年に関する特約の記載がない場合
① 起算日から計算して年に満つる期間は，年利計算する。
② 次に，年に満たない期間は，日割計算する。
③ そして①と②を合算する。

>**利息･損害金の計算について**
https://www.courts.go.jp/okayama/saiban/tetuzuki/s11_2/index.html

# pythonで計算してみよう！
それでは、これをpythonでやってみようー！

<img src="https://media.giphy.com/media/ue5ZwFCaxy64M/giphy.gif" width="250">

## sakiri_kids_money_delinquent_charge_simulator.py

```python:sakiri_kids_money_delinquent_charge_simulator.py
# coding: utf-8
import calendar
import datetime
import math
from dateutil.relativedelta import relativedelta

# 計算日
calculation_date = datetime.date(2020, 5, 17) # Sakiri's 29th birthday

# 養育費
kids_money = 30000

# 起算日
start_date = datetime.date(2018, 2, 1)

# 年利
# 2020年4月1日から法定年利は3%
APY = 0.05 if start_date < datetime.date(2020, 4, 1) else 0.03

# 遅延年数
# relativedeltaは指定した開始日を含めずに計算するため1日ずらす。
years = relativedelta(calculation_date, start_date + datetime.timedelta(days=-1)).years

# 日割り開始日
prorated_start_date = (start_date + relativedelta(years=years))

# 日割り日数
days = (calculation_date - prorated_start_date).days + 1

# 日割り期間にうるう年含まれてる？
is_leap_year_calculation_date = calendar.isleap(calculation_date.year)
is_leap_year_prorated_start_date = calendar.isleap(prorated_start_date.year)
is_leap_year = is_leap_year_calculation_date or is_leap_year_prorated_start_date

# 日割り期間は年をまたぐ？
is_cross_year = prorated_start_date.year != calculation_date.year

# 遅延損害金の計算
delinquent_charge_year = math.floor(kids_money * APY * years) # 遅延損害金（年）
delinquent_charge_days = 0
prorated_days = 0
calculation_days = 0
if is_leap_year and is_cross_year:
    # うるう年あり　年またぎあり

    # 日割り開始日の年分を計算
    # 2021/1/1 - 2020/12/31 = 1
    prorated_days = (datetime.date(prorated_start_date.year + 1, 1, 1) - prorated_start_date).days
    delinquent_charge_days_prorated = math.floor(kids_money * APY / (366 if is_leap_year_prorated_start_date else 365) * prorated_days)

    # 計算日の年分を開始
    # 2020/1/1 - 2020/1/1 + 1 = 1
    calculation_days = (calculation_date - datetime.date(calculation_date.year, 1, 1)).days + 1
    delinquent_charge_days_calculation = math.floor(kids_money * APY / (366 if is_leap_year_calculation_date else 365) * calculation_days)

    # 遅延損害金（日割り）
    delinquent_charge_days = delinquent_charge_days_prorated + delinquent_charge_days_calculation
else:
    # 年またぎなし
    delinquent_charge_days = math.floor(kids_money * APY / (366 if is_leap_year else 365) * days)

# 遅延損害金（合計）
delinquent_charge = delinquent_charge_year + delinquent_charge_days

# 表示
print("計算日: " + calculation_date.strftime('%Y/%m/%d'))
print("起算日: " + start_date.strftime('%Y/%m/%d'))
print("年利: " + str(APY))
print("日割り開始日: " + prorated_start_date.strftime('%Y/%m/%d'))
print("遅延年数: " + str(years))
print("日割り日数: " + str(days))
print("日割り期間にうるう年含まれてる？: " +("はい" if is_leap_year else "いいえ"))
print("日割り期間に年をまたぐ？: " +("はい" if is_cross_year else "いいえ"))
print("遅延損害金（年）: " + str(delinquent_charge_year) + "円")
print("遅延損害金（日割り）: " + str(delinquent_charge_days) + "円")
print("遅延損害金（合計）: " + str(delinquent_charge) + "円")

if is_leap_year and is_cross_year:
    print("== 内訳 ==")
    print("日割り開始日の日数: " + str(prorated_days))
    print("日割り開始日がうるう年？: " +("はい" if is_leap_year_prorated_start_date else "いいえ"))
    print("日割り開始日の年の遅延損害金: " + str(delinquent_charge_days_prorated) + "円")
    print("計算日の日数: " + str(calculation_days))
    print("計算日がうるう年？: " +("はい" if is_leap_year_calculation_date else "いいえ"))
    print("計算日の年の遅延損害金: " + str(delinquent_charge_days_calculation) + "円")
    print("==========")
```

### 実行してみよう！
https://paiza.io/projects/k33PBLmUxXW2Zyg-UYvMRg

```
計算日: 2020/05/17
起算日: 2018/02/01
年利: 0.05
日割り開始日: 2020/02/01
遅延年数: 2
日割り日数: 107
日割り期間にうるう年含まれてる？: はい
日割り期間に年をまたぐ？: いいえ
遅延損害金（年）: 3000円
遅延損害金（日割り）: 438円
遅延損害金（合計）: 3438円
```

あとは関数にしてぐるぐるまわせばOK！！

## sakiri_kids_money_delinquent_charge_simulator_custom.py

<img src="https://media.giphy.com/media/lJNoBCvQYp7nq/giphy.gif" width="250">

```python:sakiri_kids_money_delinquent_charge_simulator_custom.py
# coding: utf-8
import calendar
import datetime
import math
from dateutil.relativedelta import relativedelta

def sakiri_delinquent_charge(calculation_date, kids_money, start_date, print_enabled):
    # 年利
    # 2020年4月1日から法定年利は3%
    APY = 0.05 if start_date < datetime.date(2020, 4, 1) else 0.03

    # 遅延年数
    # relativedeltaは指定した開始日を含めずに計算するため1日ずらす。
    years = relativedelta(calculation_date, start_date + datetime.timedelta(days=-1)).years

    # 日割り開始日
    prorated_start_date = (start_date + relativedelta(years=years))

    # 日割り日数
    days = (calculation_date - prorated_start_date).days + 1

    # 日割り期間にうるう年含まれてる？
    is_leap_year_calculation_date = calendar.isleap(calculation_date.year)
    is_leap_year_prorated_start_date = calendar.isleap(prorated_start_date.year)
    is_leap_year = is_leap_year_calculation_date or is_leap_year_prorated_start_date

    # 日割り期間は年をまたぐ？
    is_cross_year = prorated_start_date.year != calculation_date.year

    # 遅延損害金の計算
    delinquent_charge_year = math.floor(kids_money * APY * years) # 遅延損害金（年）
    delinquent_charge_days = 0
    prorated_days = 0
    calculation_days = 0
    if is_leap_year and is_cross_year:
        # うるう年あり　年またぎあり

        # 日割り開始日の年分を計算
        # 2021/1/1 - 2020/12/31 = 1
        prorated_days = (datetime.date(prorated_start_date.year + 1, 1, 1) - prorated_start_date).days
        delinquent_charge_days_prorated = math.floor(kids_money * APY / (366 if is_leap_year_prorated_start_date else 365) * prorated_days)

        # 計算日の年分を開始
        # 2020/1/1 - 2020/1/1 + 1 = 1
        calculation_days = (calculation_date - datetime.date(calculation_date.year, 1, 1)).days + 1
        delinquent_charge_days_calculation = math.floor(kids_money * APY / (366 if is_leap_year_calculation_date else 365) * calculation_days)

        # 遅延損害金（日割り）
        delinquent_charge_days = delinquent_charge_days_prorated + delinquent_charge_days_calculation
    else:
        # 年またぎなし
        delinquent_charge_days = math.floor(kids_money * APY / (366 if is_leap_year else 365) * days)

    # 遅延損害金（合計）
    delinquent_charge = delinquent_charge_year + delinquent_charge_days

    # 表示
    if print_enabled :
        print("************************************************************")
        title_month = (next_month + relativedelta(months=-1)).strftime('%Y年%m月')
        print(title_month + "分の養育費の遅延損害を計算します…")
        print("計算日: " + calculation_date.strftime('%Y/%m/%d'))
        print("起算日: " + start_date.strftime('%Y/%m/%d'))
        print("年利: " + str(APY))
        print("日割り開始日: " + prorated_start_date.strftime('%Y/%m/%d'))
        print("遅延年数: " + str(years))
        print("日割り日数: " + str(days))
        print("日割り期間にうるう年含まれてる？: " +("はい" if is_leap_year else "いいえ"))
        print("日割り期間に年をまたぐ？: " +("はい" if is_cross_year else "いいえ"))
        print("遅延損害金（年）: " + str(delinquent_charge_year) + "円")
        print("遅延損害金（日割り）: " + str(delinquent_charge_days) + "円")
        print("遅延損害金（合計）: " + str(delinquent_charge) + "円")

        if is_leap_year and is_cross_year:
            print("== 内訳 ==")
            print("日割り開始日の日数: " + str(prorated_days))
            print("日割り開始日がうるう年？: " +("はい" if is_leap_year_prorated_start_date else "いいえ"))
            print("日割り開始日の年の遅延損害金: " + str(delinquent_charge_days_prorated) + "円")
            print("計算日の日数: " + str(calculation_days))
            print("計算日がうるう年？: " +("はい" if is_leap_year_calculation_date else "いいえ"))
            print("計算日の年の遅延損害金: " + str(delinquent_charge_days_calculation) + "円")
            print("==========")

    return delinquent_charge



# 計算日
calculation_date = datetime.date(2020, 5, 17) # Sakiri's 29th birthday
# 養育費
kids_money = 30000
# 起算日
start_date = datetime.date(2018, 2, 1)

total = 0
next_month = start_date
array = []
while True:
    # print_enabledをTrueにすれば詳細を表示
    delinquent_charge = sakiri_delinquent_charge(calculation_date, kids_money, next_month, print_enabled=False)
    total += delinquent_charge
    title_month = (next_month + relativedelta(months=-1)).strftime('%Y年%m月')
    array.append({'key':title_month, 'value':delinquent_charge})
    next_month = next_month + relativedelta(months=1)
    if next_month > calculation_date:
        break

# 表示
print("************************************************************")

print("遅延損害金の合計: " + str(total) + "円")

print("＜月別遅延損害金一覧＞")
for data in array:
    print(data['key'], data['value'],'円')

print("************************************************************")
```


### 実行してみよう！！
https://paiza.io/projects/mItcWZUwE8EpUfIl74VotQ?language=python3

```
************************************************************
遅延損害金の合計: 49027円
＜月別遅延損害金一覧＞
2018年01月 3438 円
2018年02月 3319 円
2018年03月 3192 円
2018年04月 3069 円
2018年05月 2944 円
2018年06月 2821 円
2018年07月 2693 円
2018年08月 2566 円
2018年09月 2443 円
2018年10月 2315 円
2018年11月 2192 円
2018年12月 2065 円
2019年01月 1938 円
2019年02月 1819 円
2019年03月 1692 円
2019年04月 1569 円
2019年05月 1444 円
2019年06月 1321 円
2019年07月 1193 円
2019年08月 1066 円
2019年09月 943 円
2019年10月 815 円
2019年11月 692 円
2019年12月 565 円
2020年01月 438 円
2020年02月 319 円
2020年03月 115 円
2020年04月 41 円
************************************************************
```

遅延損害金が請求できるよ！
やったね！たえちゃん！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617364/26c4a82f-64e9-96cf-8961-4b3a0607ff39.png)


# 課題
業務ではfloatで金額計算は万死に値する。
下記のサイトを参考にDecimalモジュールを利用して精密に計算するようにバージョンアップしてみてね！

[Python] 少数を含む金額計算を正確に行う（decimalモジュールの利用） - YoheiM .NET 
https://www.yoheim.net/blog.php?q=20170805

答え合わせはしません。