日付:現在の15分間隔を取得します


15

dateコマンドなどを使用して現在の15分間隔を取得する方法はありますか?

日付のような例えば、何かが%Y.%m.%d %H:%M 私を与えるだろう2011.02.22 10:19、私は何かを必要とする利回り2011.02.22 10:15からの時間スパンで10:1510:29

回答:


17

現在のUNIXタイムスタンプを取得するにはdate "+%s"、を使用して、簡単な計算(現在の例はbash)で現在の15分を見つけ、より良い形式で印刷しますdate

curdate=`date "+%s"`
curquarter=$(($curdate - ($curdate % (15 * 60))))
date -d"@$curquarter"

@それはあなたのOS上で動作していない場合は、タイムスタンプから現在の日付と時刻を設定するための構文は、現在までのGNUの拡張子である、あなたがそうでなければ、このように同じで(UTCを指定することを忘れないでください行うことができます、それは勝ちました仕事):

date -d"1970-01-01 $curquarter seconds UTC"

5

次のメソッドにより、date2回呼び出す必要がなくなります。
システムコールのオーバーヘッドにより、bashが独自のローカル環境で同じことを行うよりも「単純な」コマンドが100倍遅くなる可能性があります。

更新上記のコメントについて簡単に言及します:「100倍遅い」。今では「500倍遅い」と読むことができます...私は最近、まさにこの問題に陥りました(いいえ、盲目的に歩きました)。ここにリンクがあります:テストファイルを構築するための高速な方法

eval $(date +Y=%Y\;m=%m\;d=%d\;H=%H\;M=%M)
[[ "$M" < "15" ]] && M=00 # cater for octal clash
M=$(((M/15)*15))
((M==0)) && M=00 # the math returns 0, so make it 00  
echo $Y.$m.$d $H:$M  

または

eval $(date +Y=%Y\;m=%m\;d=%d\;H=%H\;M=%M)
if   [[ "$M" < "15" ]] ; then M=00
elif [[ "$M" < "30" ]] ; then M=15
elif [[ "$M" < "45" ]] ; then M=30
else M=45
fi
echo $Y.$m.$d $H:$M

両方のバージョンが返されるのみ

2011.02.23 01:00
2011.02.23 01:15
2011.02.23 01:30
2011.02.23 01:45   

これは、60個すべての値に対するテストループを備えた最初のものです{00..59}

for X in {00..59} ;                         ###### TEST
do                                          ###### TEST 
  eval $(date +Y=%Y\;m=%m\;d=%d\;H=%H\;M=%M)
  M=$X                                      ###### TEST 
  [[ "$M" < "15" ]] && M=00 # cater for octal clash
  M=$(((M/15)*15))
  ((M==0)) && M=00 # the math returns 0, so make it 00  
  echo $Y.$m.$d $H:$M 
done                                        ###### TEST 

1
わかりやすくするために、「システムコール」は、一般的なシステムコールではなく、「system()コールのようなfork / exec / wait」を意味します。(ユーザー/カーネルの切り替えのために、システムコールを行うとプログラム内でオーバーヘッドが発生するため、これについて言及します。これはここでは特に問題ではありません。)
mattdm

mattdm ...ありがとう。私はたった6か月のLinuxの経験から仕事をしているので、間違ったフレーズを使用した可能性が高いです。スクリプトでは、呼び出しprintfsed、「不要」catと<fileが実際の実行時間に劇的な違いをもたらす多くの例を見てきました。私の「500倍遅い」例のようにループするとき..可能な限りシェルを使用し、dateバッチ処理などのプログラムを許可することは、私が意味することのようです。GillesのLeft-Pad-0の例、vs printf
Peter.O

3

シェルで日付を操作する方法を次に示します。dateコンポーネントを取得する最初の呼び出し、および位置パラメーター($1$2など)をコンポーネントで埋めます(これは$(…)、二重引用符の外側で使用して文字列を単語に分割するまれなケースの1つです)。次に、コンポーネントに対して算術演算、テスト、または必要なことを実行します。最後にコンポーネントを組み立てます。

