Маленький, но очень мощный date


bliznezz аватар

bliznezz - Posted on 14 Август 2008

ну наверное все знаю функционал линуксовой команды date, вывод даты в самом разном формате.
а также есть функционал вычисления дат. например сегодня у меня Thu Aug 14 16:09:28 EEST 2008
вчера:

$ date --date="yesterday" +%F
$ date --date="1 days ago" +%F
2008-08-13

воскресенье через 2 недели:

$ date --date="sunday next 2 week"
Sun Aug 31 01:00:00 EEST 2008

если мы скажем день недели - date будет иметь ввиду ближайший такой день (или сегодняшний)

$ date --date="friday" +%F
2008-08-15

аналогично если добавить this: this friday. если надо прошедший:

$ date --date="last friday" +%F
2008-08-08

често бывает нужно грепать по логам за вчера, позавчера, позапозачера и т.д:

for i in `seq 7 -1 1`;do 
grep `date --date="$i days ago" +%F ` log > `date --date="$i days ago" +%F`.log ;
done

за неделю

конечно может многое другое, нетривиальное, но я думаю в коментариях появится самое разное =)
кстати, в man-е описан разве что формат вывода даты. а опции расписаны в info date

4.75
Ваша оценка: Ничего Рейтинг: 4.8 (4 голоса)

Вот в тему из одного моего скрипта:

case `uname` in
    Linux)
        sec2date() { date -d "1970-01-01 UTC $1 seconds" --rfc-2822 2> /dev/null;}
        date2sec() { date -d "$*" +%s 2> /dev/null;}
    ;;
    FreeBSD)
        #sec2date() { LANG=C date -r $1  +"%a, %d %b %Y %T %z" 2> /dev/null; }
        #date2sec() { LANG=C date -j -f "%a, %d %b %Y %T %z" "$*" +%s 2> /dev/null; }
        sec2date() { LANG=C date -r $1  +"%a, %d %b %Y %T"; }
        date2sec() {
            HEADER_SEC=`LANG=C date -u -j -f "%a, %d %b %Y %T" "$*" "+%s" 2> /dev/null;`
 
            # переводим GMT +0200 напримре в секунды и вычитаем Ж:-)
            #F_TZ=`echo $HEADER_TZ | sed 's/.*\([+-]\)\([0-9][0-9]\)\([0-9][0-9]\).*/0 \1 \2 \\\\* 3600 \1 \3 \\\\* 60/'`
            F_TZ=`echo $HEADER_TIME | sed 's/.*\([+-]\)\([0-9][0-9]\)\([0-9][0-9]\).*/0 \1 \2 \\\\* 3600 \1 \3 \\\\* 60/'`
            F_TZ=`eval expr $F_TZ`
            #HEADER_SEC=`expr $HEADER_SEC - $F_TZ`
            expr $HEADER_SEC - $F_TZ
        }
    ;;
    *)
        sec2date() { echo can\'t decode: Epoch time: $1 sec.; }
        date2sec() { echo can\'t decode: Date: $*; }
    ;;
esac

после чего в скрипте можно использовать две процедуры sec2date() и date2sec() для преобразования unix time (кол-во секунд от 1970-01-01)
в формат даты принятого в заголовках email (например Wed, 18 Jan 2006 14:16:57 +0200) и обратно.

...Все понятно - лучше если будет корректно настроен часовой пояс и все такое... Но если очень надо, то можно один раз и руками:
На час вперед:

date 0$(echo `date +%m%d%H%M%Y`+1000000|bc)

На час назад:

date 0$(echo `date +%m%d%H%M%Y`-1000000|bc)

А можно плюнуть и в cron - в таком виде:

[[ "/usr/bin/date +%w" ]] && /usr/bin/date 0$(/usr/bin/echo `/usr/bin/date +%m%d%H%M%Y`-1000000|/usr/bin/bc)
[[ "/usr/bin/date +%w" ]] && /usr/bin/date 0$(/usr/bin/echo `/usr/bin/date +%m%d%H%M%Y`-1000000|/usr/bin/bc)

> date 0$(echo `date +%m%d%H%M%Y`+1000000|bc)

$ date 0$(echo `date +%m%d%H%M%Y`-1000000|bc)
date: invalid date `062099492009'

> [[ "/usr/bin/date +%w" ]] && /usr/bin/date 0$(/usr/bin/echo `/usr/bin/date +%m%d%H%M%Y`-1000000|/usr/bin/bc)

не совсем понятно чего тут хотели достичь. вместо " точно не `?
каждый день недели кроме воскресенья переводить часы?
и почему два раза? опечатка?

Гм-м... У меня оба правильно срабатывают:

№ date
Вск Июн 21 03:26:51 EEST 2009
 
# date 0$(echo `date +%m%d%H%M%Y`-1000000|bc)
Вск Июн 21 02:26:00 EEST 2009
 
# date 0$(echo `date +%m%d%H%M%Y`+1000000|bc)
Вск Июн 21 03:26:00 EEST 2009

GNU bash, version 3.1.17(2)-release (i486-slackware-linux-gnu) И на этой тачке реально используется.

Попробовал на другой машинке
GNU bash, version 3.00.16(1)-release (i386-redhat-linux-gnu)
тоже все сработало.
А если нулик убрать между date и $(... ??

В кронтабовской строке сначала проверяется, является ли день воскресеньем, и если да, то выполняется все остальное (перевод на час).

Записи в crontab конкретно таковы:

0 3 25-31 2 * [[ "/usr/bin/date +%w" ]] && /usr/bin/date 0$(/usr/bin/echo `/usr/bin/date +%m%d%H%M%Y`+1000000|/usr/bin/bc)
0 3 25-31 9 * [[ "/usr/bin/date +%w" ]] && /usr/bin/date $(/usr/bin/echo `/usr/bin/date +%m%d%H%M%Y`-1000000|/usr/bin/bc)

Каждый день из промежутка с 25 по 31 числа марта (или октября - для второй команды) в 3:00 срабатывает проверка - является ли день воскресеньем итд.

Перевести секунды прошедшие с epoch (1970-01-01 UTC) в дату:
date --date='@2147483647'
выдаст:
Втр Янв 19 05:14:07 EET 2038

Фишка "недокументированная" - в манах почему-то не упомянута ;-))

o_O
действтиельно не документированая

а как вычислить последнюю пятницу июля?

Скриптом с условиями.
Алгоритм примерно такой,
если сегодня июль и пятница и следующая пятница уже август.

В date на FreeBSD опция --date= отсутствует. Поэтому тоже самое но BSD-шными средствами.

Вчера:

% date -v-1d +%F 
2008-08-15

воскресенье через 2 недели:

date -v+2w -v+sun
Sun 31 Aug 2008 03:10:17 CEST

ближайший такой день (пятница):

# -v+fri - следующая пятница, -v-fri - предыдущая, -vfri ближайшая к актуальному дню.
date -vfri
Fri 15 Aug 2008 03:10:50 CEST

благодарю, пригодилось!

а на перле можно так:
localtime(time-+(60*60*24*$i))

Где:
$i - количество дней,
+- соответственно дата вперед или назад.

Отправить комментарий

Google Friend Connect (leave a quick comment)
loading...
Содержание этого поля является приватным и не предназначено к показу.