1

この質問が他の言語で回答されているのを見たことがありますが、Korn シェルでは回答されていません。月の最後の営業日にスクリプトが実行されないようにする必要があります (MF は営業日であり、休日は無視されます)。

4

1 に答える 1

2

この関数は Bash、Korn シェル、および 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

次のデモ スクリプトは複数の行に分割され、より適切な変数名といくつかのコメントが含まれています。

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

出力:

土 1 月 31 日 00:00:00 CST 2009 - 6 - 金 1 月 30 日 00:00:00 CST 2009
土 2 月 28 日 00:00:00 CST 2009 - 6 - 金 2 月 27 日 00:00:00 CST 2009
火曜日 3 月 31 日 00:00:00 CDT 2009 - 2 - 火曜日 3 月 31 日 00:00:00 CDT 2009
Thu Apr 30 00:00:00 CDT 2009 - 4 - Thu Apr 30 00:00:00 CDT 2009
2009 年 5 月 31 日 (日) 00:00:00 CDT - 7 - 2009 年 5 月 29 日 (金) 00:00:00 CDT
Tue Jun 30 00:00:00 CDT 2009 - 2 - Tue Jun 30 00:00:00 CDT 2009
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
水曜日 9 月 30 日 00:00:00 CDT 2009 - 3 - 水曜日 9 月 30 日 00:00:00 CDT 2009
土 10 月 31 日 00:00:00 CDT 2009 - 6 - 金 10 月 30 日 00:00:00 CDT 2009
月 11 月 30 日 00:00:00 CST 2009 - 1 - 月 11 月 30 日 00:00:00 CST 2009
Thu Dec 31 00:00:00 CST 2009 - 4 - Thu Dec 31 00:00:00 CST 2009

注: テスト中に、これを第二次世界大戦前後の日付に使用しようとすると、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

もちろん、シェルのif...then構文に合わせて適切な調整を行います。

編集:バグ修正: 以前のバージョンの のlbdN使用方法が原因で、2 月が 28 日の土曜日に終了すると失敗しましたtail。新しいバージョンではそれが修正されています。と のみcalを使用しawkます。

編集:完全を期すために、月の最初の営業日に機能を含めると便利だと思いました。

必須: 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

以下のみcalが必要です。awk

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
于 2009-10-01T12:39:40.560 に答える