Home arrow Blog arrow Round a DateTimePicker to 15 minute increments
Monday, 25 September 2017
Main Menu
Home
Blog
News
Software
Forums
Music
Email
Web Links
Blog Links
Musical Links
Nerdery Links
Other Neato Links
Syndicate
 
Round a DateTimePicker to 15 minute increments
User Rating: / 1
PoorBest 
.NET Programming
Written by WATYF on Friday, 23 January 2009 (13934 hits)
Category: .NET Programming

This should be a quick one. Here's the problem... I've got a DateTimePicker (actually, a very large amount of them) on a form, and I want to modify those DateTimePickers so that when a user highlights the "minute" portion and clicks up or down on the spinner, the minutes go up or down in 15 minute increments (instead of one minute increments). Now, the biggest challenge to this is that the separate controls of the DateTimePicker (up, down buttons, formatted textbox, etc) are not exposed in any way (thanks Microsoft!), so I have no way of figuring out if the user clicked up, or down, or entered the minute manually. Because of this, I can't (at least, I personally haven't figured out how to) create a "perfect" solution to this problem. So I settled for the next best thing... a solution that accounts for 90% of the time and that my users will be happy with...


First off, I'd like to point out that my solution involves simply using the ValueChanged event of the DateTimePicker. One could, of course, go all out and make their own custom DateTimePicker class and override the ValueChanged event and then create an "Increment" Property for the control, so that you could easily set an increment for the DateTimePicker, but my situation doesn't call for all that, and it would require more calculations (for variable increments other than 15), and since I'm in a hurry (and suck at math) I decided to go the "quick and dirty" route.

The main part is contained in the ValueChanged event, and then there's a helper Function (for rounding up). The RoundUp function is most likely not the most efficient way to do this (since, again, I suck at math), but I couldn't find a "Round in such and such an increment" anywhere online, so I had to make do. Anyway... the basic premise of the solution is that if the minute value is a 1, 16, 31, or 46, then they clicked "up", so we increment up to the next 15 minute increment. If the minute value is a 14, 29, 44,or 59, then they clicked "down", so we round down. If it's any other number, then it's something they manually entered, so we simply round the number up to the next 15 minute increment. I'm sure you can see the "flaw" in this imperfect solution. If they manually enter a 1, or 16, or 29 (or whatever), then it will think they clicked up/down, and might not round properly. For example, if it's 5:15, and they click down, then it will round it DOWN to 5:00. But if it's 5:15 and the manually enter 5:14, then you'd think it should round UP, but instead, it will "think" they clicked "down" and therefore round the minute down to 5:00. Anyway... it's not a huge flaw, and 99% of the users will never even notice, so it's perfectly fine for me.

So here's the code:

Private Sub dtpMyTime_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles dtpMyTime.ValueChanged

            'If it's already an increment of 15, exit sub

            If (sender.Value.Minute = 0) Or (sender.Value.Minute = 15) Or (sender.Value.Minute = 30) Or (sender.Value.Minute = 45) Then Exit Sub

            'If it's a 1, 16, 31, or 46 (i.e. they clicked "up")...

            If sender.Value.Minute = 1 Or sender.Value.Minute = 16 Or sender.Value.Minute = 31 Or sender.Value.Minute = 46 Then

                  'Add 14 minutes to the value

                  sender.Value = DateAdd(DateInterval.Minute, 14, sender.Value)

            ElseIf sender.Value.Minute = 14 Or sender.Value.Minute = 29 Or sender.Value.Minute = 44 Or sender.Value.Minute = 59 Then

                  'Otheriwse, if it's a 14, 29, 44, or 59 (i.e. they clicked "down"), subtract 14 minutes from the value

                  '   You have to subtract 74 (instead of 14) if it's 59, to take it down one hour

                  If sender.Value.Minute = 59 Then sender.Value = DateAdd(DateInterval.Minute, -74, sender.Value) Else

            sender.Value = DateAdd(DateInterval.Minute, -14, sender.Value)

            Else 'Otherwise, if it's not one digit away from a 15 minute interval (i.e. they manually entered a number)

                  'Round the number up to the next 15 minute increment

                  sender.Value = New DateTime(sender.Value.Year, sender.Value.Month, sender.Value.Day, sender.Value.Hour, RoundUp(sender.Value.Minute), 0)

            End If

      End Sub

      Private Function RoundUp(ByVal iMin) As Integer

            Dim x As Integer

            For i As Integer = 1 To 15

                  x = iMin + i

                  If x = 15 Or x = 30 Or x = 45 Or x = 0 Then Return x

            Next

      End Function

 

WATYF

 

 
< Prev   Next >

Comments

You must javascript enabled to use this form

Cheers for the code mate.
I am a developer at microsoft and actually just came accross this issue for the first time yesterday.
Your code is perfect thanks alot

Fathi Alsharif
Microsoft SQL Server Development Team

Posted by Fathi Alsharif, on 09/25/2010 at 06:30

Great Man!
It works using UpDown buttons and the keyboard.
Thanks a lot!

Posted by Jortx, on 12/22/2010 at 15:14

Nice. TY!
Modified. Don't need function call.
Only need global variable intTimeClockRounding to indicate the value you want to round to.


'If it's already an increment of intTimeClockRounding, exit sub
If (sender.Value.Minute Mod intTimeClockRounding = 0) Then
Exit Sub
End If
If (sender.Value.Minute Mod intTimeClockRounding (60 - intTimeClockRounding) Then
sender.Value = DateAdd(DateInterval.Minute, -(60 + intTimeClockRounding - 1), sender.Value)
Else
sender.Value = DateAdd(DateInterval.Minute, -(intTimeClockRounding - 1), sender.Value)
End If
End If

Posted by LWT, on 03/20/2011 at 14:29

Great!
I should replace the roundup by
Math.Round(sender.Value.Minute / 15) * 15

I also changed the first 'if' check to
If (sender.Value.Minute Mod 15) = 0 Then Return

Thanks!

Posted by Marc, on 09/29/2011 at 22:47

 1 
Page 1 of 1 ( 4 Comments )
©2007 MosCom

TaskRunner Spam-a-lot

It's cool. It's nifty. It does stuff. It's...

  TaskRunner 3.3!!

Click here to get the brand spanking new version of TaskRunner... 3.3!!
Who's Online
 

Google
Recent Posts
Most Popular
 
© 2017 Musical Nerdery
Joomla! is Free Software released under the GNU/GPL License.