Как рассчитать предыдущий рабочий день в сценарии оболочки ksh? - PullRequest
6 голосов
/ 22 октября 2008

Какой самый элегантный способ вычислить предыдущий рабочий день в сценарии оболочки 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 ]

3 голосов
/ 21 сентября 2009
#!/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)
2 голосов
/ 23 октября 2008

Вот решение, которое не использует Perl. Работает как с ksh, так и с 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
0 голосов
/ 05 декабря 2009

Это должно работать для Solaris и Linux. В Unix действительно сложно, что вы не можете использовать одинаковые аргументы командной строки для всех производных Unix.

В Linux вы можете использовать date -d '-d24 hour ago', чтобы получить последний день на солярисе его 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
0 голосов
/ 22 октября 2008

Что ж, если запуск Perl считается частью скрипта, тогда разработайте ответ в Perl. Следующий вопрос - что определяет рабочий день? Вы магазин / магазин, который открыт в воскресенье? Суббота? Или 9-5 с понедельника по пятницу бизнес? А как насчет праздников?

Если вы думаете, что с понедельника по пятницу и праздничные дни временно несущественны, тогда вы можете использовать алгоритм в Perl, который отмечает, что wday будет 0 в воскресенье - 6 в субботу, и поэтому, если wday равен 1, вам нужно вычесть 3 * 86400 от времени (); если wday равен 0, вам необходимо вычесть 2 * 86400; и если wday равен 6, вам нужно вычесть 1 * 86400. Вот что у вас есть в оболочке Korn - просто сделайте это в 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) - отсюда и иллюстрированный формат.

...