c#


Rounding DateTime objects


I want to round dates/times to the nearest interval for a charting application. I'd like an extension method signature like follows so that the rounding can be acheived for any level of accuracy:
static DateTime Round(this DateTime date, TimeSpan span);
The idea is that if I pass in a timespan of ten minutes, it will round to the nearest ten minute interval. I can't get my head around the implementation and am hoping one of you will have written or used something similar before.
I think either a floor, ceiling or nearest implementation is fine.
Any ideas?
Edit: Thanks to #tvanfosson & #ShuggyCoUk, the implementation looks like this:
public static class DateExtensions {
public static DateTime Round(this DateTime date, TimeSpan span) {
long ticks = (date.Ticks + (span.Ticks / 2) + 1)/ span.Ticks;
return new DateTime(ticks * span.Ticks);
}
public static DateTime Floor(this DateTime date, TimeSpan span) {
long ticks = (date.Ticks / span.Ticks);
return new DateTime(ticks * span.Ticks);
}
public static DateTime Ceil(this DateTime date, TimeSpan span) {
long ticks = (date.Ticks + span.Ticks - 1) / span.Ticks;
return new DateTime(ticks * span.Ticks);
}
}
And is called like so:
DateTime nearestHour = DateTime.Now.Round(new TimeSpan(1,0,0));
DateTime minuteCeiling = DateTime.Now.Ceil(new TimeSpan(0,1,0));
DateTime weekFloor = DateTime.Now.Floor(new TimeSpan(7,0,0,0));
...
Cheers!
Floor
long ticks = date.Ticks / span.Ticks;
return new DateTime( ticks * span.Ticks );
Round (up on midpoint)
long ticks = (date.Ticks + (span.Ticks / 2) + 1)/ span.Ticks;
return new DateTime( ticks * span.Ticks );
Ceiling
long ticks = (date.Ticks + span.Ticks - 1)/ span.Ticks;
return new DateTime( ticks * span.Ticks );
This will let you round to any interval given, is slightly faster than dividing and then multiplying the ticks, and most importantly it's readable.
private static DateTime Floor(DateTime dateTime, TimeSpan interval)
{
return dateTime.AddTicks(-(dateTime.Ticks % interval.Ticks));
}
private static DateTime Ceiling(DateTime dateTime, TimeSpan interval)
{
var overflow = dateTime.Ticks % interval.Ticks;
return overflow == 0 ? dateTime : dateTime.AddTicks(interval.Ticks - overflow);
}
private static DateTime Round(DateTime dateTime, TimeSpan interval)
{
var halfIntervelTicks = (interval.Ticks + 1) >> 1;
return dateTime.AddTicks(halfIntervelTicks - ((dateTime.Ticks + halfIntervelTicks) % interval.Ticks));
}
You should also be clear if you want your rounding to:
be to the start, end or middle of the interval
start is the easiest and often the expected but you should be clear in your initial spec.
How you want boundary cases to round.
normally only an issue if you are rounding to the middle rather than the end.
Since rounding to the middle is an attempt at a bias free answer you need to use something like Bankers Rounding technically round half even to be truly free from bias.
It is quite likely that you really only care about the first point but in these 'simple' questions the resulting behaviour can have far reaching consequences as you use it in the real world (often at the intervals adjacent to zero)
tvanfosson's solution's cover all the cases listed in 1.
The midpoint example is biased upwards. It is doubtful that this would be a problem in time related rounding.
Just use the Ticks, using that to divide, floor/ceil/round the value, and multiply it back.

Related Links

Convert label text to decimal
Function reading line from stream is blocking
When escaping characters in a string, is it faster to test for the need to do so first?
Having trouble displaying a button once when is clicked
Date range overlap issue in LINQ
ASP.net MaskEditExtender stops working when parent div is display:none
pass C# arraylist to Javascript
Regular expression usage
Using LINQ to return List from 2 lists [duplicate]
Session is Closed! NHibernate shouldn't be trying to grab data
Run same exe twice
Is there a language that allows both static and dynamic typing? [closed]
HttpWebRequest times out on the second call to the Web Server
Trying to use Kinect for Windows with C#, but I get System.BadImageFormatException
type inference var
ASP.NET, MVC 3, C# website, pre-load linked pages

Categories

HOME
latex
livecharts
xss
sequence
spring-data-solr
gcloud
vichuploaderbundle
osclass
jsfiddle
game-engine
owncloud
smooth-scrolling
geography
draw2d
udeploy
serenity-js
rndis
policy
struts
aspxgridview
scrapy-spider
android-cursorloader
paper-trail-gem
lines
contextmenustrip
availability
flickr
restler
machine-code
javax
wit-ai
certbot
intersection
ponylang
lex
instances
head
niagara-ax
spring-ide
activeandroid
sharpdevelop
seyren
liferay-ide
opticalflow
apache-commons-cli
lattice
qudpsocket
visual-web-developer
instaparse
git-cherry-pick
php-java-bridge
mrunit
3d-rendering
nd4j
clique
stdlist
video-embedding
jquery-draggable
yfiles
gulp-cdnizer
personality-insights
musicbrainz
first-order-logic
pushwoosh
firewire
euro
gcc-warning
copy-on-write
gmaps4jsf
maven-archetype
nfa
applinks
fxmlloader
register-allocation
formbuilder
tigase
selenium-grid2
mvcgrid
smartxls
satisfiability
farpoint-spread
pidgin
mixradio
vbaccelerator
infomaker
nokogiri
mandelbrot
pyxplot
symbian3
outlook-object-model
mmo
volatility
sup
jqueryi-ui-buttonset
nsundomanager
execjs
qvariant
text-manipulation
jquery-attributes
dongle
versions
code-golf
large-data-volumes
mysql-pconnect
helios
file-storage

Resources

Mobile Apps Dev
Database Users
javascript
java
csharp
php
android
MS Developer
developer works
python
ios
c
html
jquery
RDBMS discuss
Cloud Virtualization
Database Dev&Adm
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App