基于yyymm的日期差异在unix中

时间:2016-11-13 12:30:32

标签: shell unix

#####DATE1=201609
#### DATE2=201508

如何计算这两个日期之间的差异,并将输出作为月份的计数 即

201609-201508=13month

3 个答案:

答案 0 :(得分:2)

时差的计算通常是一项复杂的任务,即使对于单个日历类型(并且有many)也是如此。许多编程语言都内置了对日期和时间操作操作的支持,包括计算时差。但是,流行的shell中最有用的功能是date命令,遗憾的是缺少此功能。

因此,我们应该用另一种语言编写脚本,还是做出一些假设,例如一年中的天数。

例如,在Perl中,任务仅使用四行代码完成:

perl -e $(cat <<'PerlScript'
use Time::Piece;
my $t1 = Time::Piece->strptime($ARGV[0], '%Y%m');
my $t2 = Time::Piece->strptime($ARGV[1], '%Y%m');
printf "%d months\n", ($t1 - $t2)->months;
PerlScript
) 201609 201508

然而,Time::Piece个对象的差异是Time::Seconds的一个实例,它实际上假设

  

一天24小时,一周7天,一天365.24225天   一年一年和一年12个月。

间接证实了我关于任务复杂性的说法。

然后让我们做出相同的假设,并编写一个简单的 shell 脚本:

DATE1=201609
DATE2=201508

printf '(%d - %d) / 2629744.2\n' \
  $(date -d ${DATE1}01 +%s) \
  $(date -d ${DATE2}01 +%s) | bc

其中2629744.2是月中的秒数,即3600 * 24 * (365.24225 / 12)

注意,大多数shell不支持浮点运算。这就是我们需要调用bc等外部工具的原因。

脚本输出13。这是一个便携版本。例如,您可以在标准shell,Bash,Korn shell或Zsh中运行它。如果要将结果放入变量,只需将printf命令包装在$( ... )中:

months=$(printf '(%d - %d) / 2629744.2\n' \
  $(date -d ${DATE1}01 +%s) \
  $(date -d ${DATE2}01 +%s) | bc)

printf '%d - %d = %d months\n' $DATE1 $DATE2 $months

答案 1 :(得分:0)

您可以尝试以下解决方案 -

[vipin@hadoop ~]$ cat time.awk
{
diff1=((substr($1,1,4)) - (substr($2,1,4)))
diff2=((substr($1,5,2)) - (substr($2,5,2)))
if(diff1 > 0)
        {
        if(diff2 > 0)
                {
                print (diff1+diff2)
                }
        else if (diff2 = 0)
                {
                print (diff1+diff2)
                }
                else
                {
                diff2=(12+((substr($1,5,2)-(substr($2,5,2)))))
                diff1=(diff1-1)
                print (diff1+diff2)
                }
        }
else if(diff1 == 0)
        {
        if(diff2 > 0)
                {
                print (diff1+diff2)
                }
        else if (diff2 == 0)
                {
                print (diff1+diff2)
                }
        else
                {
                 print "Argument 2 is greater than 1"
                }
        }
else
        {
        print "Argument 2 is greater than 1"
        }
}
  

测试用例 -

[vipin@hadoop ~]$ cat time1.txt && awk -f time.awk time1.txt
201611 201601
10
[vipin@hadoop ~]$ cat time2.txt && awk -f time.awk time2.txt
201601 201611
Argument 2 is greater than 1
[vipin@hadoop ~]$ cat time3.txt && awk -f time.awk time3.txt
201511 201601
Argument 2 is greater than 1
[vipin@hadoop ~]$ cat time4.txt && awk -f time.awk time4.txt
201611 201611
0

答案 2 :(得分:0)

让我们尝试一些快速而肮脏的东西,这对历史上的所有月都无效,但它可能已经足够好了:将YYYYMM转换为自0年以来的月数:

$ ym2m() { 
    if [[ $1 =~ ^([0-9]{4})([0-9]{2})$ ]]; then 
        echo $(( 10#${BASH_REMATCH[1]} * 12 + 10#${BASH_REMATCH[2]} ))
    else 
        return 1
    fi
}

$ ym2m 201609
24201

$ ym2m 201508
24188

$ echo $(( $(ym2m 201609) - $(ym2m 201508) ))
13

注意:

  • 需要bash版本4.3(我认为)
  • ym2m =&gt; “年月到月”
  • 在算术表达式中使用10#number以确保“08”和“09”不被视为无效的八进制数。