यूनिक्स शैल स्क्रिप्ट में अंकगणित दिनांक

मुझे यूनिक्स शैल स्क्रिप्ट्स में अंकगणित करने की आवश्यकता है जिसे मैं तीसरे पक्ष के कार्यक्रमों के निष्पादन को नियंत्रित करने के लिए उपयोग करता हूं।

मैं एक दिन और दूसरे को बढ़ाने के लिए एक समारोह का उपयोग कर रहा हूं:

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

लेकिन अब मुझे और अधिक जटिल अंकगणित करने की जरूरत है।

ऐसा करने का सबसे अच्छा और अधिक संगत तरीका क्या है?

0
ro fr bn

14 उत्तर

अपनी लिपियों को पर्ल या पायथन जैसी भाषा का उपयोग क्यों न करें, इसके बजाय जटिल तारीख प्रसंस्करण का अधिक स्वाभाविक रूप से समर्थन करता है? निश्चित रूप से आप इसे कर सकते हैं सभी को बैश में कर सकते हैं, लेकिन मुझे लगता है कि उदाहरण के लिए पाइथन का उपयोग करके आप प्लेटफॉर्म पर अधिक स्थिरता प्राप्त करेंगे, जब तक आप यह सुनिश्चित कर सकें कि पर्ल या पायथन स्थापित है।

मुझे यह जोड़ना चाहिए कि पाइथन और पर्ल स्क्रिप्ट में एक युक्त शेल स्क्रिप्ट में तार करना काफी आसान है।

0
जोड़ा
मैं जस्टिन से सहमत हूं और आपकी स्क्रिप्ट के लिए एक बेहतर टूल / भाषा का उपयोग करने की सलाह देता हूं। मैं शायद पर्ल के साथ जाऊंगा क्योंकि यह बॉक्स के बाहर अधिकांश यूनिक्स सिस्टम पर स्थापित है। पाइथन, जबकि अधिक आधुनिक, आपको इसे पहले स्थापित करने की आवश्यकता है, जो दर्द या यहां तक ​​कि राजनीतिक रूप से असंभव हो सकता है।
जोड़ा लेखक markus_b, स्रोत
date --date='1 days ago' '+%a'

यह एक बहुत ही अनुकूल समाधान नहीं है। यह केवल लिनक्स में काम करेगा। कम से कम, यह ऐक्स और सोलारिस में काम नहीं किया।

यह आरएचईएल में काम करता है:

date --date='1 days ago' '+%Y%m%d'
20080807
0
जोड़ा

मान लें कि आपके पास जीएनयू दिनांक है, जैसे:

date --date='1 days ago' '+%a'

और समान वाक्यांश

0
जोड़ा
जिस पर यूनिक्स (यूनिस?) यह काम करता है?
जोड़ा लेखक Johnsyweb, स्रोत
उपयोगी कार्यक्षमता को खोजना बहुत अच्छा है जो दिन को बचाता है, अन्यथा मुंडे आदेश में। यूनिक्स कमांड लाइन हमेशा के लिए।
जोड़ा लेखक Thalis K., स्रोत
निश्चित रूप से बीएसडी की तारीख के साथ काम नहीं करता है, जो ओएस एक्स के साथ स्थापित है। होमब्री जैसे कुछ के साथ कोरुटिल स्थापित करना जीएनयू संस्करण बनाता है जो इन एक्सटेंशन को जीडीएटी के रूप में उपलब्ध कराता है।
जोड़ा लेखक sj26, स्रोत
एक डबल अप देना चाहता था !! :-) इस पर इतना समय बर्बाद कर दिया! :-( आपका धन्यवाद! :-)
जोड़ा लेखक Senthil Kumar, स्रोत
लिनक्स पर काम करने के लिए प्रकट होता है। अगर मैं जीएनयू एक्सटेंशन था तो मुझे आश्चर्य नहीं होगा। यह मनमाने ढंग से तारीखों से मनमाने ढंग से रकम को ऑफसेट करने के लिए भी काम करता है, उदाहरण के लिए, "date --date = '2012-01-27 - 30 दिन'"
जोड़ा लेखक Joseph Garvin, स्रोत

