6

在 shell ksh 脚本中计算前一个工作日的最优雅方法是什么?

到目前为止我得到的是:

#!/bin/ksh

set -x

DAY_DIFF=1
case `date '+%a'` in
"Sun")
   DAY_DIFF=2
   ;;
"Mon")
   DAY_DIFF=3
   ;;
esac

PREV_DT=`perl -e '($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time()-${DAY_DIFF}*24*60*60);printf "%4d%02d%02d",$year+1900,$mon+1,$mday;'`

echo $PREV_DT

如何使 ${DAY_DIFF} 变量作为值而不是字符串传输?

4

4 回答 4

3
#!/bin/ksh
# GNU date is a veritable Swiss Army Knife...
((D=$(date +%w)+2))
if [ $D -gt 3 ]; then D=1; fi
PREV_DT=$(date -d "-$D days" +%F)
于 2009-09-21T18:13:10.113 回答
2

Here is a solution that doesn't use Perl. It works both with ksh and sh.

#!/bin/ksh

diff=-1
[ `date +%u` == 1 ] && diff=-3

seconds=$((`date +%s` + $diff * 24 * 3600))
format=+%Y-%m-%d

if date --help 2>/dev/null | grep -q -- -d ; then
    # GNU date (e.g., Linux)
    date -d "1970-01-01 00:00 UTC + $seconds seconds" $format
else
    # For BSD date (e.g., Mac OS X)
    date -r $seconds $format
fi
于 2008-10-23T10:16:33.863 回答
0

这应该适用于 Solaris 和 Linux。在 Unix 上,您不能在所有 Unix 衍生产品上使用相同的命令行参数,这真的很复杂。

在 Linux 上,您可以使用date -d '-d24 hour ago'Solaris 上的最后一天获取TZ=CET+24 date. 我猜其他 UNIX 的工作方式与 Solaris 相同。

#!/usr/bin/ksh

lbd=5               # last business day (1=Mon, 2=Thu ... 6=Sat, 7=Sun)
lbd_date=""         # last business day date

function lbdSunOS
{
    typeset back=$1
    typeset tz=`date '+%Z'`     # timezone

    lbd_date=`TZ=${tz}+$back date '+%Y%m%d'`
}

function lbdLinux
{
    typeset back=$1

    lbd_date=`date -d "-d$back hour ago"`
}

function calcHoursBack
{
    typeset lbd=$1
    typeset dow=`date '+%u'`    # day of the week

    if [ $dow -ge $lbd ]
    then
        return $(((dow-lbd)*24))
    else
        return $(((dow-lbd+7)*24))
    fi
}

# Main

calcHoursBack $lbd
lbd`uname -s` $?

echo $lbd_date
于 2009-12-05T14:50:41.090 回答
0

好吧,如果运行 Perl 算作脚本的一部分,那么在 Perl 中开发答案。下一个问题是 - 什么定义了工作日?您是周日营业的商店/商店吗?周六?还是周一到周五朝九晚五的生意?假期呢?

假设您认为周一到周五和假期暂时无关紧要,那么您可以使用 Perl 中的算法指出 wday 将在周日为 0 到周六为 6,因此如果 wday 为 1,则需要减去 3 * 86400从时间(); 如果 wday 为 0,则需要减去 2 * 86400;如果 wday 是 6,你需要减去 1 * 86400。这就是你在 Korn shell 中得到的东西 - 只需在 Perl 中执行它:

#!/bin/perl -w
use strict;
use POSIX;
use constant SECS_PER_DAY => 24 * 60 * 60;
my(@days) = (2, 3, 1, 1, 1, 1, 1);
my($now) = time;
my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime($now);
print strftime("%Y-%m-%d\n", localtime($now - $days[$wday] * SECS_PER_DAY));

这确实假设您有 POSIX 模块;如果没有,那么您将需要执行与您使用的大致相同的 printf() 。我还根据偏好使用 ISO 8601 日期格式(XSD 和 SQL 也使用) - 因此是图示格式。

于 2008-10-22T03:49:57.047 回答