【问题标题】:How to calculate last business day of the month in Korn Shell?如何计算 Korn Shell 每月的最后一个工作日?
【发布时间】:2010-12-02 20:19:25
【问题描述】:

我看到这个问题是用其他语言回答的,但不是 Korn Shell。我需要防止脚本在当月的最后一个工作日运行(我们可以假设 M-F 是工作日,忽略节假日)。

【问题讨论】:

  • 查看我的编辑。我添加了一个不需要date -d的版本。

标签: date ksh


【解决方案1】:

此函数在 Bash、Korn shell 和 zsh 中有效,但它需要一个带有 -d 选项的 date 命令(例如 GNU date):

function lbdm { typeset lbdm ldm dwn m y; (( m = $1 + 1 )); if [[ $m = 13 ]]; then  m=1; (( y = $2 + 1 )); else y=$2; fi; ldm=$(date -d "$m/1/$y -1 day"); dwn=$(date -d "$ldm" +%u);if [[ $dwn = 6 || $dwn = 7 ]]; then ((offset = 5 - $dwn)); lbdm=$(date -d "$ldm $offset day"); else lbdm=$ldm; fi; echo $lbdm; }

像这样运行它:

$ lbdm 10 2009
Fri Oct 30 00:00:00 CDT 2009

这里是一个演示脚本,分成不同的行,有更好的变量名和一些 cmets:

for Month in {1..12}   # demo a whole year 
do 
    Year=2009
    LastBusinessDay=""
    (( Month = $Month + 1 ))    # use the beginning of the next month to find the end of the one we're interested in
    if [[ $Month = 13 ]]
    then
        Month=1
        (( Year++ ))
    fi;
    # these two calls to date could be combined and then parsed out
    # this first call is in "American" order, but could be changed - everything else is localized - I think
    LastDayofMonth=$(date -d "$Month/1/$Year -1 day")    # get the day before the first of the month
    DayofWeek=$(date -d "$LastDayofMonth" +%u)    # the math is easier than Sun=0 (%w)
    if [[ $DayofWeek = 6 || $DayofWeek = 7 ]]    # if it's Sat or Sun
    then
        (( Offset = 5 - $DayofWeek ))    # then make it Fri
        LastBusinessDay=$(date -d "$LastDayofMonth $Offset day")
    else
        LastBusinessDay=$LastDayofMonth
    fi
    echo "$LastDayofMonth - $DayofWeek - $LastBusinessDay"
done

输出:

2009 年 1 月 31 日星期六 00:00:00 CST - 6 - 2009 年 1 月 30 日星期五 00:00:00 CST 2 月 28 日星期六 00:00:00 CST 2009 - 6 - 2 月 27 日星期五 00:00:00 CST 2009 2009 年 3 月 31 日星期二 00:00:00 CDT - 2 - 2009 年 3 月 31 日星期二 00:00:00 CDT 2009 年 4 月 30 日星期四 00:00:00 CDT - 4 - 2009 年 4 月 30 日星期四 00:00:00 CDT 2009 年 5 月 31 日星期日 00:00:00 CDT - 7 - 5 月 29 日星期五 00:00:00 CDT 2009 2009 年 6 月 30 日星期二 00:00:00 CDT - 2 - 2009 年 6 月 30 日星期二 00:00:00 CDT 2009 年 7 月 31 日星期五 00:00:00 CDT - 5 - 2009 年 7 月 31 日星期五 00:00:00 CDT 2009 年 8 月 31 日星期一 00:00:00 CDT - 1 - 2009 年 8 月 31 日星期一 00:00:00 CDT 2009 年 9 月 30 日星期三 00:00:00 CDT - 3 - 2009 年 9 月 30 日星期三 00:00:00 CDT 2009 年 10 月 31 日星期六 00:00:00 CDT - 6 - 10 月 30 日星期五 00:00:00 CDT 2009 2009 年 11 月 30 日星期一 00:00:00 CST - 1 - 2009 年 11 月 30 日星期一 00:00:00 CST 2009 年 12 月 31 日星期四 00:00:00 CST - 4 - 2009 年 12 月 31 日星期四 00:00:00 CST

注意:我在测试期间发现,如果您尝试将其用于二战前后的日期,由于 CWT 和 CPT 等战时时区,它会失败。

编辑:这是一个应该在 AIX 和其他无法使用上述功能的系统上运行的版本。它应该适用于 Bourne、Bash、Korn 和 zsh。

function lbdN { cal $1 $2 | awk 'NF == 0 {next} FNR > 2 {week = $0} END {num = split(week, days); lbdN = days[num]; if ( num == 1 ) { lbdN -= 2 }; if ( num == 7 ) { lbdN-- }; print lbdN }'; }

如果您的 cal 每周一开始,您可能需要进行调整。

你可以这样使用它:

month=12; year=2009    # if these are unset or null, the current month/year will be used
if [[ $(date +%d) == $(lbdN $month $year) ]]; 
then
    echo "Don't do stuff today"
else
    echo "It's not the last business day of the month"
fi

当然,对您的 shell 的 if...then 语法进行适当的调整。

编辑错误修复:由于使用 tail 的方式,旧版本的 lbdN 在 2 月 28 日星期六结束时失败。新版本解决了这个问题。它只使用calawk

编辑:为了完整起见,我认为包含该月第一个工作日的函数会很方便。

需要date-d

function fbdm { typeset dwn d; dwn=$(date -d "$1/1/$2" +%u); d=1; if [[ $dwn = 6 || $dwn = 7 ]]; then (( d = 9 - $dwn )); fi; echo $(date -d "$1/$d/$2"); }

2010 年 5 月:

Mon May 3 00:00:00 CDT 2010

仅需要 calawk

function fbdN { cal $1 $2 | awk 'FNR == 3 { week = $0 } END { num = split(week, days); fbdN = days[1]; if ( num == 1 ) { fbdN += 2 }; if ( num == 7 ) { fbdN++ }; print fbdN }'; }

2010 年 8 月:

2

【讨论】:

  • 谢谢丹尼斯。我真的很感谢你的帮助。不幸的是,我的“日期”命令不支持 -d 选项。我在 AIX 5.2 上运行 ksh。 $ date -d "12/1/2009 -1 day" date: Not a known flag: d Usage: date [-u] [+"Field Descriptors"] $ 我仍然会点击复选标记,因为你的解决方案显然适用于其他系统,我没有在最初的问题中列出我的操作系统。
  • 嗯...当它发布我的评论时,它取出了我的回车。我想我需要阅读有关如何格式化 cmets 的文档。
猜你喜欢
  • 2013-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多