Reputation: 20073
I'm trying to round a Date to the nearest 3, 6, 12, or 24 hours intervals (starting at midnight). Given the following inputs, I'm looking for the related output..
for 24 hours
2013-09-11 00:00:00 -> 2013-09-11 00:00:00 (no change needed)
2013-09-11 01:30:25 -> 2013-09-11 00:00:00 (rounded down)
2013-09-11 12:01:01 -> 2013-09-12 00:00:00 (rounded up)
for 12 hours
2013-09-11 00:00:00 -> 2013-09-11 00:00:00 (no change needed)
2013-09-11 12:00:00 -> 2013-09-11 12:00:00 (no change needed)
2013-09-11 11:50:57 -> 2013-09-11 12:00:00 (rounded up)
2013-09-11 12:01:00 -> 2013-09-11 12:00:00 (rounded down)
2013-09-11 22:15:48 -> 2013-09-12 00:00:00 (rounded up)
for 6 hours
2013-09-11 05:50:57 -> 2013-09-11 06:00:00 (rounded up)
2013-09-11 08:50:57 -> 2013-09-11 06:00:00 (rounded down)
2013-09-11 10:50:57 -> 2013-09-11 12:00:00 (rounded up)
for 3 hours
2013-09-11 01:50:57 -> 2013-09-11 00:00:00 (rounded down)
2013-09-11 02:50:57 -> 2013-09-11 03:00:00 (rounded up)
2013-09-11 09:40:57 -> 2013-09-11 09:00:00 (rounded down)
etc...
I keep finding all of these interesting solutions for rounding to the nearest minute, but I can't seem to fit them to my own needs. I thought I had something going using reference #2 below, but it fails miserably (http://jsfiddle.net/LUwk8/2/). Any ideas?
References:
Upvotes: 2
Views: 3353
Reputation: 225125
Get the fractional hours using [get|set][Hours|Minutes|Seconds|Milliseconds]()
, and round that to the interval:
function roundTo(num, interval) {
return Math.round(num / interval) * interval;
}
function roundHours(date, interval) {
var newDate = new Date(date);
var h = newDate.getHours() + newDate.getMinutes() / 60 + newDate.getSeconds() / 3600 + newDate.getMilliseconds() / 3600000;
newDate.setMinutes(0);
newDate.setSeconds(0);
newDate.setMilliseconds(0);
newDate.setHours(roundTo(h, interval));
return newDate;
}
Upvotes: 3
Reputation: 147483
Here's an alternative that uses the time value. Since it's UTC, it's adjusted for the offset to make UTC like local, rounded, then the offset added back on to get a local time.
// d is a date object
function roundTo3Hrs(d) {
// Three hours in milliseconds
var g = 3 * 60 * 60 * 1000;
// Get local offset
var o = d.getTimezoneOffset() * -6e4;
// Round to nearest 3 hrs
var x = Math.round((+d + o)/g);
// Return a new date object
return new Date(x * g - o);
}
// Some (minimal) tests
var now = new Date();
now.setHours(13,29,59,999);
alert(roundTo3Hrs(now)); // 12:00
now.setHours(13,30,0,0);
alert(roundTo3Hrs(now)); // 15:00
This appeals to me as it seem efficient and could be adapted for any range to round to (1 hour, 3 hour,6 hour, etc.).
Upvotes: 1
Reputation: 104820
You can use the mod of the time divided by the precision,
if you want to make 1am round down to midnight,
rather than up to 3, 6 or noon.
function roundHours(precision, d){
precision= precision || 1;
d= d? new Date(d):new Date();
if(d.getSeconds()>30) d.setMinutes(d.getMinutes()+1);
if(d.getMinutes>30) hours+= 1;
var hours= d.getHours(), diff= hours%precision;
if(diff>precision/2) hours+= (precision-diff);
else hours-= diff;
d.setHours(hours, 0, 0, 0);
return d.toLocaleString();
}
//testing precision:
var A= [], range=[3,6,12,24], d1= new Date();
for(var x= 0; x<4; x++){
A.push('\n'+range[x]+ ' hour precision:');
for(var i= 0; i<24; i++){
d1.setHours(i);
A.push(i+': '+roundHours(range[x], d1));
}
}
A.join('\n');
//returned value: (String)
3 hour precision:
00: Wednesday, September 11, 2013 12:00:00 AM
01: Wednesday, September 11, 2013 12:00:00 AM
02: Wednesday, September 11, 2013 3:00:00 AM
03: Wednesday, September 11, 2013 3:00:00 AM
04: Wednesday, September 11, 2013 3:00:00 AM
05: Wednesday, September 11, 2013 6:00:00 AM
06: Wednesday, September 11, 2013 6:00:00 AM
07: Wednesday, September 11, 2013 6:00:00 AM
08: Wednesday, September 11, 2013 9:00:00 AM
09: Wednesday, September 11, 2013 9:00:00 AM
10: Wednesday, September 11, 2013 9:00:00 AM
11: Wednesday, September 11, 2013 12:00:00 PM
12: Wednesday, September 11, 2013 12:00:00 PM
13: Wednesday, September 11, 2013 12:00:00 PM
14: Wednesday, September 11, 2013 3:00:00 PM
15: Wednesday, September 11, 2013 3:00:00 PM
16: Wednesday, September 11, 2013 3:00:00 PM
17: Wednesday, September 11, 2013 6:00:00 PM
18: Wednesday, September 11, 2013 6:00:00 PM
19: Wednesday, September 11, 2013 6:00:00 PM
20: Wednesday, September 11, 2013 9:00:00 PM
21: Wednesday, September 11, 2013 9:00:00 PM
22: Wednesday, September 11, 2013 9:00:00 PM
23: Thursday, September 12, 2013 12:00:00 AM
6 hour precision:
00: Wednesday, September 11, 2013 12:00:00 AM
01: Wednesday, September 11, 2013 12:00:00 AM
02: Wednesday, September 11, 2013 12:00:00 AM
03: Wednesday, September 11, 2013 12:00:00 AM
04: Wednesday, September 11, 2013 6:00:00 AM
05: Wednesday, September 11, 2013 6:00:00 AM
06: Wednesday, September 11, 2013 6:00:00 AM
07: Wednesday, September 11, 2013 6:00:00 AM
08: Wednesday, September 11, 2013 6:00:00 AM
09: Wednesday, September 11, 2013 6:00:00 AM
10: Wednesday, September 11, 2013 12:00:00 PM
11: Wednesday, September 11, 2013 12:00:00 PM
12: Wednesday, September 11, 2013 12:00:00 PM
13: Wednesday, September 11, 2013 12:00:00 PM
14: Wednesday, September 11, 2013 12:00:00 PM
15: Wednesday, September 11, 2013 12:00:00 PM
16: Wednesday, September 11, 2013 6:00:00 PM
17: Wednesday, September 11, 2013 6:00:00 PM
18: Wednesday, September 11, 2013 6:00:00 PM
19: Wednesday, September 11, 2013 6:00:00 PM
20: Wednesday, September 11, 2013 6:00:00 PM
21: Wednesday, September 11, 2013 6:00:00 PM
22: Thursday, September 12, 2013 12:00:00 AM
23: Thursday, September 12, 2013 12:00:00 AM
12 hour precision:
00: Wednesday, September 11, 2013 12:00:00 AM
01: Wednesday, September 11, 2013 12:00:00 AM
02: Wednesday, September 11, 2013 12:00:00 AM
03: Wednesday, September 11, 2013 12:00:00 AM
04: Wednesday, September 11, 2013 12:00:00 AM
05: Wednesday, September 11, 2013 12:00:00 AM
06: Wednesday, September 11, 2013 12:00:00 AM
07: Wednesday, September 11, 2013 12:00:00 PM
08: Wednesday, September 11, 2013 12:00:00 PM
09: Wednesday, September 11, 2013 12:00:00 PM
10: Wednesday, September 11, 2013 12:00:00 PM
11: Wednesday, September 11, 2013 12:00:00 PM
12: Wednesday, September 11, 2013 12:00:00 PM
13: Wednesday, September 11, 2013 12:00:00 PM
14: Wednesday, September 11, 2013 12:00:00 PM
15: Wednesday, September 11, 2013 12:00:00 PM
16: Wednesday, September 11, 2013 12:00:00 PM
17: Wednesday, September 11, 2013 12:00:00 PM
18: Wednesday, September 11, 2013 12:00:00 PM
19: Thursday, September 12, 2013 12:00:00 AM
20: Thursday, September 12, 2013 12:00:00 AM
21: Thursday, September 12, 2013 12:00:00 AM
22: Thursday, September 12, 2013 12:00:00 AM
23: Thursday, September 12, 2013 12:00:00 AM
24 hour precision:
00: Wednesday, September 11, 2013 12:00:00 AM
01: Wednesday, September 11, 2013 12:00:00 AM
02: Wednesday, September 11, 2013 12:00:00 AM
03: Wednesday, September 11, 2013 12:00:00 AM
04: Wednesday, September 11, 2013 12:00:00 AM
05: Wednesday, September 11, 2013 12:00:00 AM
06: Wednesday, September 11, 2013 12:00:00 AM
07: Wednesday, September 11, 2013 12:00:00 AM
08: Wednesday, September 11, 2013 12:00:00 AM
09: Wednesday, September 11, 2013 12:00:00 AM
10: Wednesday, September 11, 2013 12:00:00 AM
11: Wednesday, September 11, 2013 12:00:00 AM
12: Wednesday, September 11, 2013 12:00:00 AM
13: Thursday, September 12, 2013 12:00:00 AM
14: Thursday, September 12, 2013 12:00:00 AM
15: Thursday, September 12, 2013 12:00:00 AM
16: Thursday, September 12, 2013 12:00:00 AM
17: Thursday, September 12, 2013 12:00:00 AM
18: Thursday, September 12, 2013 12:00:00 AM
19: Thursday, September 12, 2013 12:00:00 AM
20: Thursday, September 12, 2013 12:00:00 AM
21: Thursday, September 12, 2013 12:00:00 AM
22: Thursday, September 12, 2013 12:00:00 AM
23: Thursday, September 12, 2013 12:00:00 AM
Upvotes: 2