Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Is there any way I can get the current 15 minute interval using the date command or similar ?

e.g. something like date %Y.%m.%d %H:%M will give me 2011.02.22 10:19 , I need something that yields 2011.02.22 10:15 in the time span from 10:15 to 10:29.

share|improve this question
add comment

6 Answers

up vote 9 down vote accepted

You can get the current unix timestamp with date "+%s", find the current quarter-hour with some simple math (my example is in bash) and print it back with a better format with date :

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

The @ syntax to set the current date and time from a timestamp is a GNU extention to date, if it don't works on your OS, you can do the same like this :

date -d"1970-01-01 $curquarter seconds"
share|improve this answer
add comment

The following methods make it unnecessary to call date twice.
A system call's overhead can make a "simple" command 100 times slower than bash doing the same thing in its own local environment.

UPDATE Just a quick mention about my above comment: "100 times slower". It can now read "500 times slower"... I recently fell (no, walked blindly) into this very issue. here is the link: Fast way to build a test file

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  

or

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

Both versions will return only

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

Here is the first one with a TEST loop for all 60 values {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 
share|improve this answer
    
Just for clarification — by "system call", you mean "fork/exec/wait, like the system() call", not system call in general. (I mention this because making system calls also has an overhead within a program, because of the user/kernel switch. That's not the particular issue here.) –  mattdm Mar 6 '11 at 6:03
    
mattdm... Thanks.. I'm working from only 6 months Linux experience, so I've quite likely used the wrong phrase, but I keep reading about the overheads incurred by unnecessary calls, and in my own experience of testing my own scripts, I've seen many examples where calling printf or sed and also that "unnecessary" cat vs <file does make a dramatic actual run-time difference. when looping, as in my "500 times slower" example.. So it seems that using the shell wherever possible, and allowing a program such as date to batch process is what I mean.. eg. Gilles' Left-Pad-0 example, vs printf –  Peter.O Mar 6 '11 at 11:09
add comment

Here's a way to work on dates in the shell. First call date to get the components, and fill the positional parameters ($1, $2, etc) with the components (note that this is one of these rare cases where you do want to use $(…) outside of double quotes, to break the string into words). Then perform arithmetics, tests, or whatever you need to do on the components. Finally assemble the components.

The arithmetic part can be a little tricky because shells treat 0 as an octal prefix; for example here $(($5/15)) would fail at 8 or 9 minutes past the hour. Since there's at most one leading 0, ${5#0} is safe for arithmetic. Adding 100 and subsequently stripping the 1 is a way to get a fixed number of digits in the output.

set $(date "+%Y %m %d %H %M")
m=$((100+15*(${5#0}/15)))
last_quarter_hour="$1.$2.$3 $4:${m#1}"
share|improve this answer
    
"The tricks of the trade" ...a good one. :) –  Peter.O Mar 6 '11 at 6:05
add comment

If you can live with calling date two times, this one works in bash on Solaris:

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

Edited on behalf of the comment to:

date +"%Y.%m.%d %H:$(( $(date +'%M') / 15 * 15 ))" | sed 's/:0$/:00/'
share|improve this answer
1  
In the first qurarter of the hour, this will produce a minutes output with only a single 0 instead of 00 –  Peter.O Feb 22 '11 at 14:40
    
Corrected, it is a simple sed after the original command. –  ddeimeke Feb 23 '11 at 15:53
    
One more bug: it doesn't work between H:08 and H:10. See my answer for why and a fix. –  Gilles Feb 23 '11 at 21:33
add comment

Maybe it doesn't matter anymore but you could try my very own dateutils. Rounding (down) to minutes is done with dround and a negative argument:

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

Or to adhere to your format:

dround now -15m -f '%Y.%m.%d %H:%M'
=>
  2012.07.11 13:00
share|improve this answer
add comment

Am not sure about your exact requirement. However, if you want to generate the time after 15 min, then you can use something like date -d '+15 min'. Output is shown below:

$ date; date  -d '+15 min'
Tue Feb 22 18:12:39 IST 2011
Tue Feb 22 18:27:39 IST 2011
share|improve this answer
    
You misunderstood the question. The point is to round the date (down) to a multiple of 15 minutes. –  Gilles Feb 22 '11 at 19:45
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.