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

'System.Reflection.TargetInvocationException' occurred in EntityFramework.SqlServer.dll
DataGridView1.CurrentCell and BeginEdit doesn't work if I move with Tab
How to give access to selective class methods in inheritance?
Querying derived type values using MongoDB C# driver
Arranging xml file as per xsd structure
Compare two variables every tick
Using C# & LINQ how can I find duplicate file names?
Join 3 One to Many Tables in Entity Framework
GhostScript unrecoverable error: undefined file name
How can I convert an XML fragment to a Dictionary in C#?
Detect and open all installed softwares [duplicate]
Issues creating Xamarin IOS bindings library
Convert Bot framework attachment to SMTP attachment
C# Entity Framework ObjectContext instance has been disposed
Update an item in the list not working
How to create dbf file with dBase IV structure via Microsoft.Jet.OLEDB.4.0?

Categories

HOME
classification
msbuild
swift3
primefaces
network-programming
wifi
dronekit
liquibase
hiveql
datetimepicker
ebay
angularjs-directive
richtextbox
qt4
sahi
normals
openbsd
websharper
jetbrains
dev-c++
jira-zephyr
oracle10g
android-6.0-marshmallow
uibarbuttonitem
custom-fields
javapns
spring-data-gemfire
opencsv
blockly
n1ql
kofax
area
fisheye
redbean
qt-quick
superclass
amazon-fire-tv
ack
synchronized
togglebutton
anonymous-function
serverless-architecture
riemann
fluent-nhibernate-mapping
photoshop-script
node-java
was
turbolinks
mongodb-3.3
geokit
airwatch
queuing
nsoperationqueue
audiorecord
chomsky-normal-form
music-player
containstable
askbot
android-contentresolver
gulp-cdnizer
taverna
lytro
traminer
jsoncpp
transparentproxy
tidesdk
teamstudio-unplugged
iphone-6
mind-manager
diffmerge
xts
switchpreference
angular-file-upload
cs193p
django-tests
opencobol
mongoid4
autofilter
php-amqplib
google-voice
caroufredsel
maven-webstart-plugin
windows-scheduler
cloudmade
junit-rule
mail-gem
motordriver
github-archive
pdf-reader
optimistic-concurrency
virtual-printer
zipstream
arraycollection
google-local-search
webdb
web-search
authkit
zend-acl
weak-typing

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