Арифметика даты в сценариях оболочки Unix
Мне нужно выполнить арифметику даты в сценариях оболочки 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)14
Я написал сценарий bash для преобразования дат, выраженных на английском языке, в обычные даты мм / дд / гггг. Он называется ComputeDate .
Вот несколько примеров его использования. Для краткости я поместил вывод каждого вызова в ту же строку, что и вызов, и разделил их двоеточием (:). Приведенные ниже кавычки не нужны при запуске ComputeDate :
$ ComputeDate 'yesterday': 03/19/2010
$ ComputeDate 'yes': 03/19/2010
$ ComputeDate 'today': 03/20/2010
$ ComputeDate 'tod': 03/20/2010
$ ComputeDate 'now': 03/20/2010
$ ComputeDate 'tomorrow': 03/21/2010
$ ComputeDate 'tom': 03/21/2010
$ ComputeDate '10/29/32': 10/29/2032
$ ComputeDate 'October 29': 10/1/2029
$ ComputeDate 'October 29, 2010': 10/29/2010
$ ComputeDate 'this monday': 'this monday' has passed. Did you mean 'next monday?'
$ ComputeDate 'a week after today': 03/27/2010
$ ComputeDate 'this satu': 03/20/2010
$ ComputeDate 'next monday': 03/22/2010
$ ComputeDate 'next thur': 03/25/2010
$ ComputeDate 'mon in 2 weeks': 03/28/2010
$ ComputeDate 'the last day of the month': 03/31/2010
$ ComputeDate 'the last day of feb': 2/28/2010
$ ComputeDate 'the last day of feb 2000': 2/29/2000
$ ComputeDate '1 week from yesterday': 03/26/2010
$ ComputeDate '1 week from today': 03/27/2010
$ ComputeDate '1 week from tomorrow': 03/28/2010
$ ComputeDate '2 weeks from yesterday': 4/2/2010
$ ComputeDate '2 weeks from today': 4/3/2010
$ ComputeDate '2 weeks from tomorrow': 4/4/2010
$ ComputeDate '1 week after the last day of march': 4/7/2010
$ ComputeDate '1 week after next Thursday': 4/1/2010
$ ComputeDate '2 weeks after the last day of march': 4/14/2010
$ ComputeDate '2 weeks after 1 day after the last day of march': 4/15/2010
$ ComputeDate '1 day after the last day of march': 4/1/2010
$ ComputeDate '1 day after 1 day after 1 day after 1 day after today': 03/24/2010
Я включил этот сценарий в качестве ответа на эту проблему, потому что он показывает, как выполнять арифметические операции с датами с помощью набора функций bash, и эти функции могут оказаться полезными для других. Он правильно обрабатывает високосные годы и високосные века:
#! /bin/bash
# ConvertDate -- convert a human-readable date to a MM/DD/YY date
#
# Date ::= Month/Day/Year
# | Month/Day
# | DayOfWeek
# | [this|next] DayOfWeek
# | DayofWeek [of|in] [Number|next] weeks[s]
# | Number [day|week][s] from Date
# | the last day of the month
# | the last day of Month
#
# Month ::= January | February | March | April | May | ... | December
# January ::= jan | january | 1
# February ::= feb | january | 2
# ...
# December ::= dec | december | 12
# Day ::= 1 | 2 | ... | 31
# DayOfWeek ::= today | Sunday | Monday | Tuesday | ... | Saturday
# Sunday ::= sun*
# ...
# Saturday ::= sat*
#
# Number ::= Day | a
#
# Author: Larry Morell
if [ $# = 0 ]; then
printdirections $0
exit
fi
# Request the value of a variable
GetVar () {
Var=$1
echo -n "$Var= [${!Var}]: "
local X
read X
if [ ! -z $X ]; then
eval $Var="$X"
fi
}
IsLeapYear () {
local Year=$1
if [ $[20$Year % 4] -eq 0 ]; then
echo yes
else
echo no
fi
}
# AddToDate -- compute another date within the same year
DayNames=(mon tue wed thu fri sat sun ) # To correspond with 'date' output
Day2Int () {
ErrorFlag=
case $1 in
-e )
ErrorFlag=-e; shift
;;
esac
local dow=$1
n=0
while [ $n -lt 7 -a $dow != "${DayNames[n]}" ]; do
let n++
done
if [ -z "$ErrorFlag" -a $n -eq 7 ]; then
echo Cannot convert $dow to a numeric day of wee
exit
fi
echo $[n+1]
}
Months=(31 28 31 30 31 30 31 31 30 31 30 31)
MonthNames=(jan feb mar apr may jun jul aug sep oct nov dec)
# Returns the month (1-12) from a date, or a month name
Month2Int () {
ErrorFlag=
case $1 in
-e )
ErrorFlag=-e; shift
;;
esac
M=$1
Month=${M%%/*} # Remove /...
case $Month in
[a-z]* )
Month=${Month:0:3}
M=0
while [ $M -lt 12 -a ${MonthNames[M]} != $Month ]; do
let M++
done
let M++
esac
if [ -z "$ErrorFlag" -a $M -gt 12 ]; then
echo "'$Month' Is not a valid month."
exit
fi
echo $M
}
# Retrieve month,day,year from a legal date
GetMonth() {
echo ${1%%/*}
}
GetDay() {
echo $1 | col / 2
}
GetYear() {
echo ${1##*/}
}
AddToDate() {
local Date=$1
local days=$2
local Month=`GetMonth $Date`
local Day=`echo $Date | col / 2` # Day of Date
local Year=`echo $Date | col / 3` # Year of Date
local LeapYear=`IsLeapYear $Year`
if [ $LeapYear = "yes" ]; then
let Months[1]++
fi
Day=$[Day+days]
while [ $Day -gt ${Months[$Month-1]} ]; do
Day=$[Day - ${Months[$Month-1]}]
let Month++
done
echo "$Month/$Day/$Year"
}
# Convert a date to normal form
NormalizeDate () {
Date=`echo "$*" | sed 'sX *X/Xg'`
local Day=`date +%d`
local Month=`date +%m`
local Year=`date +%Y`
#echo Normalizing Date=$Date > /dev/tty
case $Date in
*/*/* )
Month=`echo $Date | col / 1 `
Month=`Month2Int $Month`
Day=`echo $Date | col / 2`
Year=`echo $Date | col / 3`
;;
*/* )
Month=`echo $Date | col / 1 `
Month=`Month2Int $Month`
Day=1
Year=`echo $Date | col / 2 `
;;
[a-z]* ) # Better be a month or day of week
Exp=${Date:0:3}
case $Exp in
jan|feb|mar|apr|may|june|jul|aug|sep|oct|nov|dec )
Month=$Exp
Month=`Month2Int $Month`
Day=1
#Year stays the same
;;
mon|tue|wed|thu|fri|sat|sun )
# Compute the next such day
local DayOfWeek=`date +%u`
D=`Day2Int $Exp`
if [ $DayOfWeek -le $D ]; then
Date=`AddToDate $Month/$Day/$Year $[D-DayOfWeek]`
else
Date=`AddToDate $Month/$Day/$Year $[7+D-DayOfWeek]`
fi
# Reset Month/Day/Year
Month=`echo $Date | col / 1 `
Day=`echo $Date | col / 2`
Year=`echo $Date | col / 3`
;;
* ) echo "$Exp is not a valid month or day"
exit
;;
esac
;;
* ) echo "$Date is not a valid date"
exit
;;
esac
case $Day in
[0-9]* );; # Day must be numeric
* ) echo "$Date is not a valid date"
exit
;;
esac
[0-9][0-9][0-9][0-9] );; # Year must be 4 digits
[0-9][0-9] )
Year=20$Year
;;
esac
Date=$Month/$Day/$Year
echo $Date
}
# NormalizeDate jan
# NormalizeDate january
# NormalizeDate jan 2009
# NormalizeDate jan 22 1983
# NormalizeDate 1/22
# NormalizeDate 1 22
# NormalizeDate sat
# NormalizeDate sun
# NormalizeDate mon
ComputeExtension () {
local Date=$1; shift
local Month=`GetMonth $Date`
local Day=`echo $Date | col / 2`
local Year=`echo $Date | col / 3`
local ExtensionExp="$*"
case $ExtensionExp in
*w*d* ) # like 5 weeks 3 days or even 5w2d
ExtensionExp=`echo $ExtensionExp | sed 's/[a-z]/ /g'`
weeks=`echo $ExtensionExp | col 1`
days=`echo $ExtensionExp | col 2`
days=$[7*weeks+days]
Due=`AddToDate $Month/$Day/$Year $days`
;;
*d ) # Like 5 days or 5d
ExtensionExp=`echo $ExtensionExp | sed 's/[a-z]/ /g'`
days=$ExtensionExp
Due=`AddToDate $Month/$Day/$Year $days`
;;
* )
Due=$ExtensionExp
;;
esac
echo $Due
}
# Pop -- remove the first element from an array and shift left
Pop () {
Var=$1
eval "unset $Var[0]"
eval "$Var=(\${$Var[*]})"
}
ComputeDate () {
local Date=`NormalizeDate $1`; shift
local Expression=`echo $* | sed 's/^ *a /1 /;s/,/ /' | tr A-Z a-z `
local Exp=(`echo $Expression `)
local Token=$Exp # first one
local Ans=
#echo "Computing date for ${Exp[*]}" > /dev/tty
case $Token in
*/* ) # Regular date
M=`GetMonth $Token`
D=`GetDay $Token`
Y=`GetYear $Token`
if [ -z "$Y" ]; then
Y=$Year
elif [ ${#Y} -eq 2 ]; then
Y=20$Y
fi
Ans="$M/$D/$Y"
;;
yes* )
Ans=`AddToDate $Date -1`
;;
tod*|now )
Ans=$Date
;;
tom* )
Ans=`AddToDate $Date 1`
;;
the )
case $Expression in
*day*after* ) #the day after Date
Pop Exp; # Skip the
Pop Exp; # Skip day
Pop Exp; # Skip after
#echo Calling ComputeDate $Date ${Exp[*]} > /dev/tty
Date=`ComputeDate $Date ${Exp[*]}` #Recursive call
#echo "New date is " $Date > /dev/tty
Ans=`AddToDate $Date 1`
;;
*last*day*of*th*month|*end*of*th*month )
M=`date +%m`
Day=${Months[M-1]}
if [ $M -eq 2 -a `IsLeapYear $Year` = yes ]; then
let Day++
fi
Ans=$Month/$Day/$Year
;;
*last*day*of* )
D=${Expression##*of }
D=`NormalizeDate $D`
M=`GetMonth $D`
Y=`GetYear $D`
# echo M is $M > /dev/tty
Day=${Months[M-1]}
if [ $M -eq 2 -a `IsLeapYear $Y` = yes ]; then
let Day++
fi
Ans=$[M]/$Day/$Y
;;
* )
echo "Unknown expression: " $Expression
exit
;;
esac
;;
next* ) # next DayOfWeek
Pop Exp
dow=`Day2Int $DayOfWeek` # First 3 chars
tdow=`Day2Int ${Exp:0:3}` # First 3 chars
n=$[7-dow+tdow]
Ans=`AddToDate $Date $n`
;;
this* )
Pop Exp
dow=`Day2Int $DayOfWeek`
tdow=`Day2Int ${Exp:0:3}` # First 3 chars
if [ $dow -gt $tdow ]; then
echo "'this $Exp' has passed. Did you mean 'next $Exp?'"
exit
fi
n=$[tdow-dow]
Ans=`AddToDate $Date $n`
;;
[a-z]* ) # DayOfWeek ...
M=${Exp:0:3}
case $M in
jan|feb|mar|apr|may|june|jul|aug|sep|oct|nov|dec )
ND=`NormalizeDate ${Exp[*]}`
Ans=$ND
;;
mon|tue|wed|thu|fri|sat|sun )
dow=`Day2Int $DayOfWeek`
Ans=`NormalizeDate $Exp`
if [ ${#Exp[*]} -gt 1 ]; then # Just a DayOfWeek
#tdow=`GetDay $Exp` # First 3 chars
#if [ $dow -gt $tdow ]; then
#echo "'this $Exp' has passed. Did you mean 'next $Exp'?"
#exit
#fi
#n=$[tdow-dow]
#else # DayOfWeek in a future week
Pop Exp # toss monday
Pop Exp # toss in/off
if [ $Exp = next ]; then
Exp=2
fi
n=$[7*(Exp-1)] # number of weeks
n=$[n+7-dow+tdow]
Ans=`AddToDate $Date $n`
fi
;;
esac
;;
[0-9]* ) # Number weeks [from|after] Date
n=$Exp
Pop Exp;
case $Exp in
w* ) let n=7*n;;
esac
Pop Exp; Pop Exp
#echo Calling ComputeDate $Date ${Exp[*]} > /dev/tty
Date=`ComputeDate $Date ${Exp[*]}` #Recursive call
#echo "New date is " $Date > /dev/tty
Ans=`AddToDate $Date $n`
;;
esac
echo $Ans
}
Year=`date +%Y`
Month=`date +%m`
Day=`date +%d`
DayOfWeek=`date +%a |tr A-Z a-z`
Date="$Month/$Day/$Year"
ComputeDate $Date $*
Этот сценарий широко использует другой сценарий, который я написал (называемый col ... многие извинения тем, кто использует стандартный col, поставляемый с Linux). Эта версия col упрощает извлечение столбцов из стандартного ввода. Таким образом,
$ echo a b c d e | col 5 3 2
отпечатки
e c b
Вот сценарий col :
#!/bin/sh
# col -- extract columns from a file
# Usage:
# col [-r] [c] col-1 col-2 ...
# where [c] if supplied defines the field separator
# where each col-i represents a column interpreted according to the presence of -r as follows:
# -r present : counting starts from the right end of the line
# -r absent : counting starts from the left side of the line
Separator=" "
Reverse=false
case "$1" in
-r ) Reverse=true; shift;
;;
[0-9]* )
;;
* )Separator="$1"; shift;
;;
esac
case "$1" in
-r ) Reverse=true; shift;
;;
[0-9]* )
;;
* )Separator="$1"; shift;
;;
esac
# Replace each col-i with $i
Cols=""
for f in $*
do
if [ $Reverse = true ]; then
Cols="$Cols \$(NF-$f+1),"
else
Cols="$Cols \$$f,"
fi
done
Cols=`echo "$Cols" | sed 's/,$//'`
#echo "Using column specifications of $Cols"
awk -F "$Separator" "{print $Cols}"
Он также использует printdirections для печати направлений, когда скрипт запускается неправильно:
#!/bin/sh
#
# printdirections -- print header lines of a shell script
#
# Usage:
# printdirections path
# where
# path is a *full* path to the shell script in question
# beginning with '/'
#
# To use printdirections, you must include (as comments at the top
# of your shell script) documentation for running the shell script.
if [ $# -eq 0 -o "$*" = "-h" ]; then
printdirections $0
exit
fi
# Delete the command invocation at the top of the file, if any
# Delete from the place where printdirections occurs to the end of the file
# Remove the # comments
# There is a bizarre oddity here.
sed '/#!/d;/.*printdirections/,$d;/ *#/!d;s/# //;s/#//' $1 > /tmp/printdirections.$$
# Count the number of lines
numlines=`wc -l /tmp/printdirections.$$ | awk '{print $1}'`
# Remove the last line
numlines=`expr $numlines - 1`
head -n $numlines /tmp/printdirections.$$
rm /tmp/printdirections.$$
Чтобы использовать это, поместите три сценария в файлы ComputeDate , col и printdirections соответственно. Поместите файл в каталог, названный вашим PATH, обычно ~ / bin. Затем сделайте их исполняемыми с помощью:
$ chmod a+x ComputeDate col printdirections
Проблемы? Пришлите мне письмо: Morell AT cs.atu.edu Поместите ComputeDate в тему.
Вот простой способ вычисления даты в сценариях оболочки.
meetingDate='12/31/2011' # MM/DD/YYYY Format
reminderDate=`date --date=$meetingDate'-1 day' +'%m/%d/%Y'`
echo $reminderDate
Ниже приведены другие варианты вычисления даты, которые можно выполнить с помощью date
утилиты.
http://www.cyberciti.biz/tips/linux-unix-get-yesterdays-tomorrows-date.html
http://www.cyberciti.biz/faq/linux-unix-formatting-dates-for-display/
Это сработало для меня на RHEL.
Вот мои две копейки - оболочка скрипта, использующая 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
Для совместимости с BSD / OS X вы также можете использовать утилиту даты с -j
и -v
для вычисления даты. См. Дату на странице руководства FreeBSD . Вы можете объединить предыдущие ответы Linux с этим ответом, который может обеспечить вам достаточную совместимость.
В BSD, как и в Linux, при запуске date
вы получите текущую дату:
$ date
Wed 12 Nov 2014 13:36:00 AEDT
Теперь с датой из BSD вы можете сделать математику с -v
, например , листинг завтрашнюю дату ( +1d
это плюс один день ):
$ date -v +1d
Thu 13 Nov 2014 13:36:34 AEDT
Вы можете использовать существующую дату в качестве основы и, при желании, указать формат синтаксического анализа с помощью strftime, и убедитесь, что вы используете его, -j
чтобы не изменять системную дату:
$ date -j -f "%a %b %d %H:%M:%S %Y %z" "Sat Aug 09 13:37:14 2014 +1100"
Sat 9 Aug 2014 12:37:14 AEST
И вы можете использовать это как основу для расчетов даты:
$ date -v +1d -f "%a %b %d %H:%M:%S %Y %z" "Sat Aug 09 13:37:14 2014 +1100"
Sun 10 Aug 2014 12:37:14 AEST
Обратите внимание, что -v
подразумевает -j
.
Последовательно можно выполнить несколько регулировок:
$ date -v +1m -v -1w
Fri 5 Dec 2014 13:40:07 AEDT
Смотрите man-страницу для более подробной информации.
Почему бы не написать свои сценарии на таких языках, как perl или python, которые более естественно поддерживают сложную обработку дат? Конечно, вы можете сделать все это в bash, но я думаю, вы также получите большую согласованность между платформами, например, с использованием python, если вы можете убедиться, что установлен perl или python.
Я должен добавить, что довольно легко подключить скрипты Python и Perl к содержащему их скрипту оболочки.
Изучая это дальше, я думаю, вы можете просто использовать date. Я пробовал следующее на OpenBSD: я взял дату 29 февраля 2008 года и случайный час (в форме 080229301535) и добавил +1 к дневной части, например:
$ date -j 0802301535
Sat Mar 1 15:35:00 EST 2008
Как видите, дата правильно отформатировала время ...
HTH
Если вам подходит версия date для GNU, почему бы вам не взять исходный код и не скомпилировать его на AIX и Solaris?
http://www.gnu.org/software/coreutils/
В любом случае исходный код должен помочь вам получить правильную арифметику даты, если вы собираетесь писать собственный код.
Кстати, комментарии вроде «это решение хорошее, но вы, конечно, можете заметить, что оно не так хорошо, как могло бы быть. Похоже, никому не пришло в голову возиться с датами при создании Unix». на самом деле нас никуда не денешь. Я обнаружил, что каждое из предложений до сих пор было очень полезным и целевым.
Чтобы выполнить арифметику с датами в UNIX, вы получаете дату в виде числа секунд, прошедших с эпохи UNIX, выполняете некоторые вычисления, а затем конвертируете обратно в формат даты для печати. Команда date должна иметь возможность как дать вам секунды с начала эпохи, так и преобразовать это число обратно в дату для печати. Моя локальная команда даты делает это,
% date -n
1219371462
% date 1219371462
Thu Aug 21 22:17:42 EDT 2008
%
См. Вашу локальную date(1)
страницу руководства. Чтобы увеличить день, добавьте 86400 секунд.
Я сталкивался с этим пару раз. Мои мысли:
- Арифметика даты - всегда боль
- Немного проще использовать формат даты EPOCH
- date в Linux преобразуется в EPOCH, но не в Solaris
- Для портативного решения вам необходимо выполнить одно из следующих действий:
- Установите gnu date на solaris (уже упоминалось, для завершения требуется взаимодействие с человеком)
- Используйте perl для части даты ( большинство установок unix включают perl, поэтому я обычно предполагаю, что это действие не требует дополнительной работы).
Пример сценария (проверяет возраст определенных файлов пользователя, чтобы узнать, можно ли удалить учетную запись):
#!/usr/local/bin/perl
$today = time();
$user = $ARGV[0];
$command="awk -F: '/$user/ {print \$6}' /etc/passwd";
chomp ($user_dir = `$command`);
if ( -f "$user_dir/.sh_history" ) {
@file_dates = stat("$user_dir/.sh_history");
$sh_file_date = $file_dates[8];
} else {
$sh_file_date = 0;
}
if ( -f "$user_dir/.bash_history" ) {
@file_dates = stat("$user_dir/.bash_history");
$bash_file_date = $file_dates[8];
} else {
$bash_file_date = 0;
}
if ( $sh_file_date > $bash_file_date ) {
$file_date = $sh_file_date;
} else {
$file_date = $bash_file_date;
}
$difference = $today - $file_date;
if ( $difference >= 3888000 ) {
print "User needs to be disabled, 45 days old or older!\n";
exit (1);
} else {
print "OK\n";
exit (0);
}
Если вы хотите продолжить работу с awk, вам пригодятся функции mktime и strftime:
BEGIN { dateinit }
{ newdate=daysadd(OldDate,DaysToAdd)}
# daynum: convert DD-MON-YYYY to day count
#-----------------------------------------
function daynum(date, d,m,y,i,n)
{
y=substr(date,8,4)
m=gmonths[toupper(substr(date,4,3))]
d=substr(date,1,2)
return mktime(y" "m" "d" 12 00 00")
}
#numday: convert day count to DD-MON-YYYY
#-------------------------------------------
function numday(n, y,m,d)
{
m=toupper(substr(strftime("%B",n),1,3))
return strftime("%d-"m"-%Y",n)
}
# daysadd: add (or subtract) days from date (DD-MON-YYYY), return new date (DD-MON-YYYY)
#------------------------------------------
function daysadd(date, days)
{
return numday(daynum(date)+(days*86400))
}
#init variables for date calcs
#-----------------------------------------
function dateinit( x,y,z)
{
# Stuff for date calcs
split("JAN:1,FEB:2,MAR:3,APR:4,MAY:5,JUN:6,JUL:7,AUG:8,SEP:9,OCT:10,NOV:11,DEC:12", z)
for (x in z)
{
split(z[x],y,":")
gmonths[y[1]]=y[2]
}
}
В книге Криса Ф. А. Джонсона «Рецепты сценариев оболочки: подход к решению проблем» (ISBN: 978-1-59059-471-1) есть библиотека функций даты, которая может оказаться полезной. Исходный код доступен по адресу http://apress.com/book/downloadfile/2146 (функции даты находятся в Chapter08 / data-funcs-sh внутри tar-файла).