bashおよびシェルスクリプトで「1000日」形式を2年、9ヶ月、0日形式に変換するKISS方法は何ですか?

bashおよびシェルスクリプトで「1000日」形式を2年、9ヶ月、0日形式に変換するKISS方法は何ですか?

シェルスクリプトで「1000日」などの形式を「2年、9ヶ月、0日」などの形式に変換する「簡単に保つ」方法は何ですか?

モジュラスまたは床丸めを適用することを検討しました。同様の問題を見ましたが、「短い」方向に行くのではなく、すべてを必要以上に複雑にする追加の要件があります。

答え1

そしてdateutils

$ today=$(dseq -f %F now)
$ ddiff -f '%y years, %m months and %d days' "$today" "$(dadd "$today" 1000)"
2 years, 8 months and 26 days

各月の日数が異なるため、開始日(この場合は今日)によって結果が異なります。

一部のシステムでは、他のパッケージの同様の名前のコマンドと区別するために、ユーティリティ名の前に(、、、)dateutilsが付いています。dateutils.dateutils.dseqdateutils.dadddateutils.ddiff

答え2

これらの演算を単純化する場合、整数演算を直接適用すると、おおよその答えを得ることができます。

d=1000           # days interval

yd=365           # days per year
md=$((yd/12))    # days per month

y=$((d/yd))      # years
d=$((d-y*yd))    # remaining days

m=$((d/md))      # months
d=$((d-m*md))    # remaining days

echo y=$y, m=$m, d=$d

出力

y=2, m=9, d=0

テスト目的でこれを(n読み取り不可能な)関数に圧縮してから、いくつかの制限を調べることができます。

ymd() ( d=$1; echo -n "$d ==> "; yd=365; y=$((d/yd)); d=$((d-y*yd)); md=$((yd/12)); m=$((d/md)); d=$((d-m*md)); echo "y=$y, m=$m, d=$d"; )

これにより、次のように希望の答えを得ることができます。

ymd 1000
1000 ==> y=2, m=9, d=0

そして

ymd $((2*365))
730 ==> y=2, m=0, d=0

しかし、1年は12ヶ月30日がないため

ymd $((2*365 -1))
729 ==> y=1, m=12, d=4

関連情報