none
Establecer Limites de horas en Datetimepicker RRS feed

  • Pregunta

  • Buenas!

    Tengo un datetimepicker y encontré la propiedad

    mindate (fecha y hora minima) y maxdate (fecha y hora máxima)

    lo he puesto para que se vea como "showupdown"

    es decir puede cambiar horas y minutos.

    Lo que deseo es establecer limites de horas

    por decir

    mínimo sea 14/07/2015 06:00 y el máximo 14/07/2015 20:00

    (en este caso no tengo problemas)

    pero cuando establezco que el valor mínimo sea 14/07/2015 20:00  y el mayor 15/07/2015 06:00

    las horas que me da a elegir son entre 20 y 23 nada mas,

    sin tomar en cuenta que el valor mayor es las 6am del dia siguiente (tendria que salir 1,2,3,4,5,6)

    espero haberme expresado bien 

    y que puedan ayudarme

    desde ya muchas gracias

    Julia 

    jueves, 16 de julio de 2015 21:22

Respuestas

  • Hola Julia,

    al final me he picado un poco con tu problema y he preparado un control para editar horas que permite establecer una hora mínima y máxima.

    Lo he hecho a la carrera y casi no lo he probado pero tiene buena pinta. A ver si te sirve:

    Public Class TimePicker
        Inherits UpDownBase
    
        Private _actual As TimeSpan = New TimeSpan(0, 0, 0)
        Private _textBox As TextBox = MyBase.Controls(1)
        Private _minValue As TimeSpan = New TimeSpan(0, 0, 0)
        Private _maxValue As TimeSpan = New TimeSpan(23, 59, 59)
        Private _partialText As String = String.Empty
        Private _minTime As TimeSpan = _minValue
        Private _maxTime As TimeSpan = _maxValue
    
        Public Sub New()
    
        End Sub
    
        Public Property Value() As TimeSpan
            Get
                Return _actual
            End Get
            Set(ByVal value As TimeSpan)
                If Not IsValueInRange(value) Then
                    Throw New Exception("Valor no válido")
                End If
                _actual = value
                UpdateEditText()
            End Set
        End Property
    
        Public Overrides Property Text As String
            Get
                Return MyBase.Text
            End Get
            Set(value As String)
                If Not IsValidText(value) Then
                    Throw New Exception("Valor no válido")
                End If
                UpdateText(value)
            End Set
        End Property
    
        Public Property MinTime As TimeSpan
            Get
                Return _minTime
            End Get
            Set(value As TimeSpan)
                If value < _minValue OrElse value > _maxValue Then
                    Throw New Exception("Valor no válido")
                End If
                _minTime = value
                If Not IsValueInRange() Then
                    _actual = _minTime
                    UpdateEditText()
                End If
            End Set
        End Property
    
        Public Property MaxTime() As TimeSpan
            Get
                Return _maxTime
            End Get
            Set(ByVal value As TimeSpan)
                If value < _minValue OrElse value > _maxValue Then
                    Throw New Exception("Valor no válido")
                End If
                _maxTime = value
                If Not IsValueInRange() Then
                    _actual = _maxTime
                    UpdateEditText()
                End If
            End Set
        End Property
    
    
        Public Overrides Sub DownButton()
            Dim diff As TimeSpan = IIf(_textBox.SelectionStart < 3, New TimeSpan(1, 0, 0), New TimeSpan(0, 1, 0))
            Dim value As TimeSpan = _actual.Subtract(diff)
            If value < _minValue Then
                value.Add(New TimeSpan(24, 0, 0))
            End If
            While Not IsValueInRange(value)
                value = value.Subtract(diff)
                If value < _minValue Then
                    value.Add(New TimeSpan(24, 0, 0))
                End If
            End While
            _actual = value
            UpdateEditText()
            If _textBox.SelectionStart < 3 Then
                _textBox.SelectionStart = 0
                _textBox.SelectionLength = 2
            Else
                _textBox.SelectionStart = 3
                _textBox.SelectionLength = 2
            End If
        End Sub
    
        Public Overrides Sub UpButton()
            Dim diff As TimeSpan = IIf(_textBox.SelectionStart < 3, New TimeSpan(1, 0, 0), New TimeSpan(0, 1, 0))
            Dim value As TimeSpan = _actual.Add(diff)
            If value > _maxValue Then
                value.Subtract(New TimeSpan(24, 0, 0))
            End If
            While Not IsValueInRange(value)
                value = value.Add(diff)
                If value > _maxValue Then
                    value.Subtract(New TimeSpan(24, 0, 0))
                End If
            End While
            _actual = value
            UpdateEditText()
            If _textBox.SelectionStart < 3 Then
                _textBox.SelectionStart = 0
                _textBox.SelectionLength = 2
            Else
                _textBox.SelectionStart = 3
                _textBox.SelectionLength = 2
            End If
        End Sub
    
        Protected Overrides Sub UpdateEditText()
            While _actual < _minValue
                _actual = _actual.Add(New TimeSpan(24, 0, 0))
            End While
            While _actual > _maxValue
                _actual = _actual.Subtract(New TimeSpan(24, 0, 0))
            End While
            Dim selInit As Integer = _textBox.SelectionStart
            MyBase.Text = String.Format("{0}:{1}", _actual.Hours.ToString("00"), _actual.Minutes.ToString("00"))
            _textBox.SelectionStart = selInit
        End Sub
    
        Protected Overrides Sub OnTextChanged(e As EventArgs)
            UpdateText(MyBase.Text)
            MyBase.OnTextChanged(e)
        End Sub
    
        Protected Overrides Sub OnKeyUp(e As KeyEventArgs)
            MyBase.OnKeyUp(e)
            UpdateSelectionText()
        End Sub
    
        Protected Overrides Sub OnMouseUp(mevent As MouseEventArgs)
            MyBase.OnMouseUp(mevent)
            UpdateSelectionText()
        End Sub
    
        Protected Overrides Sub OnKeyDown(e As KeyEventArgs)
            Select Case e.KeyCode
                Case Keys.Delete
                    _textBox.SelectedText = "0"
                    UpdateEditText()
                    e.Handled = True
                Case Keys.Left
                    _textBox.SelectionStart = 0
                    UpdateSelectionText()
                    e.Handled = True
                Case Keys.Right
                    _textBox.SelectionStart = 3
                    UpdateSelectionText()
                    e.Handled = True
            End Select
            MyBase.OnKeyDown(e)
        End Sub
    
        Protected Overrides Sub OnKeyPress(e As KeyPressEventArgs)
            If (Char.IsNumber(e.KeyChar)) Then
                If String.IsNullOrEmpty(_partialText) Then
                    _partialText = e.KeyChar.ToString()
                Else
                    Dim text As String = IIf(_textBox.SelectionStart > 0, _textBox.Text.Substring(0, _textBox.SelectionStart), String.Empty)
                    text = text & _partialText & e.KeyChar.ToString()
                    If (_textBox.SelectionStart + _textBox.SelectionLength < _textBox.Text.Length) Then
                        text = text & _textBox.Text.Substring(_textBox.SelectionStart + _textBox.SelectionLength)
                    End If
                    If IsValidText(text) Then
                        _partialText = _partialText & e.KeyChar.ToString()
                    Else
                        _partialText = e.KeyChar.ToString()
                    End If
                End If
                _textBox.SelectedText = _partialText
            End If
            e.Handled = True
            MyBase.OnKeyPress(e)
        End Sub
    
        Private Sub UpdateText(text As String)
            Dim parts As String() = text.Split(":")
            If parts.Count <> 2 OrElse Not IsNumeric(parts(0)) OrElse Not IsNumeric(parts(1)) Then
                UpdateEditText()
                Return
            End If
            _actual = New TimeSpan(Integer.Parse(parts(0)), Integer.Parse(parts(1)), 0)
            UpdateEditText()
        End Sub
    
        Private Sub UpdateSelectionText()
            If _textBox.SelectionStart < 3 Then
                _textBox.SelectionStart = 0
                _textBox.SelectionLength = 2
            Else
                _textBox.SelectionStart = 3
                _textBox.SelectionLength = 2
            End If
        End Sub
    
        Private Function IsValidText(text As String) As Boolean
            Dim parts As String() = text.Split(":")
            If parts.Count <> 2 OrElse Not IsNumeric(parts(0)) OrElse Not IsNumeric(parts(1)) Then
                Return False
            End If
            Dim value As TimeSpan = New TimeSpan(Integer.Parse(parts(0)), Integer.Parse(parts(1)), 0)
            Return IsValueInRange(value)
        End Function
    
        Private Function IsValueInRange() As Boolean
            Return IsValueInRange(_actual)
        End Function
    
        Private Function IsValueInRange(value As TimeSpan) As Boolean
            Return (_minTime <= _maxTime AndAlso _minTime <= value AndAlso _maxTime >= value) _
                OrElse (_minTime > _maxTime AndAlso (_minTime <= value OrElse _maxTime >= value))
        End Function
    
    End Class
    


    Píldoras .NET
    Artículos, tutoriales y ejemplos de código .NET

    Píldoras JS
    Artículos, tutoriales y ejemplos de código JavaScript, HTML5, CSS3, ...

    lunes, 20 de julio de 2015 22:44