シェル0は8進数の接頭辞として扱うため、算術部分は少し注意が必要です。たとえば、ここで$(($5/15))は1時間の8分または9分で失敗します。先頭0に1つしか存在し${5#0}ないため、算術的に安全です。100を追加してからストリッピングする1と、出力で固定桁数を取得できます。

set $(date "+%Y %m %d %H %M")
m=$((100+15*(${5#0}/15)))
last_quarter_hour="$1.$2.$3 $4:${m#1}"

「取引の秘 "」...良いもの。:)
Peter.O

2

多分それはもう問題ではないかもしれませんが、あなたは私自身のdateutilsを試すことができます 分数への丸め(切り捨て)はdround、負の引数を使用して行われます。

dround now /-15m
=>
  2012-07-11T13:00:00

または、フォーマットに準拠するには:

dround now /-15m -f '%Y.%m.%d %H:%M'
=>
  2012.07.11 13:00

それは実際にあなたのユーティリティがもうどのように機能するのですか?-15m使用して私は毎時最寄りの15分に入力巻き戻しを取得:dateutils.dround '2018-11-12 13:55' -15m生成しません。2018-11-12T13:15:002018-11-12T13:45:00

1
@JackDouglasツールは進化しました。あなたが望むのは、今です/-15m。つまり、1時間の15分の次の倍数に切り捨てます。この機能は、それがより少ない値を受け入れるため、より面倒な構文を得た13は60(時間内分)の約数ではないので、/ -13mは、たとえばことはできません
hroptatyr

いいですね、今必要なものが手に入りますdateutils.dround '2018-11-12 12:52:31' /450s /-15m、ありがとう!

2

一部のシェルは、外部dateコマンドを呼び出さずに作業を実行できます。

a=$(printf '%(%s)T\n'); printf '%(%Y.%m.%d %H:%M)T\n' "#$((a-a%(15*60)))"
a=$(printf '%(%s)T\n'); printf '%(%Y.%m.%d %H:%M)T\n' "$((a-a%(15*60)))"
zmodload zsh/datetime; a=$EPOCHSECONDS; strftime '%Y-%m-%d %H:%M' $((a-a%(15*60)))

上記の3つはローカル(UTCではない)時間を提供します。必要に応じて、先頭にTZ = UTC0を使用します。

kshとbashの構文はほぼ同じです(#kshで必要なものを除く)。zshは、モジュールをロードする必要があります(zshディストリビューションに含まれています)。

(GNU)awkを使用して行うこともできます。

awk 'BEGIN{t=systime();print strftime("%Y.%m.%d %H:%M",t-t%(15*60),1)}'

ローカルが必要な場合、UTCの結果が提供されます(最後1をに変更0)。ただし、外部awkまたは外部zshモジュールの読み込みは、日付自体の呼び出しと同じくらい遅い場合があります。

a=$(date +%s); date -ud "@$((a-a%(15*60)))" +'%Y.%m.%d %H:%M'

のような小さな実行可能ファイルでもbusybox同様の結果が得られます。

a=$(busybox date +%s);busybox date -ud "@$((a-a%(15*60)))" +'%Y.%m.%d %H:%M'

busyboxがPATHのディレクトリ内のこれらの名前にリンクされている場合、先頭のbusyboxワードは省略されることに注意してください。

どちらdatebusybox date上記は、UTC時間を表示します。-u現地時間のオプションを削除します。


OSの日付のバージョンがより制限されている場合(そしてそれがあなたが使用しなければならないものです)、試してください:

a=$(date +%s); a=$(( a-a%(15*60) ))
date -d"1970-01-01 $a seconds UTC" +'%Y.%m.%d %H:%M'

または、FreeBSDの場合は、次を試してください。

a=$(date +%s); a=$(( a-a%(15*60) ))
date -r "$a" +'%Y.%m.%d %H:%M'

1

呼び出し日付を2回使用できる場合、これはSolarisのbashで機能します。

date +"%Y.%m.%d %H:$(( $(date +'%M') / 15 * 15 ))"

コメントに代わって編集:

date +"%Y.%m.%d %H:$(( $(date +'%M') / 15 * 15 ))" | sed 's/:0$/:00/'

1
1時間の最初のクォーラムで、これは00ではなく1つの0のみで分出力を生成します
Peter.O

修正されたのは、元のコマンドの後の単純なsedです。
ddeimeke

もう1つのバグ:H:08とH:10の間では機能しません。理由と修正方法については、私の回答をご覧ください。
ジル 'SO-悪である停止

-1

正確な要件についてはわかりません。ただし、15分後に時間を生成する場合は、などを使用できますdate -d '+15 min'。出力は次のとおりです。

$ date; date  -d '+15 min'
Tue Feb 22 18:12:39 IST 2011
Tue Feb 22 18:27:39 IST 2011

1
あなたは質問を誤解しました。ポイントは、日付を15分の倍数に切り捨てることです。
ジル 'SO-悪であるのをやめる'
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.