Linux、DSTセーフのbashで昨日の日付を取得する


158

Linuxで実行するシェルスクリプトがあり、この呼び出しを使用して昨日の日付を取得します YYYY-MM-DD形式でます。

date -d "1 day ago" '+%Y-%m-%d'

ほとんどの場合それは機能しますが、スクリプトが昨日の朝実行された2013-03-11 0:35 CDTときに戻りました"2013-03-09"なくました"2013-03-10"

おそらく、(昨日から始まった)夏時間のせいです。私は"1 day ago"それが実装されている方法が24時間減算された方法を推測し、24時間前2013-03-11 0:35 CDTはそれでした2013-03-09 23:35 CST、それはの結果につながりました"2013-03-09"

では、Linuxのbashで昨日の日付を取得するためのDSTセーフの優れた方法は何でしょうか。


常にこれを同時に実行していますか、繰り返し実行していますか?
2013年

@tink毎日00:35に実行
Ike Walker

回答:


267

実行する頻度とタイミングに関係なく、これはうまくいくと思います...

date -d "yesterday 13:00" '+%Y-%m-%d'

1
これを後で使用するために変数にどのように割り当てますか?
null

6
@null-他のシェルコマンドの出力を割り当てるのと同じ方法。変数= $ ...(日付は"昨日の夜01時00" '+%Y-%m-%d'では-d)
ティンク

GNU-dateの場合:date -d yesterday 13:00 -I
gogstad 2017年

私が正しく理解していれば、夏時間と冬時間の切り替えは常に夜間に行われるという事実に依存していますか?
Nicolas Raoul

2
@NicolasRaoul:保証されません。ただし、これを早朝にスケジュールすることは、広く行われている規則です。一方、IIRCには、スイッチがローカルの正午の近く​​で発生する場所はありません。したがって、「1300JがDST境界上にあることはありません」は妥当な仮定です。
Piskvorは

56

Mac OSXでの日付は少し異なります。

昨日

date -v-1d +%F

先週

date -v-1w +%F

8
OSX内でGNUスタイルを使用することに関心がある場合はgdate、homebrewのcoreutilsパッケージ内にあるを使用することもできます。
user456584 2014年

11
つまりdate、違います。
オーグラ2016年

12

これも機能するはずですが、多すぎるかもしれません。

date -d @$(( $(date +"%s") - 86400)) +"%Y-%m-%d"

構文をdateサポートしていないMac OS Xに対処する必要がある場合は、このようなものが必要ですyesterday...
Mikko Rantalainen '22

7

スクリプトが1日の最初の時間に実行されることが確実な場合は、次のようにすることができます。

  date -d "12 hours ago" '+%Y-%m-%d'

ところで、スクリプトが毎日crontabを介して00:35に実行される場合、DSTの変更がその時間に該当するとどうなるかを自問する必要があります。スクリプトを実行できなかったか、場合によっては2回実行できました。近代的な実装がcronされている非常に賢いが、この点で。


5

あなたは使うことができます

date -d "30 days ago" +"%d/%m/%Y"

30日前の日付を取得するには、同様に30をx日で置き換えることができます


%Y%m%d質問に一致するように形式を変更する必要があります。それがきちんと動いたので私はとにかく賛成票を投じた。
isapir

4

ここでは、SolarisとAIXでも機能するソリューションを紹介します。

タイムゾーンの操作は、クロックを数時間変更するために可能です。夏時間のため、24時間前は今日または昨日の前日になります。

昨日は20または30時間前です。どれ?さて、今日ではない最新のもの。

echo -e "$(TZ=GMT+30 date +%Y-%m-%d)\n$(TZ=GMT+20 date +%Y-%m-%d)" | grep -v $(date +%Y-%m-%d) | tail -1

echoコマンドで使用される-eパラメーターはbashで必要ですが、kshでは機能しません。kshでは、-eフラグなしで同じコマンドを使用できます。

スクリプトをさまざまな環境で使用する場合は、#!/ bin / kshまたは#!/ bin / bashでスクリプトを開始できます。\ nを改行で置き換えることもできます。

