计算付款天数

计算付款天数

我需要显示距离即将到来的付款日还有多少天(假设它总是在任何一个月的 10 日)。

我如何在 bash 中做到这一点?

答案1

虽然bash现在具有日期格式化功能,但它没有日期解析或计算功能,因此您可能需要使用其他 shell,例如ksh93orzsh或适当的编程语言,例如perlor 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

相关内容