UNIX中用于减去日期的工具


22

Solaris UNIX中是否有任何工具(因此没有可用的GNU工具)来减去日期?我知道在Linux中,我们gawk可以从另一个日期中减去一个日期。但是在Solaris中,我们拥有的最大值nawk(已改进awk)无法执行日期计算。我也不能使用perl。

有什么办法可以进行日期计算20100909 - 20001010吗?

更新:bc能够执行日期计算吗?


1
另请参阅快速计算日期差异,以获取GNU日期何时可用。
吉尔(Gilles)'所以

Answers:


10

这是我刚刚编写的awk脚本,应该与POSIX awk一起使用。您必须尝试使用​​Solaris版本;请记住,Solaris上也有两种版本的Awk,一个在/ bin中,一个在/ usr / xpg4 / bin / awk中(我相信它是nawk)。

BEGIN {
    daysofmonth["01"] = 0; daysofmonth["02"] = 31; daysofmonth["03"] = 59;
    daysofmonth["04"] = 90; daysofmonth["05"] = 120; daysofmonth["06"] = 151;
    daysofmonth["07"] = 181; daysofmonth["08"] = 212; daysofmonth["09"] = 243;
    daysofmonth["10"] = 273; daysofmonth["11"] = 304; daysofmonth["12"] = 334;
    fullday = 86400;
}
/[12][09][0-9][0-9][01][0-9][0123][0-9]/ {
    year = substr($0, 1, 4); month = substr($0, 5, 2); day = substr($0, 7, 2);
    date = ((year - 1970) * 365.25) + daysofmonth[month] + day - 1;
    if ((year % 4) == 0 && month > 2) { date = date + 1; }
    print date * fullday - (25200);
}
{}

传递一个YYYYmmdd日期字符串,它将转换为自大纪元以来的秒数(有点可能会超出日期)。然后,您将能够减去两者。

today=`echo 20110210 | awk -f convdate.awk`
then=`echo 20001231 | awk -f convdate.awk`
sincethen=`expr $today - $then`

我检查了您与Oracle的逻辑。某些日期还可以,但是会生成一个浮点数。恐怕我必须截断为整数,是吗?
jyz 2011年

小数点是几分之一秒,不一定需要。
Arcege 2011年

这个纪元到期20380119。为什么不使用一年中的儒略日呢?杜佩... unix.stackexchange.com/questions/302266/...
jas-

13

不幸的是,没有POSIX命令行实用程序提供日期运算。date -d并且date +%s是如果你有他们的路要走,但他们是GNU扩展。

有一种笨拙的骇客程序,touch用于检查日期是否过去至少n天:

touch -t 201009090000 stamp
if [ -n "$(find stamp -mtime +42)" ]; then ...

(请注意,如果DST在该时间间隔内启动或停止并且脚本在凌晨1点之前运行,则此代码可能会关闭一个。)

许多人最终在Bourne或POSIX shell中实现了日期操作库。在comp.unix.shell FAQ中有一些示例和链接。

安装GNU工具可能是最省力的方法。


11

我会尝试使用datePOSIX中包含的命令,因此它随处可见。更新:不幸的是,-d似乎不是POSIX日期的一部分,并且可能不在Solaris上。因此,这可能无法回答OP的问题。

d1=`date -d 20100909 +%s`
d2=`date -d 20001010 +%s`

现在d1d2是与unix纪元以来的秒数相对应的整数。因此,为了获得两者之间的差异,我们减去($((d1-d2))以bash表示)并隐式转换为我们想要的任何单位。天是最简单的:

echo "$(((d1-d2)/86400)) days"

如果没有bash,转换方式可能会有所不同。最可移植的方法可能是使用exprexpr的posix手册页)。


是的,这不能回答我的问题,因为它是Solaris ...但是感谢您的想法和发布:)
jyz 2010年

8

作为记录,dateutils是我尝试提供一组涵盖日期算术的可移植工具。您的示例可以归结为

ddiff -i '%Y%m%d' 20001010 20100909
=>
  3621

-i指定的输入格式。


2
这个软件包很棒,它存在于Ubuntu Universe库中(至少对于Trusty)。在另一个系统上,我可以轻松地从头开始编译它。强烈推荐。非常感谢你!
罗伯特·缪尔

还包装在Fedora和EPEL中,用于RH生态系统。
mattdm


3

在Solaris上Wrt GNU日期:

我再说一次:

太多的Solaris SysAdmin管理员为没有故意从Sun(现在为Oracle)安装官方软件包而感到自豪,这些软件包在配置新主机时使Solaris系统“兼容GNU”。击败我为什么。

