Bash

循環遍歷 unix 日期

  • August 7, 2016

我有相當基本的任務,但無法找到適當的解決方案。我想將自 2008 年以來的日期間隔迭代到目前,並且每次循環迭代都需要紀元值。我也有興趣迭代兩年、半年和幾個月。

我寫了這樣的腳本

#!/bin/bash
initial_date=`date -d "2008-02-04 00:00:00 UTC" +%s`
end_date=`date +%s`
n=0
until [ $initial_date -gt $end_date ]; do
echo $initial_date
let n+=1
readable_date=`date +"%Y-%m-%d %T" -d "1970-01-01 $initial_date sec"`
echo $readable_date
readable_date=`date -d "$readable_date + $n year"`
initial_date=`date -d "$readable_date" +%s`
done

但它的輸出對我來說很奇怪:

1202083200
2008-02-04 00:00:00
1233702000
2009-02-03 23:00:00

1265230800
2010-02-03 21:00:00
1296756000
2011-02-03 18:00:00

1328277600
2012-02-03 15:00:00
1359885600
2013-02-03 11:00:00

1391403600
2014-02-03 06:00:00
1422918000
2015-02-02 23:00:00

1454425200
2016-02-02 15:00:00

為什麼年份沒有正確增加?在我看來,移動時間似乎是 unix>>UTC>>unix 轉換的副作用。是否有任何直接(無需重新轉換)方法可以做到這一點?

PS
是的,我檢查了這個這個這個問題,發現沒有明確的方法可以做到這一點。它們都是基於遞增數字和在它的幫助下轉換日期,這對我來說似乎並不精確。

是的,我考慮過添加60*60*24*30*365到初始日期,但它是否正確?這種方法不考慮閏年、由 31 天組成的月份等。

使用日期:

$ dateA="2008-02-04 00:00:00 UTC"

獲取具有偏移時間的日期的第一個原因是請求“本地”日期:

$ date -d "$dateA"
Sun Feb  3 19:00:00 EST 2008

如果您指定 UTC 時間,這將得到糾正:

$ TZ=UTC0 date -d "$dateA"
Mon Feb  4 00:00:00 UTC 2008

或者更好(養成使用它的習慣)使用-u日期選項:

$ date -ud "$dateA"
Mon Feb  4 00:00:00 UTC 2008

第二個原因是請求帶有標誌的“相關項目”:

$ date -ud "$(date +"%Y-%m-%d %T" -ud "$dateA") +1 year"  ### wrong
Tue Feb  3 23:00:00 UTC 2009

$ date -ud "$(date +"%Y-%m-%d %T" -ud "$dateA") 1 year"  ### better
Mon Feb  4 00:00:00 UTC 2008

但是當使用“時區”(-z)時,所有時間問題(通常)都會消失:

$ date -ud "$(date +"%Y-%m-%d %T %z" -ud "$dateA") +1 year"  ### Best
Wed Feb  4 00:00:00 UTC 2009

$ date -ud "$(date +"%Y-%m-%d %T %z" -ud "$dateA") 1 year"  ### Preferred
Wed Feb  4 00:00:00 UTC 2009

該問題與解析日期字元串的方式有關,如果缺少 TZ 值,+1 可能會被解釋為時區值:

$ date -ud "2008-02-04 00:00:00 +3 year"
Tue Feb  3 21:00:00 UTC 2009

即使已設置 TZ 的環境值:

$ TZ=UTC0 date -ud "2008-02-04 00:00:00 +3 year"
Tue Feb  3 21:00:00 UTC 2009

是的,年份增加了一次(2009 年而不是 2008 年),但+3用於更改呈現的時間(不是預期的)。

我再說一遍:問題是+3可能會被解析為時區值。


此外,要將(紀元)秒轉換為日期,GNU 日期可以使用“@”

$ dateAsec="$( date -ud "$dateA" +"%s" )

$ date -ud @"$dateAsec"
Mon Feb  4 00:00:00 UTC 2008

腳本(使用 (newdate) 函式)可以這樣編寫:

#!/bin/bash
dateI="$(date -ud "2008-02-04 00:00:00 UTC" +%s)"
dateF="$(date -u +%s)"

newdate(){ date -ud "$(date +"%Y-%m-%d %T %z" -ud @"$dateI") $1 year" +"%s"; }

n=0
while 
   dateN="$( newdate "$n" )"
   (( dateN < dateF ));
do
   dateNhuman="$(date +"%Y-%m-%d %T %z" -ud @"$dateN")"
   echo "dateN=$dateN --- $dateNhuman ---> $dateF $(( $dateF - $dateN )) $n"
   (( n++ ))
done

結果:

dateN=1202083200 --- 2008-02-04 00:00:00 +0000 ---> 1470543626 268460426 0
dateN=1233705600 --- 2009-02-04 00:00:00 +0000 ---> 1470543626 236838026 1
dateN=1265241600 --- 2010-02-04 00:00:00 +0000 ---> 1470543626 205302026 2
dateN=1296777600 --- 2011-02-04 00:00:00 +0000 ---> 1470543626 173766026 3
dateN=1328313600 --- 2012-02-04 00:00:00 +0000 ---> 1470543626 142230026 4
dateN=1359936000 --- 2013-02-04 00:00:00 +0000 ---> 1470543626 110607626 5
dateN=1391472000 --- 2014-02-04 00:00:00 +0000 ---> 1470543626 79071626 6
dateN=1423008000 --- 2015-02-04 00:00:00 +0000 ---> 1470543626 47535626 7
dateN=1454544000 --- 2016-02-04 00:00:00 +0000 ---> 1470543626 15999626 8

所有的歲月都出現了,一切似乎都是正確的。

引用自:https://unix.stackexchange.com/questions/301743