इसे आगे देखकर, मुझे लगता है कि आप बस तारीख का उपयोग कर सकते हैं। मैंने ओपनबीएसडी पर निम्नलिखित की कोशिश की है: मैंने 2 9 फरवरी 2008 की तारीख और एक यादृच्छिक घंटा (08022 9 301535 के रूप में) लिया और दिन के दिन +1 जोड़ा, जैसे:

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

जैसा कि आप देख सकते हैं, तिथि सही ढंग से स्वरूपित ...

HTH

0
जोड़ा

यदि तिथि का जीएनयू संस्करण आपके लिए काम करता है, तो आप स्रोत को क्यों नहीं लेते हैं और इसे AIX और Solaris पर संकलित क्यों नहीं करते?

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

किसी भी मामले में, स्रोत आपको अंकगणित सही तिथि प्राप्त करने में मदद करनी चाहिए यदि आप अपना कोड लिखने जा रहे हैं।

एक तरफ, टिप्पणियां जैसे "वह समाधान अच्छा है लेकिन निश्चित रूप से आप ध्यान दे सकते हैं कि यह उतना अच्छा नहीं है जितना हो सकता है। ऐसा लगता है कि यूनिक्स का निर्माण करते समय कोई भी तारीखों के साथ झुकाव करने का विचार नहीं करता।" वास्तव में हमें कहीं भी नहीं मिलता है। मैंने सुझावों में से प्रत्येक को बहुत उपयोगी और लक्ष्य पर पाया है।

0
जोड़ा

यूनिक्स पर तारीखों के साथ अंकगणित करने के लिए आपको यूनिक्स युग के बाद से संख्या सेकंड के रूप में तारीख मिलती है, कुछ गणना करें, फिर अपने प्रिंट करने योग्य दिनांक प्रारूप में वापस कनवर्ट करें। दिनांक कमांड आपको युग के बाद से सेकंड देने में सक्षम होना चाहिए और उस नंबर से वापस प्रिंट करने योग्य तिथि में कनवर्ट करना चाहिए। मेरा स्थानीय दिनांक कमांड यह करता है,

% date -n
1219371462
% date 1219371462
Thu Aug 21 22:17:42 EDT 2008
% 

अपनी स्थानीय दिनांक (1) मैन पेज देखें। एक दिन में वृद्धि करने के लिए 86400 सेकंड जोड़ें।

0
जोड़ा

मैंने इसमें कुछ बार टक्कर लगी है। मेरे विचार हैं:

  1. Date arithmetic is always a pain
  2. It is a bit easier when using EPOCH date format
  3. date on Linux converts to EPOCH, but not on Solaris
  4. For a portable solution, you need to do one of the following:
    1. Install gnu date on solaris (already mentioned, needs human interaction to complete)
    2. Use perl for the date part (most unix installs include perl, so I would generally assume that this action does not require additional work).

एक नमूना स्क्रिप्ट (यह देखने के लिए कि क्या खाता हटाया जा सकता है, कुछ उपयोगकर्ता फ़ाइलों की उम्र के लिए जांच करता है):

#!/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);
}
0
जोड़ा