GNU Date非常出色,并且默认情况下应在任何Solaris主机IMHO上可用。

在Solaris 10上

从Solaris Companion CD安装软件包SFWcoreu。安装后,您会在以下位置找到GNU日期/opt/sfw/bin/date

在Solaris 11上

您可能已经拥有它,因为我认为它是标准安装的一部分。但是gdate,为了将其与日期的Sun版本区分开来而将其称为。

如果未安装,请执行以下操作:

pkg install // solaris / file / gnu-coreutils

谢谢你的提示。能给我一个使用方法的例子吗?因此,我可以要求sysadmin安装它...
jyz

在Solaris 11上,它将同时安装/usr/bin/gdate/usr/gnu/bin/date因此您可以选择按名称或$ PATH设置使用它。
alanc

2

如果您有Python:

from time import *
date1 = strptime("20100909","%Y%m%d")
date2 = strptime("20001010","%Y%m%d")
diff = mktime(date1) - mktime(date2)
print repr(d/86400) + " days"

您将问题标记为“ gawk”,但是却说“没有GNU工具”。Gawk具有日期算术。


我没有 有人编辑了我的帖子并标记为“ gawk” ...
jyz 2010年

2

蟒蛇:

 from datetime import datetime as dt
 a = dt(2010, 9, 9)
 b = dt(2000, 10, 10)
 print (a - b).days

1

1. %j以年中的日期(001..366)格式定义date1和date2

user@linux:~$ date1=`date -d 20100909 +%j` 
user@linux:~$ date2=`date -d 20001010 +%j`

2.计算与 expr

user@linux:~$ datediff=`expr $date2 - $date1`

3.因此,答案是32天

user@linux:~$ echo $datediff days
32 days
user@linux:~$ 

...或单线解决方案

user@linux:~$ echo $(( $(date -d 20001010 +%j) - $(date -d 20100909 +%j) )) days
32 days
user@linux:~$ 

要么

user@linux:~$ expr $(date -d 20001010 +%j) - $(date -d 20100909 +%j)
32
user@linux:~$

要么

user@linux:~$ expr `date -d 20001010 +%j` - `date -d 20100909 +%j`
32
user@linux:~$ 

0

带有日期BSD for macOS:

echo "Quelle est la date de début ?"
read DATE_DE_DEBUT
echo "Quelle est la date de fin ?"
read DATE_DE_FIN
ANNEE=$(($(echo $DATE_DE_FIN | awk -F "/" '{print $3}')-$(echo $DATE_DE_DEBUT  | awk -F "/" '{print $3}')))

echo " "

if [[ $ANNEE > 0 ]]; then

for((annee=$ANNEE-1 ; $ANNEE ; annee++))

  do
  #echo $annee  
  for((mois=0 ; 13 - $mois ; mois++))
      do
  #   echo année:$annee mois:$mois
          for((jour=0 ; 32 - $jour ; jour++))
              do
 #             echo année:$annee mois:$mois jour:$jour
           TEST=$(date -Rjf"%d/%m/%Y" -v +"$annee"y -v +"$mois"m -v +"$jour"d $DATE_DE_DEBUT +"%d/%m/%Y")
           if [[ $TEST = $DATE_DE_FIN ]]; then
                  echo "Différence entre le $DATE_DE_DEBUT et le $DATE_DE_FIN";
                  echo "est de :";
                  echo "$annee année(s) $mois mois $jour jour(s)";
             exit 0;
            fi


          done 
  done
  done

 else 
 annee=0
 for((mois=0 ; 13 - $mois ; mois++))
      do
#      echo année:$annee mois:$mois
          for((jour=0 ; 32 - $jour ; jour++))
              do
              #echo année:$annee mois:$mois jour:$jour
              TEST=$(date -Rjf"%d/%m/%Y" -v +"$annee"y -v +"$mois"m -v +"$jour"d $DATE_DE_DEBUT +"%d/%m/%Y")
              if [[ $TEST = $DATE_DE_FIN ]]; then 
                      echo "Différence entre le $DATE_DE_DEBUT et le $DATE_DE_FIN";
                     echo "est de :";
                     echo "$annee année(s) $mois mois $jour jour(s)";
              exit 0;
              fi
              done
      done

fi

0

您可以使用awk Velor库以秒为单位返回差异:

$ velour -n 'print t_utc(2010, 9, 9) - t_utc(2000, 10, 10)'
312854400

或天数:

$ velour -n 'print t_secday(t_utc(2010, 9, 9) - t_utc(2000, 10, 10))'
3621
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.