Todas las respuestas

  • Hola:
    Prueba con esto

    Public Class Form1

        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
            Me.DateTimePicker1.Format = DateTimePickerFormat.Custom
            Me.DateTimePicker1.CustomFormat = "dd/MM/yyyy HH:mm"
            Me.DateTimePicker1.MinDate = CDate("17/05/2015 17:00")
            Me.DateTimePicker1.MaxDate = CDate("18/05/2015 06:00")
        End Sub
    End Class

    Un saludo desde Bilbo
    Carlos

    viernes, 17 de julio de 2015 8:49
  • Antes que nada, 

    gracias por tu tiempo Carlos

    pero la verdad no me ha funcionado :(

    de igual manera muchas gracias por tu colaboración 

    Julia

    domingo, 19 de julio de 2015 23:25
  • Hola Julia Lan,

    La manera como te han indicado es correcta, es más, como lo has venido haciendo también es correcto. Creo suponer que lo que estas esperando es que luego de las 11 pm cambie automáticamente a las 12 y que el día se convierta en 15. Eso no es posible, por lo menos no es parte de la funcionalidad del control aunque podrías codificar algún algoritmo adicional para que ello suceda. Lo que intento mencionarte es que si quieres navegar entre las 12 horas y las 6 am del día 15, deberás moverte del día 14 al 15. Te dejo otra propuesta, pero considera lo dicho anteriormente.

    dtpFechaInicio.Format = DateTimePickerFormat.Custom
            dtpFechaInicio.CustomFormat = "dd/MM/yyyy hh:mm tt"
            dtpFechaInicio.ShowUpDown = True
            dtpFechaInicio.Value = "14/07/2015 08:00 p.m."
            dtpFechaInicio.MinDate = "14/07/2015 08:00 p.m."
            dtpFechaInicio.MaxDate = "15/07/2015 06:00 a.m."

    Si la solución propuesta atendió su consulta no olvide marcarla como respuesta.

    Willams Morales
    Arequipa - PERÚ

    lunes, 20 de julio de 2015 1:09
  • Hola:
    ¿ Puedes explicar que es lo que no te funciona ?

    Un saludo desde Bilbo
    Carlos

    lunes, 20 de julio de 2015 11:29
  • Buen día Carlos y Williams

    El código que me pasaste

            Me.DateTimePicker1.Format = DateTimePickerFormat.Custom
            Me.DateTimePicker1.CustomFormat = "dd/MM/yyyy HH:mm"
            Me.DateTimePicker1.MinDate = CDate("17/05/2015 17:00")
            Me.DateTimePicker1.MaxDate = CDate("18/05/2015 06:00")

    muestra el día y yo solo necesito las horas por lo que en mi caso usé

            Me.DateTimePicker1.Format = DateTimePickerFormat.Custom
            Me.DateTimePicker1.CustomFormat = "HH:mm"
            Me.DateTimePicker1.MinDate = CDate("17/05/2015 17:00")
            Me.DateTimePicker1.MaxDate = CDate("18/05/2015 06:00")

    tendria que mostrarme las horas (17,18,19,20,21,22,23,00,01,02,03,04,05,06) cierto?

    pero sin embargo solo muestra (0,1,2,3,4,5,6) y regresa a 6

    Saludos desde Paraguay

    Julia


    • Editado Julia Lan lunes, 20 de julio de 2015 16:24
    lunes, 20 de julio de 2015 16:12
  • Creo que no os estáis entendiendo bien.

    Lo que trata de hacer Julia es mostrar un control únicamente con la hora y que ésta pueda ser cualquier hora válida entre las 17:00 y las 06:00.

    Me temo que con el datetimepicker no vas a poder hacerlo, tendrías que utilizar un control de terceros o implementar tú misma la funcionalidad o utilizar dos NumericUpDown


    Píldoras .NET
    Artículos, tutoriales y ejemplos de código .NET

    Píldoras JS
    Artículos, tutoriales y ejemplos de código JavaScript, HTML5, CSS3, ...

    lunes, 20 de julio de 2015 17:36
  • Buen día Williams:

    Acabo de entender lo que mencionas, 

    pero como he comentado lo que necesito son las horas y minutos nada mas

    por lo que mi formato es 

    dtpFechaInicio.CustomFormat ="HH:mm"


    se me ocurrió que podría ser agregando en el formato el día de la semana para que "cambie" de fecha como en esta imagen

    pero agregando en el formato 

    dtpFechaInicio.CustomFormat = "ddd HH:mm "

    tampoco me permite cambiar de día

    Gracias por la colaboración

    Saludos desde Paraguay



    • Editado Julia Lan lunes, 20 de julio de 2015 17:48
    lunes, 20 de julio de 2015 17:46
  • Buenas tardes Asier

    Como lo has dicho, es ese mi objetivo.

    En cuanto a usar dos NumericUpDown, lo he pensado.

    Será trabajoso ya que uso 4 DateTimePicker por cada uno de los días de la semana.

    Lo que pasaría a 8 NumericUpDown por cada día de la semana.

    Otra opción que me pareció aceptable es usar el MasketBox,

    pero en este caso no sé si se pueden establecer límites o rangos

    Desde ya muchas gracias

    Saludos desde Paraguay


    lunes, 20 de julio de 2015 19:15
  • No, en el caso del MaskedTextBox tendrías que controlar por código que los valores introducidos sean válidos. Puede ser la mejor opción si no te importa renunciar a los botones UpDown.

    Píldoras .NET
    Artículos, tutoriales y ejemplos de código .NET

    Píldoras JS
    Artículos, tutoriales y ejemplos de código JavaScript, HTML5, CSS3, ...

    lunes, 20 de julio de 2015 19:17
  • Gracias por la sugerencia Asier! 

    Espero encontrarle la vuelta 

    Saludos

    lunes, 20 de julio de 2015 19:24
  • Hola Julia,

    al final me he picado un poco con tu problema y he preparado un control para editar horas que permite establecer una hora mínima y máxima.

    Lo he hecho a la carrera y casi no lo he probado pero tiene buena pinta. A ver si te sirve:

    Public Class TimePicker
        Inherits UpDownBase
    
        Private _actual As TimeSpan = New TimeSpan(0, 0, 0)
        Private _textBox As TextBox = MyBase.Controls(1)
        Private _minValue As TimeSpan = New TimeSpan(0, 0, 0)
        Private _maxValue As TimeSpan = New TimeSpan(23, 59, 59)
        Private _partialText As String = String.Empty
        Private _minTime As TimeSpan = _minValue
        Private _maxTime As TimeSpan = _maxValue
    
        Public Sub New()
    
        End Sub
    
        Public Property Value() As TimeSpan
            Get
                Return _actual
            End Get
            Set(ByVal value As TimeSpan)
                If Not IsValueInRange(value) Then
                    Throw New Exception("Valor no válido")
                End If
                _actual = value
                UpdateEditText()
            End Set
        End Property
    
        Public Overrides Property Text As String
            Get
                Return MyBase.Text
            End Get
            Set(value As String)
                If Not IsValidText(value) Then
                    Throw New Exception("Valor no válido")
                End If
                UpdateText(value)
            End Set
        End Property
    
        Public Property MinTime As TimeSpan
            Get
                Return _minTime
            End Get
            Set(value As TimeSpan)
                If value < _minValue OrElse value > _maxValue Then
                    Throw New Exception("Valor no válido")
                End If
                _minTime = value
                If Not IsValueInRange() Then
                    _actual = _minTime
                    UpdateEditText()
                End If
            End Set
        End Property
    
        Public Property MaxTime() As TimeSpan
            Get
                Return _maxTime
            End Get
            Set(ByVal value As TimeSpan)
                If value < _minValue OrElse value > _maxValue Then
                    Throw New Exception("Valor no válido")
                End If
                _maxTime = value
                If Not IsValueInRange() Then
                    _actual = _maxTime
                    UpdateEditText()
                End If
            End Set
        End Property
    
    
        Public Overrides Sub DownButton()
            Dim diff As TimeSpan = IIf(_textBox.SelectionStart < 3, New TimeSpan(1, 0, 0), New TimeSpan(0, 1, 0))
            Dim value As TimeSpan = _actual.Subtract(diff)
            If value < _minValue Then
                value.Add(New TimeSpan(24, 0, 0))
            End If
            While Not IsValueInRange(value)
                value = value.Subtract(diff)
                If value < _minValue Then
                    value.Add(New TimeSpan(24, 0, 0))
                End If
            End While
            _actual = value
            UpdateEditText()
            If _textBox.SelectionStart < 3 Then
                _textBox.SelectionStart = 0
                _textBox.SelectionLength = 2
            Else
                _textBox.SelectionStart = 3
                _textBox.SelectionLength = 2
            End If
        End Sub
    
        Public Overrides Sub UpButton()
            Dim diff As TimeSpan = IIf(_textBox.SelectionStart < 3, New TimeSpan(1, 0, 0), New TimeSpan(0, 1, 0))
            Dim value As TimeSpan = _actual.Add(diff)
            If value > _maxValue Then
                value.Subtract(New TimeSpan(24, 0, 0))
            End If
            While Not IsValueInRange(value)
                value = value.Add(diff)
                If value > _maxValue Then
                    value.Subtract(New TimeSpan(24, 0, 0))
                End If
            End While
            _actual = value
            UpdateEditText()
            If _textBox.SelectionStart < 3 Then
                _textBox.SelectionStart = 0
                _textBox.SelectionLength = 2
            Else
                _textBox.SelectionStart = 3
                _textBox.SelectionLength = 2
            End If
        End Sub
    
        Protected Overrides Sub UpdateEditText()
            While _actual < _minValue
                _actual = _actual.Add(New TimeSpan(24, 0, 0))
            End While
            While _actual > _maxValue
                _actual = _actual.Subtract(New TimeSpan(24, 0, 0))
            End While
            Dim selInit As Integer = _textBox.SelectionStart
            MyBase.Text = String.Format("{0}:{1}", _actual.Hours.ToString("00"), _actual.Minutes.ToString("00"))
            _textBox.SelectionStart = selInit
        End Sub
    
        Protected Overrides Sub OnTextChanged(e As EventArgs)
            UpdateText(MyBase.Text)
            MyBase.OnTextChanged(e)
        End Sub
    
        Protected Overrides Sub OnKeyUp(e As KeyEventArgs)
            MyBase.OnKeyUp(e)
            UpdateSelectionText()
        End Sub
    
        Protected Overrides Sub OnMouseUp(mevent As MouseEventArgs)
            MyBase.OnMouseUp(mevent)
            UpdateSelectionText()
        End Sub
    
        Protected Overrides Sub OnKeyDown(e As KeyEventArgs)
            Select Case e.KeyCode
                Case Keys.Delete
                    _textBox.SelectedText = "0"
                    UpdateEditText()
                    e.Handled = True
                Case Keys.Left
                    _textBox.SelectionStart = 0
                    UpdateSelectionText()
                    e.Handled = True
                Case Keys.Right
                    _textBox.SelectionStart = 3
                    UpdateSelectionText()
                    e.Handled = True
            End Select
            MyBase.OnKeyDown(e)
        End Sub
    
        Protected Overrides Sub OnKeyPress(e As KeyPressEventArgs)
            If (Char.IsNumber(e.KeyChar)) Then
                If String.IsNullOrEmpty(_partialText) Then
                    _partialText = e.KeyChar.ToString()
                Else
                    Dim text As String = IIf(_textBox.SelectionStart > 0, _textBox.Text.Substring(0, _textBox.SelectionStart), String.Empty)
                    text = text & _partialText & e.KeyChar.ToString()
                    If (_textBox.SelectionStart + _textBox.SelectionLength < _textBox.Text.Length) Then
                        text = text & _textBox.Text.Substring(_textBox.SelectionStart + _textBox.SelectionLength)
                    End If
                    If IsValidText(text) Then
                        _partialText = _partialText & e.KeyChar.ToString()
                    Else
                        _partialText = e.KeyChar.ToString()
                    End If
                End If
                _textBox.SelectedText = _partialText
            End If
            e.Handled = True
            MyBase.OnKeyPress(e)
        End Sub
    
        Private Sub UpdateText(text As String)
            Dim parts As String() = text.Split(":")
            If parts.Count <> 2 OrElse Not IsNumeric(parts(0)) OrElse Not IsNumeric(parts(1)) Then
                UpdateEditText()
                Return
            End If
            _actual = New TimeSpan(Integer.Parse(parts(0)), Integer.Parse(parts(1)), 0)
            UpdateEditText()
        End Sub
    
        Private Sub UpdateSelectionText()
            If _textBox.SelectionStart < 3 Then
                _textBox.SelectionStart = 0
                _textBox.SelectionLength = 2
            Else
                _textBox.SelectionStart = 3
                _textBox.SelectionLength = 2
            End If
        End Sub
    
        Private Function IsValidText(text As String) As Boolean
            Dim parts As String() = text.Split(":")
            If parts.Count <> 2 OrElse Not IsNumeric(parts(0)) OrElse Not IsNumeric(parts(1)) Then
                Return False
            End If
            Dim value As TimeSpan = New TimeSpan(Integer.Parse(parts(0)), Integer.Parse(parts(1)), 0)
            Return IsValueInRange(value)
        End Function
    
        Private Function IsValueInRange() As Boolean
            Return IsValueInRange(_actual)
        End Function
    
        Private Function IsValueInRange(value As TimeSpan) As Boolean
            Return (_minTime <= _maxTime AndAlso _minTime <= value AndAlso _maxTime >= value) _
                OrElse (_minTime > _maxTime AndAlso (_minTime <= value OrElse _maxTime >= value))
        End Function
    
    End Class
    


    Píldoras .NET
    Artículos, tutoriales y ejemplos de código .NET

    Píldoras JS
    Artículos, tutoriales y ejemplos de código JavaScript, HTML5, CSS3, ...

    lunes, 20 de julio de 2015 22:44
  • Buenas Asier!

    Agradezco tu interés en resolver mis dudas, pero la verdad he terminado creando una función que toma el rango de valores posibles y los compara con la hora ingresada,de igual manera tu código nos ayudará a varios por aquí.

    Saludos desde Paraguay



    jueves, 23 de julio de 2015 22:29