回答:
現在の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"
次のメソッドにより、date
2回呼び出す必要がなくなります。
システムコールのオーバーヘッドにより、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
printf
やsed
、「不要」cat
と<fileが実際の実行時間に劇的な違いをもたらす多くの例を見てきました。私の「500倍遅い」例のようにループするとき..可能な限りシェルを使用し、date
バッチ処理などのプログラムを許可することは、私が意味することのようです。GillesのLeft-Pad-0の例、vs printf
シェルで日付を操作する方法を次に示します。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}"
多分それはもう問題ではないかもしれませんが、あなたは私自身のdateutilsを試すことができます 分数への丸め(切り捨て)はdround
、負の引数を使用して行われます。
dround now /-15m
=>
2012-07-11T13:00:00
または、フォーマットに準拠するには:
dround now /-15m -f '%Y.%m.%d %H:%M'
=>
2012.07.11 13:00
dateutils.dround '2018-11-12 13:55' -15m
生成しません。2018-11-12T13:15:00
2018-11-12T13:45:00
/-15m
。つまり、1時間の15分の次の倍数に切り捨てます。この機能は、それがより少ない値を受け入れるため、より面倒な構文を得た13は60(時間内分)の約数ではないので、/ -13mは、たとえばことはできません
一部のシェルは、外部date
コマンドを呼び出さずに作業を実行できます。
ksh
a=$(printf '%(%s)T\n'); printf '%(%Y.%m.%d %H:%M)T\n' "#$((a-a%(15*60)))"
bash a=$(printf '%(%s)T\n'); printf '%(%Y.%m.%d %H:%M)T\n' "$((a-a%(15*60)))"
zsh 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モジュールの読み込みは、日付自体の呼び出しと同じくらい遅い場合があります。
gnu-date a=$(date +%s); date -ud "@$((a-a%(15*60)))" +'%Y.%m.%d %H:%M'
のような小さな実行可能ファイルでもbusybox
同様の結果が得られます。
busybox-date a=$(busybox date +%s);busybox date -ud "@$((a-a%(15*60)))" +'%Y.%m.%d %H:%M'
busyboxがPATHのディレクトリ内のこれらの名前にリンクされている場合、先頭のbusyboxワードは省略されることに注意してください。
どちらdate
とbusybox 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'
呼び出し日付を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/'
正確な要件についてはわかりません。ただし、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