24 Stimmen

Datumsarithmetik in Unix-Shell-Skripten

Ich muss Datumsberechnungen in Unix-Shell-Skripten durchführen, die ich zur Steuerung der Ausführung von Programmen Dritter verwende.

Ich verwende eine Funktion zum Erhöhen eines Tages und eine andere zum Verringern:

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

aber jetzt muss ich komplexere Berechnungen durchführen.

Was ist der beste und kompatibelste Weg, dies zu tun?

3voto

joast Punkte 2968

Das Buch "Shell Script Recipes: A Problem Solution Approach" (ISBN: 978-1-59059-471-1) von Chris F.A. Johnson enthält eine Bibliothek mit Datumsfunktionen, die hilfreich sein könnte. Der Quellcode ist verfügbar unter http://apress.com/book/downloadfile/2146 (die Datumsfunktionen befinden sich in Kapitel08/data-funcs-sh innerhalb der tar-Datei).

0voto

Jon Ericson Punkte 20031

Wenn die GNU-Version von date für dich funktioniert, warum nimmst du nicht den Quellcode und kompilierst ihn auf AIX und Solaris?

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

In jedem Fall sollte der Quelltext Ihnen helfen, die Datumsarithmetik richtig zu verstehen, wenn Sie Ihren eigenen Code schreiben wollen.

Nebenbei bemerkt, Kommentare wie "diese Lösung ist gut, aber Sie können sicher feststellen, dass sie nicht so gut ist, wie sie sein könnte. Es scheint, dass bei der Entwicklung von Unix niemand daran gedacht hat, mit Datumsangaben herumzuspielen", bringen uns nicht wirklich weiter. Ich fand jeden der bisherigen Vorschläge sehr nützlich und treffend.

0voto

Johnny Baloney Punkte 3119

Hier sind meine zwei Groschen wert - ein Skript-Wrapper unter Verwendung von date y grep .

Beispiel für die Verwendung

> 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 :-(

Drehbuch

#!/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

-1voto

Tulio Galdamez Punkte 1

Das funktioniert bei mir:

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'`

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X