![计算付款天数](https://linux22.com/image/107084/%E8%AE%A1%E7%AE%97%E4%BB%98%E6%AC%BE%E5%A4%A9%E6%95%B0.png)
我需要显示距离即将到来的付款日还有多少天(假设它总是在任何一个月的 10 日)。
我如何在 bash 中做到这一点?
答案1
虽然bash
现在具有日期格式化功能,但它没有日期解析或计算功能,因此您可能需要使用其他 shell,例如ksh93
orzsh
或适当的编程语言,例如perl
or python
。
对于ksh93
,困难的部分是找出支持哪些日期格式,因为它几乎没有记录(您可以随时查看测试数据尽管举个例子)。
例如,它确实支持类似 crontab 的时间规范,然后为您提供下一次与规范匹配的时间,因此您可以执行以下操作:
now=$(printf '%(%s)T')
next_10th=$(printf '%(%s)T' '* * 10 * *')
echo "Pay day is in $(((next_10th - now) / 86400)) days"
现在有了标准实用程序,实现起来就不那么困难了:
eval "$(date '+day=%d month=%m year=%Y')"
day=${day#0} month=${month#0}
if [ "$day" -le 10 ]; then
delta=$((10 - day))
else
case $month in
[13578]|10|12) D=31;;
2) D=$((28 + (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))));;
*) D=30;;
esac
delta=$((D - day + 10))
fi
echo "Pay day is in $delta days"
答案2
dom = 一个月中的哪一天
dom=6 ; \
days=$[ ${dom}-$(date +%-d) ] ; \
[ ${days} -lt 0 ] && days=$[ ${days} + $(date +%d -d "$(date +%Y%m01 -d 'next month') yesterday") ] ; \
echo ${days} days
30 days
答案3
echo $(expr '(' $(date -d 2017/03/10 +%s) - $(date +%s) + 86399 ')' / 86400) "days for my payment"
3 days for my payment
答案4
$td
我们只需从所选的预期发薪日中减去当前日期(今天)。
如果发薪日大于当前日期,则结果将为正且正确。
例如 td=8 和 pd=15:
$ td=8; pd=15
$ echo "The next PayDay will be in $((pd-td)) days"
7
如果结果为负,我们只需添加当月的天数。
执行该操作的脚本可能是:
#!/bin/bash
pd=${1:-10} # Pay day selected
td=$( date -u +'%-d' ) # Today day of the month.
# To calculate the number of days in the present month.
MonthDays=$( date +'%-d' -ud "$(date +"%Y-%m-01T00:00:00UTC") next month last day" )
# Maybe a simpler alternative for current month last day:
# echo $(cal) | awk '{print $NF}' # $(cal) is unquoted on purpose.
# Make the next PayDay fit within the available days in the month.
# If the selected PayDay given to the script is 31 and the month
# only has 30 days, the next PayDay should be 30,
# not an un-existent and impossible 31.
pd=$(( (pd>MonthDays)?MonthDays:pd ))
res=$(( pd-td ))
# If the value of res is negative, just add the number of days in present month.
echo "Pay Day is in $(( res+=(res<0)?MonthDays:0 )) days"
请注意,唯一date
命令仅需要在当前月份使用,因此不会跨越月/年界限。这可以避免几乎所有问题。唯一的假设是当前月份从 day 开始01
。此外,计算是在 UTC+0 完成的,这避免了 DST(夏令时)或当地变化可能出现的问题。
如果选择的发薪日(例如 31)大于该月可能的天数(例如二月的天数为 28),则程序会假设这样的 28 是发薪日,而不是不存在的(二月)31。
调用脚本(如果今天是第 9 天):
$ ./script 7
Pay Day is in 29 days
$ ./script 16
Pay Day is in 7 days
$ ./script 31
Pay Day is in 19 days
但如果今天是 2 月 28 日:
$ ./script 8
Pay Day is in 8 days
$ ./script 28
Pay Day is in 0 days
$ ./script 31
Pay Day is in 0 days