Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 每月正确减少一个日期_Linux_Bash_Shell_Date_Datetime - Fatal编程技术网

Linux 每月正确减少一个日期

Linux 每月正确减少一个日期,linux,bash,shell,date,datetime,Linux,Bash,Shell,Date,Datetime,我有一个简单的代码,它是工作,但不是预期的。我的代码的主要建议是将给定日期缩短到目标日期2012-01-31 但结果是: 2017-10-28 2017-09-28 2017-08-28 2017-07-28 2017-06-28 2017-05-28 2017-04-28 2017-03-28 2017-02-28 2017-01-28 2016-12-28 2016-11-28 2016-10-28 2016-09-28 2016-08-28 2016-07-28 2016-06-28 20

我有一个简单的代码,它是工作,但不是预期的。我的代码的主要建议是将给定日期缩短到目标日期2012-01-31

但结果是:

2017-10-28
2017-09-28
2017-08-28
2017-07-28
2017-06-28
2017-05-28
2017-04-28
2017-03-28
2017-02-28
2017-01-28
2016-12-28
2016-11-28
2016-10-28
2016-09-28
2016-08-28
2016-07-28
2016-06-28
2016-05-28
2016-04-28
2016-03-28
2016-02-28
2016-01-28
...
守则:

#!/bin/bash

d=2017-10-31
while [ "$d" != 2012-01-31 ]; do 
  echo $d
  d=$(date -I -d "$d -1 month")
done
我真的希望能有正确的月份,比如:

2017-10-31
2017-09-30
2017-08-31
2017-07-31
2017-06-30
2017-05-31
2017-04-30
2017-03-31
2017-02-28
2017-01-31
2016-12-31
2016-11-30
2016-10-31
2016-09-30
2016-08-31
2016-07-31
2016-06-30
2016-05-31
2016-04-30
2016-03-31
2016-02-29
2016-01-31
...

我怎样才能做到这一点呢?

也许你可以减去当前月份的天数,而不是减去一个月(因为这种行为而臭名昭著)

!/bin/bash

d=2017-10-31
while [ "$d" != 2012-01-31 ]; do
  echo $d
  days_in_month==$(cal $(date +"%m %Y" -d $d) | awk 'NF {DAYS = $NF}; END {print DAYS}')
  d=$(date -I -d "$d $days_in_month day ago")
done

也许你可以减去当前月份的天数,而不是减去一个月(这种行为是臭名昭著的)

!/bin/bash

d=2017-10-31
while [ "$d" != 2012-01-31 ]; do
  echo $d
  days_in_month==$(cal $(date +"%m %Y" -d $d) | awk 'NF {DAYS = $NF}; END {print DAYS}')
  d=$(date -I -d "$d $days_in_month day ago")
done

假设您的开始日期始终是当月的最后一天,如果使用此算法,您可以让
date
计算每月的天数:

date = date +1 day -1 month -1 day
也就是说,首先将日期翻转到下个月的第一天,然后只需减去一个月即可得到当月的第一天,最后只需减去一天即可得到上个月的最后一天

例如:

#!/bin/bash
d=2017-10-31
while [ "$d" != 2012-01-31 ]; do 
    echo $d
    d=$(date -I -d "$(date -I -d "$(date -I -d "$d +1 day") 1 month ago") 1 day ago")
done
注:使用
1天前
代替
-1天
,因为后者可以通过
日期
解释为时区(已知的gotcha)


或者,您可以手动将日期设置为
01
(使用shell的参数展开),然后简单地用
日期减去
1天

d=2017-10-31
while [ "$d" != 2012-01-31 ]; do 
    echo $d
    d=$(date -I -d "${d%-*}-01 1 day ago")
done

输出为(在两种情况下):


假设您的开始日期始终是当月的最后一天,如果使用此算法,您可以让
date
计算每月的天数:

date = date +1 day -1 month -1 day
也就是说,首先将日期翻转到下个月的第一天,然后只需减去一个月即可得到当月的第一天,最后只需减去一天即可得到上个月的最后一天

例如:

#!/bin/bash
d=2017-10-31
while [ "$d" != 2012-01-31 ]; do 
    echo $d
    d=$(date -I -d "$(date -I -d "$(date -I -d "$d +1 day") 1 month ago") 1 day ago")
done
注:使用
1天前
代替
-1天
,因为后者可以通过
日期
解释为时区(已知的gotcha)


或者,您可以手动将日期设置为
01
(使用shell的参数展开),然后简单地用
日期减去
1天

d=2017-10-31
while [ "$d" != 2012-01-31 ]; do 
    echo $d
    d=$(date -I -d "${d%-*}-01 1 day ago")
done

输出为(在两种情况下):


在不检查日期的情况下,生成月初和获取月底的小技巧更容易

$ d=2017-10-31; bd=$(date -I -d "$d +1 month");   
  while [ $d != 2012-01-31 ];        
  do 
      bd=$(date -I -d "$bd - 1 month");           
      d=$(date -I -d "$bd - 1 day");  
      echo $d;
  done

2017-10-31
2017-09-30
2017-08-31
2017-07-31
...  
2016-07-31
2016-06-30
2016-05-31
2016-04-30
2012-03-31
2012-02-29
2012-01-31

在不检查日期的情况下,生成月初和获取月底的小技巧更容易

$ d=2017-10-31; bd=$(date -I -d "$d +1 month");   
  while [ $d != 2012-01-31 ];        
  do 
      bd=$(date -I -d "$bd - 1 month");           
      d=$(date -I -d "$bd - 1 day");  
      echo $d;
  done

2017-10-31
2017-09-30
2017-08-31
2017-07-31
...  
2016-07-31
2016-06-30
2016-05-31
2016-04-30
2012-03-31
2012-02-29
2012-01-31