यदि आप अजीब के साथ जारी रखना चाहते हैं, तो 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]
     }
}
0
जोड़ा
लेकिन, जैसा कि मैंने अभी पाया है, एमकेटाइम गॉक है, और सौर पर अजीब / नॉक पर नहीं है :(
जोड़ा लेखक Joe Watkins, स्रोत

क्रिस एफए जॉनसन द्वारा "शेल स्क्रिप्ट रेसिपीज़: ए प्रॉब्लम सॉल्यूशन दृष्टिकोण" (आईएसबीएन: 978-1-59059-471-1) पुस्तक है, जो एक तिथि कार्य पुस्तकालय है जो सहायक हो सकती है। स्रोत कोड http://apress.com/book/downloadfile/2146 पर उपलब्ध है ( दिनांक फ़ंक्शन अध्याय 08 / डेटा-funcs-sh में टैर फ़ाइल के भीतर हैं)।

0
जोड़ा

मैंने पारंपरिक रूप से अंग्रेजी में व्यक्त की गई तिथियों को परिवर्तित करने के लिए एक बैश स्क्रिप्ट लिखी है मिमी / डीडी / yyyy तिथियां। इसे 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

मैंने इस स्क्रिप्ट को इस समस्या के उत्तर के रूप में शामिल किया है क्योंकि यह दिखाता है कि कैसे बैश फ़ंक्शंस के सेट के माध्यम से अंकगणित करने के लिए और ये फ़ंक्शन उपयोगी साबित हो सकते हैं दूसरो के लिए। यह छलांग साल को संभालने और सदियों को सही ढंग से छलांग लगाता है:

#! /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 $Dat
0
जोड़ा
सबसे सरल समाधान के लिए मेरा जवाब देखें।
जोड़ा लेखक Harun Prasad, स्रोत

शैल स्क्रिप्टिंग में दिनांक गणना करने का एक आसान तरीका यहां है।

meetingDate='12/31/2011' # MM/DD/YYYY Format
reminderDate=`date --date=$meetingDate'-1 day' +'%m/%d/%Y'`
echo $reminderDate

Below are more variations of date computation that can be achieved using date utility. http://www.cyberciti.biz/tips/linux-unix-get-yesterdays-tomorrows-date.html http://www.cyberciti.biz/faq/linux-unix-formatting-dates-for-display/

यह मेरे लिए आरएचईएल पर काम किया।

0
जोड़ा
+1 यह अंकगणित करने के लिए मुझे यही चाहिए। बहुत आसान और सीधा। मैंने एम / डी / वाई ऑर्डर को सही किया।
जोड़ा लेखक Erick Robertson, स्रोत

यहां मेरे दो पेनी लायक हैं - एक स्क्रिप्ट रैपर 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 ""  
#
#  ::= see "man date", section "DATE STRING"
#  ::= + | -
#  ::= INTEGER | INTEGER
#  ::= 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
जोड़ा

बीएसडी / ओएस एक्स संगतता के लिए, आप दिनांक गणित करने के लिए -j और -v के साथ दिनांक उपयोगिता का भी उपयोग कर सकते हैं। दिनांक के लिए फ्रीबीएसडी मैनपेज देखें। आप पिछले लिनक्स उत्तरों को इस उत्तर के साथ जोड़ सकते हैं जो आपको पर्याप्त संगतता प्रदान कर सकता है।

बीएसडी पर, लिनक्स के रूप में, date चल रहा है आपको वर्तमान दिनांक देगा:

$ date
Wed 12 Nov 2014 13:36:00 AEDT

अब बीएसडी की तारीख के साथ आप -v के साथ गणित कर सकते हैं, उदाहरण के लिए कल की तारीख सूचीबद्ध करना ( + 1d प्लस एक दिन है):

$ date -v +1d
Thu 13 Nov 2014 13:36:34 AEDT

आप आधार के रूप में मौजूदा दिनांक का उपयोग कर सकते हैं, और वैकल्पिक रूप से स्ट्रैटाइम का उपयोग करके पार्स प्रारूप निर्दिष्ट कर सकते हैं, और सुनिश्चित कर सकते हैं कि आप -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

अधिक जानकारी के लिए मैनपेज देखें।

0
जोड़ा
जादू के लिए धन्यवाद!
जोड़ा लेखक Yoga, स्रोत

यह मेरे लिए काम करता है:

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
जोड़ा