echo "$(TZ=GMT+30 date +%Y-%m-%d)
$(TZ=GMT+20 date +%Y-%m-%d)" | grep -v $(date +%Y-%m-%d) | tail -1

0

使用してdate、信頼できる秒数:

あなたが正しく指摘しているように、英語の時間計算に依存している場合、基礎となる計算に関する詳細の多くは隠されています。たとえば-d yesterday-d 1 day ago動作が異なります。

代わりに、UNIXエポックUTC以降の(正確に文書化された)秒に確実に依存し、必要な瞬間を取得するためにbash演算を実行できます。

date -d @$(( $(date +"%s") - 24*3600)) +"%Y-%m-%d"

これは別の答えで指摘されました。このフォームはdate、コマンドラインフラグが異なるプラットフォーム間でより移植性が高く、言語に依存しません(たとえば、フランス語のロケールでは「昨日」と「それ以上」)。率直に言って(長期的に)覚えやすいでしょう。すでに知っています。あなたは、そうでない場合は、自分自身を求め続けるかもしれません:「それがあった-d 2 hours agoか、-d 2 hour ago再び?」または「それです-d yesterday-d 1 day ago私がしたいこと?」)。ここで唯一トリッキーなのはです@

bashで武装し、他には何もない:

bashだけでbashを実行すると、組み込みのprintfを介して昨日の時刻を取得することもできます。

 %(datefmt)T
     causes printf to output the date-time string resulting from using
     datefmt as a format string for strftime(3).  The  corresponding  argu
     ment  is an integer representing the number of seconds since the
     epoch.  Two special argument values may be used: -1 represents the
     current time, and -2 represents the time the shell was invoked.
     If no argument is specified, conversion behaves as if -1 had
     been  given.
     This is an exception to the usual printf behavior.

そう、

# inner printf gets you the current unix time in seconds
# outer printf spits it out according to the format
printf "%(%Y-%m-%d)T\n" $(( $(printf "%(%s)T" -1) - 24*3600 ))

または、temp変数と同等です(外部サブシェルはオプションですが、環境変数をクリーンに保ちます)。

(
  now=$(printf "%(%s)T" -1);
  printf "%(%Y-%m-%d)T\n" $((now - 24*3600));
)

注:%()Tフォーマッターへの引数はデフォルトを想定しないとマンページに記載されていますが、-1代わりに0を取得するようです(ありがとう、bashマニュアルバージョン4.3.48)。


0
date -d "yesterday" '+%Y-%m-%d'

これを後で使用するには:

date=$(date -d "yesterday" '+%Y-%m-%d')

2
このコードはOPの問題を解決する可能性がありますが、コードがOPの問題にどのように対処するかについての説明を含めることをお勧めします。このようにして、将来の訪問者はあなたの投稿から学び、それを自分のコードに適用することができます。SOはコーディングサービスではなく、知識のリソースです。高品質で完全な回答はこの考えを補強し、賛成される可能性が高くなります。これらの機能に加えて、すべての投稿が自己完結型であるという要件は、フォーラムから私たちを区別するプラットフォームとしてのSOのいくつかの長所です。編集して追加情報を追加したり、ソースドキュメントで説明を補足したりできます。
SherylHohman

0

以下を使用できます。

date -d "yesterday 13:55" '+%Y-%m-%d'

または、取得したい時間がbashによって取得されます。

月間:

date -d "30 days ago" '+%Y-%m-%d'

0

この質問にはタグが付けられています 「DSTセーフ」

そして、フォークを使用してdate暗黙の遅延を命令する場合、純粋なbashビルトインを使用するシンプルでより効率的な方法があります。

printf -v tznow '%(%z %s)T' -1
TZ=${tznow% *} printf -v yesterday '%(%Y-%m-%d)T' $(( ${tznow#* } - 86400 ))
echo $yesterday

これは、forkする必要があるよりも、システムフレンドリーではるかに高速dateです。

から V> = 5.0、新しい変数があります$EPOCHSECONDS

printf -v tz '%(%z)T' -1
TZ=$tz printf -v yesterday '%(%Y-%m-%d)T' $(( EPOCHSECONDS - 86400 ))
echo $yesterday
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.