循環遍歷 unix 日期
我有相當基本的任務,但無法找到適當的解決方案。我想將自 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:001265230800
2010-02-03 21:00:00
1296756000
2011-02-03 18:00:001328277600
2012-02-03 15:00:00
1359885600
2013-02-03 11:00:001391403600
2014-02-03 06:00:00
1422918000
2015-02-02 23:00:001454425200
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
所有的歲月都出現了,一切似乎都是正確的。