Арифметика дат в сценариях оболочки Unix - PullRequest
18 голосов
/ 09 августа 2008

Мне нужно сделать арифметику дат в сценариях оболочки Unix, которые я использую для контроля выполнения сторонних программ.

Я использую функцию для увеличения дня, а другую для уменьшения:

IncrementaDia(){
echo $1 | awk '
BEGIN {
        diasDelMes[1] = 31
        diasDelMes[2] = 28
        diasDelMes[3] = 31
        diasDelMes[4] = 30
        diasDelMes[5] = 31
        diasDelMes[6] = 30
        diasDelMes[7] = 31
        diasDelMes[8] = 31
        diasDelMes[9] = 30
        diasDelMes[10] = 31
        diasDelMes[11] = 30
        diasDelMes[12] = 31
}
{
        anio=substr($1,1,4)
        mes=substr($1,5,2)
        dia=substr($1,7,2)

        if((anio % 4 == 0 && anio % 100 != 0) || anio % 400 == 0)
        {
                diasDelMes[2] = 29;
        }

        if( dia == diasDelMes[int(mes)] ) {
                if( int(mes) == 12 ) {
                        anio = anio + 1
                        mes = 1
                        dia = 1
                } else {
                        mes = mes + 1
                        dia = 1
                }
        } else {
                dia = dia + 1
        }
}
END {
        printf("%04d%02d%02d", anio, mes, dia)
}
'
}

if [ $# -eq 1 ]; then
        tomorrow=$1
else
        today=$(date +"%Y%m%d")
        tomorrow=$(IncrementaDia $hoy)
fi

но теперь мне нужно сделать более сложную арифметику.

Какой самый лучший и совместимый способ сделать это?

Ответы [ 14 ]

3 голосов
/ 09 августа 2008

Если посмотреть дальше, я думаю, вы можете просто использовать дату. Я попробовал следующее в OpenBSD: я взял дату 29 февраля 2008 года и случайный час (в форме 080229301535) и добавил +1 к дневной части, например так:

$ date -j 0802301535
Sat Mar  1 15:35:00 EST 2008

Как видите, дата правильно отформатировала время ...

НТН

0 голосов
/ 14 июля 2016

Это работает для меня:

TZ=GMT+6;
export TZ
mes=`date --date='2 days ago' '+%m'`
dia=`date --date='2 days ago' '+%d'`
anio=`date --date='2 days ago' '+%Y'`
hora=`date --date='2 days ago' '+%H'`
0 голосов
/ 25 апреля 2012

Вот мои две копейки - оболочка сценария, использующая date и grep.

Пример использования

> sh ./datecalc.sh "2012-08-04 19:43:00" + 1s
2012-08-04 19:43:00 + 0d0h0m1s
2012-08-04 19:43:01

> sh ./datecalc.sh "2012-08-04 19:43:00" - 1s1m1h1d
2012-08-04 19:43:00 - 1d1h1m1s
2012-08-03 18:41:59

> sh ./datecalc.sh "2012-08-04 19:43:00" - 1d2d1h2h1m2m1s2sblahblah
2012-08-04 19:43:00 - 1d1h1m1s
2012-08-03 18:41:59

> sh ./datecalc.sh "2012-08-04 19:43:00" x 1d
Bad operator :-(

> sh ./datecalc.sh "2012-08-04 19:43:00"
Missing arguments :-(

> sh ./datecalc.sh gibberish + 1h
date: invalid date `gibberish'
Invalid date :-(

Сценарий

#!/bin/sh

# Usage:
#
# datecalc "<date>" <operator> <period>
#
# <date> ::= see "man date", section "DATE STRING"
# <operator> ::= + | -
# <period> ::= INTEGER<unit> | INTEGER<unit><period>
# <unit> ::= s | m | h | d

if [ $# -lt 3 ]; then
echo "Missing arguments :-("
exit; fi

date=`eval "date -d \"$1\" +%s"`
if [ -z $date ]; then
echo "Invalid date :-("
exit; fi

if ! ([ $2 == "-" ] || [ $2 == "+" ]); then
echo "Bad operator :-("
exit; fi
op=$2

minute=$[60]
hour=$[$minute*$minute]
day=$[24*$hour]

s=`echo $3 | grep -oe '[0-9]*s' | grep -m 1 -oe '[0-9]*'`
m=`echo $3 | grep -oe '[0-9]*m' | grep -m 1 -oe '[0-9]*'`
h=`echo $3 | grep -oe '[0-9]*h' | grep -m 1 -oe '[0-9]*'`
d=`echo $3 | grep -oe '[0-9]*d' | grep -m 1 -oe '[0-9]*'`
if [ -z $s ]; then s=0; fi
if [ -z $m ]; then m=0; fi
if [ -z $h ]; then h=0; fi
if [ -z $d ]; then d=0; fi

ms=$[$m*$minute]
hs=$[$h*$hour]
ds=$[$d*$day]

sum=$[$s+$ms+$hs+$ds]
out=$[$date$op$sum]
formattedout=`eval "date -d @$out +\"%Y-%m-%d %H:%M:%S\""`

echo $1 $2 $d"d"$h"h"$m"m"$s"s"
echo $formattedout
0 голосов
/ 16 августа 2008

Если у вас работает версия даты из GNU, почему бы вам не взять исходный код и не скомпилировать его в AIX и Solaris?

http://www.gnu.org/software/coreutils/

В любом случае источник должен помочь вам получить правильную арифметику даты, если вы собираетесь написать собственный код.

Кроме того, комментарии типа «это решение хорошо, но, конечно, вы можете заметить, что оно не так хорошо, как может быть. Кажется, никто не думал возиться с датами при создании Unix». на самом деле никуда нас не приведет. Я нашел, что каждое из предложений до сих пор было очень полезным и целевым.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...