Foro de elhacker.net

Programación => .NET (C#, VB.NET, ASP) => Mensaje iniciado por: #Aitor en 23 Septiembre 2015, 16:26 pm



Título: Cuenta regresiva a partir de una fecha (VB.Net)
Publicado por: #Aitor en 23 Septiembre 2015, 16:26 pm
Código
  1.    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
  2.        '  Dim Año As Integer = Microsoft.VisualBasic.DateAndTime.Year(Now) '2015
  3.  
  4.        Dim Mes As Integer = Microsoft.VisualBasic.DateAndTime.Month(Now) ' Mes 9
  5.        Dim Dia As Integer = Microsoft.VisualBasic.DateAndTime.Day(Now)
  6.        Dim Hora As Integer = Microsoft.VisualBasic.DateAndTime.Hour(Now)
  7.        Dim Minuto As Integer = Microsoft.VisualBasic.DateAndTime.Minute(Now)
  8.        Dim Segundo As Integer = Microsoft.VisualBasic.DateAndTime.Second(Now)
  9.  
  10.  
  11.        Dim MesAni As Integer = 10
  12.        Dim DiaAni As Integer = 5
  13.        Dim HoraAni As Integer = 23
  14.        Dim MinutoAni As Integer = 59
  15.        Dim SegundoAni As Integer = 59
  16.  
  17.        Dim Mesrestante As Integer = MesAni - Mes
  18.        Dim Diarestante As Integer = DiaAni - Dia
  19.        Dim Horarestante As Integer = HoraAni - Hora
  20.        Dim Minutorestante As Integer = MinutoAni - Minuto
  21.        Dim Segundorestante As Integer = SegundoAni - Segundo
  22.  
  23.        Label1.Text = "Dias: " & Diarestante & " Horas: " & Horarestante & " Minutos " & Minutorestante & " Segundos: " & Segundorestante
  24.        Label1.Show()
  25.  
  26.    End Sub


La idea es hacer una cuenta regresiva que este en una continua actualización, a partir de una fecha clave, y la fecha base del ordenador.

El problema aquí está en que el mes no es el mismo, y por lo tanto la variable Diarestante da un valor negativo. ¿Cómo solucionar eso? O en su defecto alguna forma mejor de hacerlo.

La idea principal es que no se muestre lo que contiene el programa hasta ese día, supongo que para saber si se ha pasado el día basta con comprobar que el díaActual sea mayor que el diaAni.


Edito:

Para arreglarlo de una forma cutre:

Código
  1.        Dim Mes As Integer = Microsoft.VisualBasic.DateAndTime.Month(Now) ' Mes 9
  2.        Dim Dia As Integer = Microsoft.VisualBasic.DateAndTime.Day(Now)
  3.        Dim Hora As Integer = Microsoft.VisualBasic.DateAndTime.Hour(Now)
  4.        Dim Minuto As Integer = Microsoft.VisualBasic.DateAndTime.Minute(Now)
  5.        Dim Segundo As Integer = Microsoft.VisualBasic.DateAndTime.Second(Now)
  6.  
  7.  
  8.        Dim MesAni As Integer = 10
  9.        Dim DiaAni As Integer = 278
  10.        Dim HoraAni As Integer = 23
  11.        Dim MinutoAni As Integer = 59
  12.        Dim SegundoAni As Integer = 59
  13.  
  14.        Select Case Dia
  15.            Case 23
  16.                Dia = 266
  17.            Case 24
  18.                Dia = 267
  19.            Case 25
  20.                Dia = 268
  21.            Case 26
  22.                Dia = 269
  23.            Case 27
  24.                Dia = 270
  25.            Case 28
  26.                Dia = 271
  27.            Case 29
  28.                Dia = 272
  29.            Case 30
  30.                Dia = 273
  31.            Case 1
  32.                Dia = 274
  33.            Case 2
  34.                Dia = 275
  35.            Case 3
  36.                Dia = 276
  37.            Case 4
  38.                Dia = 277
  39.            Case 5
  40.                Dia = 278
  41.        End Select
  42.  
  43.        Dim Mesrestante As Integer = MesAni - Mes
  44.        Dim Diarestante As Integer = DiaAni - Dia
  45.        Dim Horarestante As Integer = HoraAni - Hora
  46.        Dim Minutorestante As Integer = MinutoAni - Minuto
  47.        Dim Segundorestante As Integer = SegundoAni - Segundo
  48.  
  49.  
  50.        Label1.Text = "Dias: " & Diarestante & " Horas: " & Horarestante & " Minutos " & Minutorestante & " Segundos: " & Segundorestante
  51.        Label1.Show()

De esta forma con los casos me aseguro de que tengan el dia correspondiente a su dia en base a los 365 dias posibles...

Pero claro, esto solo sirve como un apaño para solucionar mi problema suponiendo que la cuenta regresiva es de máximo 1 mes. Sigo sin saber como solucionar el problema en sí.


Título: Re: Cuenta regresiva a partir de una fecha (VB.Net)
Publicado por: Eleкtro en 23 Septiembre 2015, 18:15 pm
¿Cómo solucionar eso? O en su defecto alguna forma mejor de hacerlo.

Estás siguiendo el camino equivocado.

Usa un TimeSpan.



Tenia un viejo código que desarrollé el año pasado para medir el tiempo de forma amistosa, para usar un cronómetro o un temporizador/cuenta atrás de forma sencilla. He refactorizado un poco el código (por eso he tardado en responderte).

Para tus necesidades, podrías utilizarlo de la siguiente manera:
Código
  1. Public NotInheritable Class Form1 : Inherits Form
  2.  
  3.    ''' <summary>
  4.    ''' The <see cref="TimeMeasurer"/> instance that measure time intervals.
  5.    ''' </summary>
  6.    Private WithEvents countDown As New TimeMeasurer With {.UpdateInterval = 100}
  7.  
  8.    Private Shadows Sub Load() Handles MyBase.Load
  9.  
  10.        ' Medir el lapso de 1 mes desde la fecha y hora actual.
  11.        Me.countDown.Start(DateTime.Now, DateTime.Now.AddMonths(1))
  12.  
  13.    End Sub
  14.  
  15.    ''' <summary>
  16.    ''' Handles the TimeUpdated event of the countdown instance.
  17.    ''' </summary>
  18.    ''' <param name="sender">The source of the event.</param>
  19.    ''' <param name="e">The <see cref="TimeMeasurer.TimeUpdatedEventArgs"/> instance containing the event data.</param>
  20.    Private Sub Countdown_TimeUpdated(ByVal sender As Object, ByVal e As TimeMeasurer.TimeUpdatedEventArgs) _
  21.    Handles countDown.TimeUpdated
  22.  
  23.        Me.lblCountDown.Text = String.Format("Days:{0:00} Hours:{1:00} Minutes:{2:00} Seconds:{3:00}",
  24.                                            e.Remaining.Days, e.Remaining.Hours, e.Remaining.Minutes, e.Remaining.Seconds)
  25.  
  26.    End Sub
  27.  
  28. End Class


El código fuente (version actualizada y mejor refactorizada):
Código
  1. ' ***********************************************************************
  2. ' Author           : Elektro
  3. ' Last Modified On : 26-September-2015
  4. ' ***********************************************************************
  5. ' <copyright file="TimeMeasurer.vb" company="Elektro Studios">
  6. '     Copyright (c) Elektro Studios. All rights reserved.
  7. ' </copyright>
  8. ' ***********************************************************************
  9.  
  10. #Region " Usage Examples "
  11.  
  12. #End Region
  13.  
  14. #Region " Option Statements "
  15.  
  16. Option Strict On
  17. Option Explicit On
  18. Option Infer Off
  19.  
  20. #End Region
  21.  
  22. #Region " Imports "
  23.  
  24. Imports System
  25. Imports System.Diagnostics
  26. Imports System.Linq
  27. Imports System.Windows.Forms
  28.  
  29. #End Region
  30.  
  31. ''' ----------------------------------------------------------------------------------------------------
  32. ''' <summary>
  33. ''' Measures the elapsed and/or remaining time of a time interval.
  34. ''' The time measurer can be used as a chronometer or a countdown.
  35. ''' </summary>
  36. ''' ----------------------------------------------------------------------------------------------------
  37. Public NotInheritable Class TimeMeasurer : Implements IDisposable
  38.  
  39. #Region " Objects "
  40.  
  41.    ''' ----------------------------------------------------------------------------------------------------
  42.    ''' <summary>
  43.    ''' An <see cref="Stopwatch"/> instance to retrieve the elapsed time. (chronometer)
  44.    ''' </summary>
  45.    ''' ----------------------------------------------------------------------------------------------------
  46.    Private timeElapsed As Stopwatch
  47.  
  48.    ''' ----------------------------------------------------------------------------------------------------
  49.    ''' <summary>
  50.    ''' A <see cref="TimeSpan"/> instance to retrieve the remaining time. (countdown)
  51.    ''' </summary>
  52.    ''' ----------------------------------------------------------------------------------------------------
  53.    Private timeRemaining As TimeSpan
  54.  
  55.    ''' ----------------------------------------------------------------------------------------------------
  56.    ''' <summary>
  57.    ''' A <see cref="Timer"/> instance that updates the elapsed and remaining time, and also raise <see cref="TimeMeasurer"/> events.
  58.    ''' </summary>
  59.    ''' ----------------------------------------------------------------------------------------------------
  60.    Private WithEvents measureTimer As Timer
  61.  
  62.    ''' ----------------------------------------------------------------------------------------------------
  63.    ''' <summary>
  64.    ''' Flag that indicates wheter this <see cref="TimeMeasurer"/> instance has finished to measure time interval.
  65.    ''' </summary>
  66.    ''' ----------------------------------------------------------------------------------------------------
  67.    Private isFinished As Boolean
  68.  
  69. #End Region
  70.  
  71. #Region " Properties "
  72.  
  73.    ''' ----------------------------------------------------------------------------------------------------
  74.    ''' <summary>
  75.    ''' Gets the maximum time that the <see cref="TimeMeasurer"/> can measure, in milliseconds.
  76.    ''' </summary>
  77.    ''' ----------------------------------------------------------------------------------------------------
  78.    ''' <value>
  79.    ''' The maximum time that the <see cref="TimeMeasurer"/> can measure, in milliseconds.
  80.    ''' </value>
  81.    ''' ----------------------------------------------------------------------------------------------------
  82.    Public Shared ReadOnly Property MaxValue As Double
  83.        Get
  84.            Return (TimeSpan.MaxValue.TotalMilliseconds - 1001.0R)
  85.        End Get
  86.    End Property
  87.  
  88.    ''' ----------------------------------------------------------------------------------------------------
  89.    ''' <summary>
  90.    ''' Gets the current state of this <see cref="TimeMeasurer"/> instance.
  91.    ''' </summary>
  92.    ''' ----------------------------------------------------------------------------------------------------
  93.    ''' <value>
  94.    ''' The update interval.
  95.    ''' </value>
  96.    ''' ----------------------------------------------------------------------------------------------------
  97.    Public ReadOnly Property State As TimeMeasurerState
  98.        Get
  99.            If (Me.timeElapsed Is Nothing) OrElse (Me.isFinished) Then
  100.                Return TimeMeasurerState.Disabled
  101.  
  102.            ElseIf Not Me.timeElapsed.IsRunning Then
  103.                Return TimeMeasurerState.Paused
  104.  
  105.            Else
  106.                Return TimeMeasurerState.Enabled
  107.  
  108.            End If
  109.        End Get
  110.    End Property
  111.  
  112.    ''' ----------------------------------------------------------------------------------------------------
  113.    ''' <summary>
  114.    ''' Gets or sets the update interval.
  115.    ''' Maximum value is 1000 (1 second).
  116.    ''' </summary>
  117.    ''' ----------------------------------------------------------------------------------------------------
  118.    ''' <value>
  119.    ''' The update interval.
  120.    ''' </value>
  121.    ''' ----------------------------------------------------------------------------------------------------
  122.    ''' <exception cref="ArgumentException">
  123.    ''' A value smaller than 1000 is required.;value
  124.    ''' </exception>
  125.    Public Property UpdateInterval As Integer
  126.        Get
  127.            Return Me.updateIntervalB
  128.        End Get
  129.        <DebuggerHidden>
  130.        <DebuggerStepThrough>
  131.        Set(ByVal value As Integer)
  132.            If (value > 1000) Then
  133.                Throw New ArgumentException(message:="A value smaller than 1000 is required.", paramName:="value")
  134.            Else
  135.                Me.updateIntervalB = value
  136.                If (Me.measureTimer IsNot Nothing) Then
  137.                    Me.measureTimer.Interval = value
  138.                End If
  139.            End If
  140.        End Set
  141.    End Property
  142.    ''' <summary>
  143.    ''' The update interval.
  144.    ''' </summary>
  145.    Private updateIntervalB As Integer = 100I
  146.  
  147. #End Region
  148.  
  149. #Region " Enumerations "
  150.  
  151.    ''' ----------------------------------------------------------------------------------------------------
  152.    ''' <summary>
  153.    ''' Specifies the current state of a <see cref="TimeMeasurer"/> instance.
  154.    ''' </summary>
  155.    ''' ----------------------------------------------------------------------------------------------------
  156.    Public Enum TimeMeasurerState As Integer
  157.  
  158.        ''' <summary>
  159.        ''' The <see cref="TimeMeasurer"/> is running.
  160.        ''' </summary>
  161.        Enabled = &H0I
  162.  
  163.        ''' <summary>
  164.        ''' The <see cref="TimeMeasurer"/> is paused.
  165.        ''' </summary>
  166.        Paused = &H1I
  167.  
  168.        ''' <summary>
  169.        ''' The <see cref="TimeMeasurer"/> is fully stopped, it cannot be resumed.
  170.        ''' </summary>
  171.        Disabled = &H2I
  172.  
  173.    End Enum
  174.  
  175. #End Region
  176.  
  177. #Region " Events "
  178.  
  179.    ''' ----------------------------------------------------------------------------------------------------
  180.    ''' <summary>
  181.    ''' Occurs when the elapsed/remaining time updates.
  182.    ''' </summary>
  183.    ''' ----------------------------------------------------------------------------------------------------
  184.    Public Event TimeUpdated(ByVal sender As Object, ByVal e As TimeUpdatedEventArgs)
  185.  
  186. #Region " Time Updated EventArgs "
  187.  
  188.    ''' ----------------------------------------------------------------------------------------------------
  189.    ''' <summary>
  190.    ''' Defines the <see cref="TimeUpdated"/> event arguments.
  191.    ''' </summary>
  192.    ''' ----------------------------------------------------------------------------------------------------
  193.    Public NotInheritable Class TimeUpdatedEventArgs : Inherits EventArgs
  194.  
  195. #Region " Properties "
  196.  
  197.        ''' ----------------------------------------------------------------------------------------------------
  198.        ''' <summary>
  199.        ''' Gets the elapsed time.
  200.        ''' </summary>
  201.        ''' ----------------------------------------------------------------------------------------------------
  202.        ''' <value>
  203.        ''' The elapsed time.
  204.        ''' </value>
  205.        ''' ----------------------------------------------------------------------------------------------------
  206.        Public ReadOnly Property Elapsed As TimeSpan
  207.            Get
  208.                Return Me.elapsedB
  209.            End Get
  210.        End Property
  211.        ''' ----------------------------------------------------------------------------------------------------
  212.        ''' <summary>
  213.        ''' ( Baking Field )
  214.        ''' The elapsed time.
  215.        ''' </summary>
  216.        ''' ----------------------------------------------------------------------------------------------------
  217.        Private ReadOnly elapsedB As TimeSpan
  218.  
  219.        ''' ----------------------------------------------------------------------------------------------------
  220.        ''' <summary>
  221.        ''' Gets the remaining time.
  222.        ''' </summary>
  223.        ''' ----------------------------------------------------------------------------------------------------
  224.        ''' <value>
  225.        ''' The remaining time.
  226.        ''' </value>
  227.        ''' ----------------------------------------------------------------------------------------------------
  228.        Public ReadOnly Property Remaining As TimeSpan
  229.            Get
  230.                Return Me.remainingB
  231.            End Get
  232.        End Property
  233.        ''' ----------------------------------------------------------------------------------------------------
  234.        ''' <summary>
  235.        ''' ( Baking Field )
  236.        ''' The remaining time.
  237.        ''' </summary>
  238.        ''' ----------------------------------------------------------------------------------------------------
  239.        Private ReadOnly remainingB As TimeSpan
  240.  
  241.        ''' ----------------------------------------------------------------------------------------------------
  242.        ''' <summary>
  243.        ''' Gets the goal time.
  244.        ''' </summary>
  245.        ''' ----------------------------------------------------------------------------------------------------
  246.        ''' <value>
  247.        ''' The goal time.
  248.        ''' </value>
  249.        ''' ----------------------------------------------------------------------------------------------------
  250.        Public ReadOnly Property Goal As TimeSpan
  251.            Get
  252.                Return Me.goalB
  253.            End Get
  254.        End Property
  255.        ''' ----------------------------------------------------------------------------------------------------
  256.        ''' <summary>
  257.        ''' ( Baking Field )
  258.        ''' The goal time.
  259.        ''' </summary>
  260.        ''' ----------------------------------------------------------------------------------------------------
  261.        Private ReadOnly goalB As TimeSpan
  262.  
  263. #End Region
  264.  
  265. #Region " Constructors "
  266.  
  267.        ''' ----------------------------------------------------------------------------------------------------
  268.        ''' <summary>
  269.        ''' Prevents a default instance of the <see cref="TimeUpdatedEventArgs"/> class from being created.
  270.        ''' </summary>
  271.        ''' ----------------------------------------------------------------------------------------------------
  272.        Private Sub New()
  273.        End Sub
  274.  
  275.        ''' ----------------------------------------------------------------------------------------------------
  276.        ''' <summary>
  277.        ''' Initializes a new instance of the <see cref="TimeUpdatedEventArgs"/> class.
  278.        ''' </summary>
  279.        ''' ----------------------------------------------------------------------------------------------------
  280.        ''' <param name="elapsed">
  281.        ''' The elapsed time.
  282.        ''' </param>
  283.        '''
  284.        ''' <param name="remaining">
  285.        ''' The remaining time.
  286.        ''' </param>
  287.        '''
  288.        ''' <param name="goal">
  289.        ''' The goal time.
  290.        ''' </param>
  291.        ''' ----------------------------------------------------------------------------------------------------
  292.        Public Sub New(ByVal elapsed As TimeSpan,
  293.                       ByVal remaining As TimeSpan,
  294.                       ByVal goal As TimeSpan)
  295.  
  296.            Me.elapsedB = elapsed
  297.            Me.remainingB = remaining
  298.            Me.goalB = goal
  299.  
  300.        End Sub
  301.  
  302. #End Region
  303.  
  304.    End Class
  305.  
  306. #End Region
  307.  
  308. #End Region
  309.  
  310. #Region " Public Methods "
  311.  
  312.    ''' ----------------------------------------------------------------------------------------------------
  313.    ''' <summary>
  314.    ''' Starts the time interval measurement.
  315.    ''' </summary>
  316.    ''' ----------------------------------------------------------------------------------------------------
  317.    ''' <param name="milliseconds">
  318.    ''' The time interval to measure, in milliseconds.
  319.    ''' </param>
  320.    ''' ----------------------------------------------------------------------------------------------------
  321.    ''' <exception cref="ArgumentOutOfRangeException">
  322.    ''' milliseconds;A value smaller than <see cref="TimeMeasurer.MaxValue"/> is required.
  323.    ''' </exception>
  324.    '''
  325.    ''' <exception cref="ArgumentOutOfRangeException">
  326.    ''' milliseconds;A value greater than 0 is required.
  327.    ''' </exception>
  328.    ''' ----------------------------------------------------------------------------------------------------
  329.    <DebuggerHidden>
  330.    <DebuggerStepThrough>
  331.    Public Sub Start(ByVal milliseconds As Double)
  332.  
  333.        If (milliseconds > TimeMeasurer.MaxValue) Then
  334.            Throw New ArgumentOutOfRangeException(paramName:="milliseconds",
  335.                                                  message:=String.Format("A value smaller than {0} is required.", TimeMeasurer.MaxValue))
  336.  
  337.        ElseIf (milliseconds <= 0) Then
  338.            Throw New ArgumentOutOfRangeException(paramName:="milliseconds",
  339.                                                  message:="A value greater than 0 is required.")
  340.  
  341.        Else
  342.            Me.timeElapsed = New Stopwatch
  343.            Me.timeRemaining = TimeSpan.FromMilliseconds(milliseconds)
  344.            Me.measureTimer = New Timer With
  345.               {
  346.                 .Tag = milliseconds,
  347.                 .Interval = Me.updateIntervalB,
  348.                 .Enabled = True
  349.               }
  350.  
  351.            Me.isFinished = False
  352.            Me.timeElapsed.Start()
  353.            Me.measureTimer.Start()
  354.  
  355.        End If
  356.  
  357.    End Sub
  358.  
  359.    ''' ----------------------------------------------------------------------------------------------------
  360.    ''' <summary>
  361.    ''' Starts a time interval measurement given a difference between two dates.
  362.    ''' </summary>
  363.    ''' ----------------------------------------------------------------------------------------------------
  364.    ''' <param name="startDate">
  365.    ''' The starting date.
  366.    ''' </param>
  367.    '''
  368.    ''' <param name="endDate">
  369.    ''' The ending date.
  370.    ''' </param>
  371.    ''' ----------------------------------------------------------------------------------------------------
  372.    <DebuggerHidden>
  373.    <DebuggerStepThrough>
  374.    Public Sub Start(ByVal startDate As Date,
  375.                     ByVal endDate As Date)
  376.  
  377.        Me.Start(endDate.Subtract(startDate).TotalMilliseconds)
  378.  
  379.    End Sub
  380.  
  381.    ''' ----------------------------------------------------------------------------------------------------
  382.    ''' <summary>
  383.    ''' Starts a time interval measurement given a <see cref="TimeSpan"/>.
  384.    ''' </summary>
  385.    ''' ----------------------------------------------------------------------------------------------------
  386.    ''' <param name="time">
  387.    ''' A <see cref="TimeSpan"/> instance that contains the time interval.
  388.    ''' </param>
  389.    ''' ----------------------------------------------------------------------------------------------------
  390.    <DebuggerHidden>
  391.    <DebuggerStepThrough>
  392.    Public Sub Start(ByVal time As TimeSpan)
  393.  
  394.        Me.Start(time.TotalMilliseconds)
  395.  
  396.    End Sub
  397.  
  398.    ''' ----------------------------------------------------------------------------------------------------
  399.    ''' <summary>
  400.    ''' Pauses the time interval measurement.
  401.    ''' </summary>
  402.    ''' ----------------------------------------------------------------------------------------------------
  403.    ''' <exception cref="Exception">
  404.    ''' TimeMeasurer is not running.
  405.    ''' </exception>
  406.    ''' ----------------------------------------------------------------------------------------------------
  407.    <DebuggerHidden>
  408.    <DebuggerStepThrough>
  409.    Public Sub Pause()
  410.  
  411.        If (Me.State <> TimeMeasurerState.Enabled) Then
  412.            Throw New Exception("TimeMeasurer is not running.")
  413.  
  414.        Else
  415.            Me.measureTimer.Stop()
  416.            Me.timeElapsed.Stop()
  417.  
  418.        End If
  419.  
  420.    End Sub
  421.  
  422.    ''' ----------------------------------------------------------------------------------------------------
  423.    ''' <summary>
  424.    ''' Resumes the time interval measurement.
  425.    ''' </summary>
  426.    ''' ----------------------------------------------------------------------------------------------------
  427.    ''' <exception cref="Exception">
  428.    ''' TimeMeasurer is not paused.
  429.    ''' </exception>
  430.    ''' ----------------------------------------------------------------------------------------------------
  431.    <DebuggerHidden>
  432.    <DebuggerStepThrough>
  433.    Public Sub [Resume]()
  434.  
  435.        If (Me.State <> TimeMeasurerState.Paused) Then
  436.            Throw New Exception("TimeMeasurer is not paused.")
  437.  
  438.        Else
  439.            Me.measureTimer.Start()
  440.            Me.timeElapsed.Start()
  441.  
  442.        End If
  443.  
  444.    End Sub
  445.  
  446.    ''' <summary>
  447.    ''' Stops the time interval measurement.
  448.    ''' </summary>
  449.    ''' ----------------------------------------------------------------------------------------------------
  450.    ''' <exception cref="Exception">
  451.    ''' TimeMeasurer is not running.
  452.    ''' </exception>
  453.    ''' ----------------------------------------------------------------------------------------------------
  454.    <DebuggerHidden>
  455.    <DebuggerStepThrough>
  456.    Public Sub [Stop]()
  457.  
  458.        If (Me.State = TimeMeasurerState.Disabled) Then
  459.            Throw New Exception("TimeMeasurer is not running.")
  460.  
  461.        Else
  462.            Me.Reset()
  463.            Me.isFinished = True
  464.  
  465.            Me.measureTimer.Stop()
  466.            Me.timeElapsed.Stop()
  467.  
  468.        End If
  469.  
  470.    End Sub
  471.  
  472. #End Region
  473.  
  474. #Region " Private Methods "
  475.  
  476.    ''' ----------------------------------------------------------------------------------------------------
  477.    ''' <summary>
  478.    ''' Stops Time intervals and resets the elapsed and remaining time to zero.
  479.    ''' </summary>
  480.    ''' ----------------------------------------------------------------------------------------------------
  481.    Private Sub Reset()
  482.  
  483.        Me.measureTimer.Stop()
  484.        Me.timeElapsed.Reset()
  485.  
  486.    End Sub
  487.  
  488. #End Region
  489.  
  490. #Region " Event Handlers "
  491.  
  492.    ''' ----------------------------------------------------------------------------------------------------
  493.    ''' <summary>
  494.    ''' Handles the <see cref="Timer.Tick"/> event of the <see cref="MeasureTimer"/> timer.
  495.    ''' </summary>
  496.    ''' ----------------------------------------------------------------------------------------------------
  497.    ''' <param name="sender">
  498.    ''' The source of the event.
  499.    ''' </param>
  500.    '''
  501.    ''' <param name="e">
  502.    ''' The <see cref="EventArgs"/> instance containing the event data.
  503.    ''' </param>
  504.    ''' ----------------------------------------------------------------------------------------------------
  505.    Private Sub MeasureTimer_Tick(ByVal sender As Object, ByVal e As EventArgs) _
  506.    Handles measureTimer.Tick
  507.  
  508.        Dim timeDiff As TimeSpan = (Me.timeRemaining - Me.timeElapsed.Elapsed)
  509.  
  510.        ' If finished...
  511.        If (timeDiff.TotalMilliseconds <= 0.0R) _
  512.        OrElse (Me.timeElapsed.ElapsedMilliseconds > DirectCast(Me.measureTimer.Tag, Double)) Then
  513.  
  514.            Me.Reset()
  515.            Me.isFinished = True
  516.  
  517.            If (Me.TimeUpdatedEvent IsNot Nothing) Then
  518.                Dim goal As TimeSpan = TimeSpan.FromMilliseconds(DirectCast(Me.measureTimer.Tag, Double))
  519.                RaiseEvent TimeUpdated(sender, New TimeUpdatedEventArgs(goal, TimeSpan.FromMilliseconds(0.0R), goal))
  520.            End If
  521.  
  522.        Else ' If not finished...
  523.            If (Me.TimeUpdatedEvent IsNot Nothing) Then
  524.                RaiseEvent TimeUpdated(sender, New TimeUpdatedEventArgs(Me.timeElapsed.Elapsed,
  525.                                                                        timeDiff,
  526.                                                                        TimeSpan.FromMilliseconds(DirectCast(Me.measureTimer.Tag, Double))))
  527.            End If
  528.  
  529.        End If
  530.  
  531.    End Sub
  532.  
  533. #End Region
  534.  
  535. #Region " IDisposable Support "
  536.  
  537.    ''' ----------------------------------------------------------------------------------------------------
  538.    ''' <summary>
  539.    ''' To detect redundant calls when disposing.
  540.    ''' </summary>
  541.    ''' ----------------------------------------------------------------------------------------------------
  542.    Private isDisposed As Boolean = False
  543.  
  544.    ''' ----------------------------------------------------------------------------------------------------
  545.    ''' <summary>
  546.    ''' Releases all the resources used by this instance.
  547.    ''' </summary>
  548.    ''' ----------------------------------------------------------------------------------------------------
  549.    <DebuggerStepThrough>
  550.    Public Sub Dispose() Implements IDisposable.Dispose
  551.        Me.Dispose(isDisposing:=True)
  552.        GC.SuppressFinalize(obj:=Me)
  553.    End Sub
  554.  
  555.    ''' ----------------------------------------------------------------------------------------------------
  556.    ''' <summary>
  557.    ''' Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
  558.    ''' Releases unmanaged and - optionally - managed resources.
  559.    ''' </summary>
  560.    ''' ----------------------------------------------------------------------------------------------------
  561.    ''' <param name="isDisposing">
  562.    ''' <see langword="True"/> to release both managed and unmanaged resources;
  563.    ''' <see langword="False"/> to release only unmanaged resources.
  564.    ''' </param>
  565.    ''' ----------------------------------------------------------------------------------------------------
  566.    <DebuggerStepThrough>
  567.    Private Sub Dispose(ByVal isDisposing As Boolean)
  568.  
  569.        If (Not Me.isDisposed) AndAlso (isDisposing) Then
  570.  
  571.            If (Me.measureTimer IsNot Nothing) Then
  572.                Me.measureTimer.Stop()
  573.                Me.measureTimer.Dispose()
  574.            End If
  575.  
  576.            If (Me.TimeUpdatedEvent IsNot Nothing) Then
  577.                RemoveHandler Me.TimeUpdated, Me.TimeUpdatedEvent
  578.            End If
  579.  
  580.        End If
  581.  
  582.        Me.isDisposed = True
  583.  
  584.    End Sub
  585.  
  586. #End Region
  587.  
  588. End Class


Título: Re: Cuenta regresiva a partir de una fecha (VB.Net)
Publicado por: #Aitor en 23 Septiembre 2015, 18:53 pm
Siento haberte hecho modificar parte de tu código, pero mi nivel de programación es pésimo y no entiendo nada...

Estoy en shock (?)


Título: Re: Cuenta regresiva a partir de una fecha (VB.Net)
Publicado por: Eleкtro en 23 Septiembre 2015, 19:39 pm
Siento haberte hecho modificar parte de tu código, pero mi nivel de programación es pésimo y no entiendo nada...

Estoy en shock (?)

La class TimeMeasurer que compartí, solo tienes que copiarla y pegarla en un nuevo archivo.vb, el archivo lo creas desde Visual Studio, Add Item -> Class, y ahí pegas todo el código tal cual lo puse.

La class expone varios eventos, los que te interesan son TimeMeasurer.RemainingTimeUpdated y TimeMeasurer.RemainingTimeFinished, el primer evento se dispara al mismo tiempo que el Timer interno de la class tickea (el intervalo de actualización lo puedes modificar usando la propiedad TimeMeasurer.UpdateInterval), y el otro evento se dispara cuando la cuenta atrás llega a cero.

Arriba te mostré un ejemplo de lo que acabo de mencionar respecto a cómo suscribirte a esos eventos y cómo usar la class en general, ¿hay algo que sigas sin entender?.

Saludos!


Título: Re: Cuenta regresiva a partir de una fecha (VB.Net)
Publicado por: Lekim en 26 Septiembre 2015, 02:07 am
Hola Aitor

Te explico, respondí a tu pregunta en el foro de VisualBasic, de hecho al final te decía que eso no era para .Net.  así que he copiado la respuesta y ahora la pongo aquí (añadiendo alguna cosa).

Veo que ya te ha respondido Elektro, pero él es un programador muy avanzado y a veces su código puede ser un poco difícil de entender como ya has mencionado. Yo soy más como tu así que no creo que tengas problemas para entender el mío.




Código
  1.    Label1.Text = "Dias: " & (-1 * Diarestante) & " Horas: " & Horarestante & " Minutos " & Minutorestante & " Segundos: " & Segundorestante



No soy profesional pero sabía un poco sobre el tema porque hice un programa en el que tenía que ir restando días a partir de una determinada fecha.  Así que he hecho esta otra forma. Creo que se puede simplificar más o hacer de otra manera.


Ejemplo, la línea siguiente resta 3 días a la fecha 5/8/2015 y se obtiene 3/12/2015:
Código
  1.        Dim Fecha As Date = "#5/12/2015#"
  2.        Me.Text = DateAdd(DateInterval.Day, -2, Fecha)
  3.  

Esta otra obtiene la diferéncia en días, meses, años, horas, etc te sadrá valor negativo o postitivo dependiendo de si Date1 es anterior o posterior a Date2. En este caso obtiene días porque he puesto DateInterval.Day, si quieres meses tienes que poner DateInterval.Month, y así sucesivamente:
Código
  1. DateAndTime.DateDiff(DateInterval.Day, Date1, Date2)
  2.  

Espero que te sirva, sino para lo que quieres que sirva como ejemplo.

Código
  1. '//////////////////
  2. '////Por Lekim ////
  3. '///29/09/2015/////
  4. '//////////////////
  5. Option Explicit On
  6. Option Infer Off
  7. Option Strict On
  8. Public Class Form1
  9.  
  10.    Dim DiaMenos As Integer
  11.    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
  12.        '  Dim Año As Integer = Microsoft.VisualBasic.DateAndTime.Year(Now) '2015
  13.  
  14.        Dim FechaLim As Object = "#5/10/2015#" 'Fecha futura límite
  15.        Dim Reloj24h As Object = "#23:59:59#" '24 horas del día a restar
  16.        Dim RelojNow As Object = DateAndTime.TimeValue(CStr(Date.Now))
  17.        Dim TotalDias As Integer = CInt(DateAndTime.DateDiff(DateInterval.Day, CDate(Date.Now), CDate(FechaLim))) 'Días hasta la fecha límite
  18.        Dim DiasRestantes As Integer 'Dias restante que quedan
  19.        Dim CronoTime As Date 'Nueva tiempo resultado de ir restandos segundos
  20.        Dim CronoFecha As Object = String.Empty 'Nueva fecha resultado de ir restando días
  21.  
  22.        Dim m As Integer : Dim h As Integer : Dim s As Integer
  23.        h = CInt((DateDiff(DateInterval.Minute, CDate(RelojNow), CDate(Reloj24h)) / 60))  'Obtiene las horas
  24.        m = CInt(DateDiff(DateInterval.Minute, CDate(RelojNow), CDate(Reloj24h)) - (h * 60)) 'Obtiene los minutos
  25.        s = CInt(DateDiff(DateInterval.Second, CDate(RelojNow), CDate(Reloj24h)) - ((h * 3600) + (m * 60)))
  26.  
  27.        'Resta un segundo
  28.        If h < 0 Then h = h * (-1)
  29.        If m < 0 Then m = m * (-1)
  30.        If s < 0 Then s = s * (-1)
  31.        CronoTime = CDate((h & ":" & m & ":" & s).ToString)
  32.  
  33.        'Si el cronómentro llega a cero resta un día
  34.        If Hour(CronoTime) = 0 And Minute(CronoTime) = 0 And Second(CronoTime) = 0 Then DiaMenos -= 1
  35.  
  36.        CronoFecha = DateAdd(DateInterval.Day, DiaMenos, CDate(FechaLim)) 'Obtiene una fecha resultado de restar x días a la fecha límite
  37.  
  38.        'Convierte las fechas a DATE y obtiene la diferencia de días
  39.        Dim datTim1 As Date = CDate(FechaLim) : Dim datTim2 As Date = CDate(CronoFecha)
  40.        DiasRestantes = CInt(TotalDias - DateAndTime.DateDiff(DateInterval.Day, CDate(datTim2), CDate(datTim1)))
  41.  
  42.        Label1.Text = _
  43.        "Fecha Actual: " & Strings.FormatDateTime(Date.Now, DateFormat.LongDate) & ControlChars.CrLf & _
  44.        "Fecha Límite: " & Strings.FormatDateTime(CDate(Replace(CStr(CDate(FechaLim)), "#", "", 1)), DateFormat.LongDate) & ControlChars.CrLf &
  45.        "Quedan: " & DiasRestantes & " días " & "y " & Strings.Format(CronoTime, "HH:mm:ss")
  46.  
  47.    End Sub
  48. End Class
  49.  

más info:
https://msdn.microsoft.com/es-es/library/b5xbyt6f%28v=vs.90%29.aspx (https://msdn.microsoft.com/es-es/library/b5xbyt6f%28v=vs.90%29.aspx)

Saludos




Otra cosa, si quieres saber cuantos días tiene un mes de un determinado año usa:

Código
  1. 'devuelve 28
  2. Date.DaysInMonth(2015, 2)




Título: Re: Cuenta regresiva a partir de una fecha (VB.Net)
Publicado por: Eleкtro en 26 Septiembre 2015, 19:48 pm
Por si sirve de algo, he vuelto a refactorizar el código fuente para que se entienda mejor, ahora solo expongo UN solo evento al que podemos suscribirnos para obtener el tiempo transcurrido, el tiempo restante, y el tiempo límite o meta.

El ejemplo de arriba también lo he modificado, más simple que esto es imposible ya:

Cita de: http://foro.elhacker.net/net/cuenta_regresiva_a_partir_de_una_fecha_vbnet-t441934.0.html;msg2040412#msg2040412
Código
  1.    Public NotInheritable Class Form1 : Inherits Form
  2.  
  3.        Private WithEvents countdown As New TimeMeasurer With {.UpdateInterval = 100}
  4.  
  5.        Private Shadows Sub Load() Handles MyBase.Load
  6.  
  7.            ' Medir el lapso de 1 mes desde la fecha y hora actual.
  8.            Me.countdown.Start(DateTime.Now, DateTime.Now.AddMonths(1))
  9.  
  10.        End Sub
  11.  
  12.        Private Sub Countdown_TimeUpdated(ByVal sender As Object, ByVal e As TimeMeasurer.TimeUpdatedEventArgs) _
  13.        Handles countDown.TimeUpdated
  14.  
  15.            Me.lblCountDown.Text = String.Format("Days:{0:00} Hours:{1:00} Minutes:{2:00} Seconds:{3:00}",
  16.                                                 e.Remaining.Days, e.Remaining.Hours, e.Remaining.Minutes, e.Remaining.Seconds)
  17.  
  18.        End Sub
  19.  
  20.    End Class

Basicamente el código fuente que compartí encapsula todos los miembros necesarios para resolver el problema que tienes de una forma amistosa orientada a eventos xD.

De todas formas si aun sigues sin saber cómo utilizarlo a pesar del ejemplo, o si por algún motivo prefieres no usar mi solución entonces ahí tienes la alternativa de @Lekim, aunque os aconsejo a los dos que cambieis los hábitos que están siguiendo ya que son perjudiciales para el aprendizaje, por ejemplo no es necesario la aplicación de operaciones aritméticas para calcular manualmente las horas, dias, minutos y demás, pueden usar las propiedades que expone un objeto TimeSpan o un objeto Date cómo mencioné al principìo!, con eso lo resolverían TODO sin complicarse.



@Lekim, con tu permiso, te muestro como podrías simplificar para mejorar el código que compartiste:

Código
  1. Public Class Form1
  2.  
  3.    Dim culture As CultureInfo = CultureInfo.GetCultureInfo("es-ES")
  4.    Dim fechaLimite As Date = Date.ParseExact("01/10/2015 00:00:00", "dd/MM/yyyy hh:mm:ss", culture, DateTimeStyles.None)
  5.  
  6.    Private Sub Form1_Shown() Handles MyBase.Shown
  7.        Timer1.Enabled = True
  8.    End Sub
  9.  
  10.    Private Sub Timer1_Tick() Handles Timer1.Tick
  11.  
  12.        Dim dateDiff As TimeSpan = fechaLimite.Subtract(Date.Now)
  13.        Dim dateFormat As String = "dddd dd, MMMM, yyyy"
  14.  
  15.        Dim sb As New StringBuilder
  16.        With sb
  17.            .AppendFormat("Fecha Actual: {0}", Date.Today.ToString(dateFormat, culture))
  18.            .AppendLine()
  19.            .AppendFormat("Fecha Límite: {0}", fechaLimite.ToString(dateFormat, culture))
  20.            .AppendLine()
  21.            .AppendFormat("Quedan: {0}", String.Format("{0:0}d. {1:00}h. {2:00}m. {3:00}s.",
  22.                                                       dateDiff.TotalDays, dateDiff.Hours,
  23.                                                       dateDiff.Minutes, dateDiff.Seconds))
  24.        End With
  25.  
  26.        Me.Label1.Text = sb.ToString
  27.  
  28.    End Sub
  29.  
  30. End Class

(http://i.imgur.com/L61wEGC.png)

También te recomiendo activar las declaraciones "Option" cuando programes bajo VB.Net, verias las decenas de fallos que cometiste en aquél código sin darte cuenta, sobre todo de casting.

Otra recomendación que les hago, eviten CUALQUIER uso de los miembros expuestos en el namespace Microsoft.VisualBasic, cómo por ejemplo DateDiff, DateAdd, FormatDateTime, Len, Mid, etc, evitenlo todo sin excepción, todo eso es morralla rescatada de VisualBasic 6 para familiarizar a los que migran a VB.Net, aunque es puro código .Net pero no tan optimizado, así que deberían usar los equivalentes del resto de la librería de classes de .Net.

Saludos!


Título: Re: Cuenta regresiva a partir de una fecha (VB.Net)
Publicado por: Lekim en 27 Septiembre 2015, 14:30 pm
Hola Elektro. Gracias por el comentario

Citar
También te recomiendo activar las declaraciones "Option" cuando programes bajo VB.Net

He puesto Option Explicit On  a principio de código pero no me muestra ningún fallo. Si que es cierto que hay variables sin uso pero es porque en un principio lo hice de una manera y luego lo cambié, porque en un prinicipio usaba la variable Dim Reloj24h As Object = "#23:59:59#"  y lo le iba restando los segundos con Segundos -=1 y DateAdd pero caí en que no sería correcto decir que desde ahora hasta pasado mañana quedan 1 día y 23:59:59 a no ser que ahora mismo sean  justo las 00:00:00 de la noche. Habría que descontar las horas desde las doce hasta la hora actual. Por eso anulé 'Dim SegundoMenos As Integer, pero aunque estaba, no se usaba. Simplemente lo dejé para que se viera esa opción de hacerlo así.

Bueno, he corregido un poco el código ya que según la hora dabe error en CronoTime (línea 29) y he puesto Option Explicit On. Ejecuto el código y me va perfecto.


En cuanto a la librería de classes de .Net me gustaría que me dijeras como encontrar lo que busco cuando quiero hacer algo porque con los miembros Microsoft.VisualBasic es fácil intuir como contruir el código, además que es muy directo. Es decir, quiero saber la diferencia de fecha lo puedo hacer sólo con una línea de código , pero NO con con las clases de .Net. que son mucho más rebuscadas, como su puede ver en tu conversión. Voy a analizar tu código a ver como se usan esas clases que pones. No hace falta que me las expliques ya experimento yo  ;)

También he visto que usas Shown en lugar de Load, ¿Cuál es la diferencia?


saludos


  





Título: Re: Cuenta regresiva a partir de una fecha (VB.Net)
Publicado por: Eleкtro en 27 Septiembre 2015, 16:08 pm
He puesto Option Explicit On  a principio de código pero no me muestra ningún fallo.

Pero no estás activando la opción de los casteos ni desactivando la inferencia de types, solamente activaste la declaración explícita de variables.

Código
  1. Option Explicit On
  2. ' +
  3. Option Strict On
  4. Option Infer Off

Pruébalo de nuevo y verás de lo que te hablaba. :P

PD: Puedes activar por edefecto esas opciones para todos los proyectos/classes nuevos, en el menú Tools -> Options -> Projects and Solutions -> VB Defaults de Visual Studio.



También he visto que usas Shown en lugar de Load, ¿Cuál es la diferencia?

El evento Form.Shown se dispara cuando la ventana del Form se muestra.

El evento Form.Load se dispara cuando el Form se carga (esto ocurre antes de mostrar la ventana).

En el ejemplo de arriba lo usé por costumbre, nada relevante.



En cuanto a la librería de classes de .Net me gustaría que me dijeras como encontrar lo que busco cuando quiero hacer algo

Creo que no existe un artículo que especifique esos miembros equivalentes en la documentación de la MSDN, pero si que podemos encontrar esa tabla de miembros equivalentes en otras fuentes:
Visual Basic 6 to .NET Function Equivalents (http://en.wikibooks.org/wiki/Visual_Basic_.NET/Visual_Basic_6_to_.NET_Function_Equivalents)

Si lo que buscas no está ahí entonces siempre puedes formular una pregunta en el foro y con gusto te ayudaré. (pero en otro post. No hagamos demasiado offtopic en este hilo)



con los miembros Microsoft.VisualBasic es fácil intuir como contruir el código, además que es muy directo.

Nombres intuitivos si, pero solo eso. De todas formas los miembros que están fuera de ese namespace también son intuitivos, simplemente los desconocerás, pero intuitivos te aseguro que si lo son.

La gente suele pensar que me quejo demasiado de este asunto en concreto, que no me tengo que obsesionar con tanta "perfección" en el rendimiento por que da igual usar un método u otro con argumentos como los que has expuesto de que "es más intuitivo" o etc, así que despues de esto no se ya que pensarán, pero bueno, supongo que es mi deber intentar defender los buenos hábitos de programación .Net xD.

Para empezar, si aprendes a usar Microsoft.VisualBasic y te acostumbras a ello, en realidad no estás aprendiendo a usar .Net. Digamos que el Namespace Microsoft.VisualBasic es cómo el lenguaje Batch en programación, algo que está ahí, se le llama lenguaje, pero no se puede clasificar cómo lenguaje de programación realmente, pues eso mismo es el namespace Microsoft.VisualBasic, está ahí por cuestiones de compatibilidad, se puede usar siempre que lo necesites, pero lo mejor sería no utilizarlo por que no lo necesitas.

Todo lo que existe en Microsoft.VisualBasic es un código menos optimizado y son miembros con menos overloads (sustitutos). En resumen, la funcionalidad es más limitada.

Aparte, si vieras el código fuente (mediante reflection) verías que no es tan "directo" internamente hablando, hacen muchas vueltas y la mayoría de los métodos no se valen por si mismos así que en realidad son simples wrappers (gracias a dios) de los métodos optimizados de .Net, por ejemplo la función Microsoft.VisualBasic.Strings.Mid() (entre otras) en realidad se limitan a hacer unas evaluaciones irrelevantes del argumento y seguidamente llama a System.String.Substring(), vuelve a hacer las mismas evaluaciones del argumento (si. esto quiere decir que cuando llamas a Mid y a toda esa otra morralla, trabajan innecesareamente x2) y por último devuelve el valor que tenga que devolver, es quien hace el trabajo de verdad.

Aquí puedes ver una referencia del código fuente de la librería de classes de .Net Framework:
➢ http://referencesource.microsoft.com/
(creo que es una referencia parcial)

Saludos


Título: Re: Cuenta regresiva a partir de una fecha (VB.Net)
Publicado por: Lekim en 29 Septiembre 2015, 13:35 pm
Gracias por la ayuda Elektro

He vuelto a retocar mi código y ahora creo que no tiene ningún error, excepto los del uso de los miembros de VisualBasic. Aunque no se puede considerar error, si no como dices una forma poco eficiente de programar en .NET.

Tu información me va de perlas, de nuevo gracias  ;-)