Error: Formato o funciones de DatePart pueden devolver número incorrecto de semana para el último lunes de año actual

IMPORTANTE: Este artículo ha sido traducido por un software de traducción automática de Microsoft (http://support.microsoft.com/gp/mtdetails) en lugar de un traductor humano. Microsoft le ofrece artículos traducidos por un traductor humano y artículos traducidos automáticamente para que tenga acceso en su propio idioma a todos los artículos de nuestra base de conocimientos (Knowledge Base). Sin embargo, los artículos traducidos automáticamente pueden contener errores en el vocabulario, la sintaxis o la gramática, como los que un extranjero podría cometer al hablar el idioma. Microsoft no se hace responsable de cualquier imprecisión, error o daño ocasionado por una mala traducción del contenido o como consecuencia de su utilización por nuestros clientes. Microsoft suele actualizar el software de traducción frecuentemente.

Haga clic aquí para ver el artículo original (en inglés): 200299
Este artículo se ha archivado. Se ofrece "tal cual" y no se volverá a actualizar.
Síntomas
Cuando usa función el formato o ParcFecha para determinar el número de semana de fechas utilizando la siguiente sintaxis:
Format(AnyDate, "ww", vbMonday, vbFirstFourDays)DatePart("ww", AnyDate, vbMonday, vbFirstFourDays)				
se devuelve el último lunes de algunos años del calendario como semana 53 cuando debería ser semana 1.
Causa
Al determinar el número de semana de una fecha con el estándar ISO 8601, la llamada de función subyacente en el archivo Oleaut32.dll devuelve erróneamente la semana 53 en lugar de la semana 1 para el lunes pasado en ciertos años.
Solución
Utilizar una función definida por el usuario para devolver el número de semana según las reglas del estándar ISO 8601. En este artículo se incluye un ejemplo.
Estado
Microsoft ha confirmado que este es un problema en el archivo Oleaut32.dll.
Más información
El estándar ISO 8601 se utiliza ampliamente en Europa y incluye lo siguiente:
  ISO 8601 "Data elements and interchange formats - Information interchange   - Representation of dates and times"  ISO 8601 : 1988 (E) paragraph 3.17:  "week, calendar: A seven day period within a calendar year, starting  on a Monday and identified by its ordinal number within the year;  the first calendar week of the year is the one that includes the  first Thursday of that year. In the Gregorian calendar, this is  equivalent to the week which includes 4 January."				
Esto se puede implementar aplicando estas reglas para semanas de calendario:
  • Un año se divide en 52 o 53 semanas de calendario.
  • Una semana del calendario tiene 7 días. El lunes es el día 1, el domingo es el día 7.
  • La primera semana del calendario un año es el que contiene al menos 4 días.
  • Si un año no concluye en domingo, bien sus últimos días de 1-3 pertenecen a la primera semana del año siguiente o los primeros 1-3 días del año siguiente pertenece a la última semana del año presente.
  • Sólo un año inicial o concluir un jueves tiene 53 semanas de calendario.
En Visual Basic y Visual Basic para aplicaciones, todas las funciones fecha, excepto para la función DateSerial , procede de las llamadas al archivo Oleaut32.dll. Puesto que las Format() ParcFecha() funciones y pueden devolver el número de semana de calendario de una fecha dada, ambos se ven afectados por este error. Para evitar este problema, debe utilizar el código alternativo que proporciona este artículo.

Pasos para reproducir este comportamiento

  1. Inicie un proyecto EXE estándar en Visual Basic. Se creará Form1 de manera predeterminada.
  2. Agregue dos CommandButtons a Form1.
  3. Pegue el código siguiente en la ventana de código de Form1:
    Option ExplicitPrivate Sub Command1_Click()' This code tests a "problem" date and the days around itDim DateValue As DateDim i As IntegerDebug.Print "   Format function:"DateValue = #12/27/2003#For i = 1 To 4   ' examine the last 4 days of the year    DateValue = DateAdd("d", 1, DateValue)    Debug.Print "Date: " & DateValue & "   Day: " & _      Format(DateValue, "ddd") & "   Week: " & _      Format(DateValue, "ww", vbMonday, vbFirstFourDays)Next iEnd SubPrivate Sub Command2_Click()' This code lists all "Problem" dates within a specified range  Dim MyDate As Date  Dim Years As Long  Dim days As Long  Dim woy1 As Long  Dim woy2 As Long  Dim ToPrint As String  For Years = 1850 To 2050    For days = 0 To 3      MyDate = DateSerial(Years, 12, 28 + days)      woy1 = Format(MyDate, "ww", vbMonday, vbFirstFourDays)      woy2 = Format(MyDate, "ww", vbMonday, vbFirstFourDays)      If woy2 > 52 Then        If Format(MyDate + 7, "ww", vbMonday, vbFirstFourDays) = 2 Then _          woy2 = 1      End If      If woy1 <> woy2 Then        ToPrint = MyDate & String(13 - Len(CStr(MyDate)), " ")        ToPrint = ToPrint & Format(MyDate, "dddd") & _          String(10 - Len(Format(MyDate, "dddd")), " ")        ToPrint = ToPrint & woy1 & String(5 - Len(CStr(woy1)), " ")        ToPrint = ToPrint & woy2        Debug.Print ToPrint      End If    Next days  Next YearsEnd Sub					
  4. Mantenga presionada la tecla CTRL y presione la tecla G para abrir la ventana Inmediato.
  5. Ejecute el proyecto, haga clic en Command1 y observe los siguientes resultados en la ventana Inmediato:
       Format function:Date: 12/28/03   Day: Sun   Week: 52Date: 12/29/03   Day: Mon   Week: 53Date: 12/30/03   Day: Tue   Week: 1Date: 12/31/03   Day: Wed   Week: 1						
    tenga en cuenta que con este formato, todas las semanas empiezan el lunes, por lo que debe considerar el inicio de 1 semana y no forma parte de semana 53 en 12/29/2003.
  6. Haga clic en Command2 para ver una lista de fechas en el intervalo especificado que experimente este problema. La lista incluye la fecha, el día de semana (siempre lunes), la semana # devueltos por el formato (53) y debe devolver el número de semana (1). Por ejemplo:
    12/29/1851   Monday    53   112/31/1855   Monday    53   112/30/1867   Monday    53   112/29/1879   Monday    53   112/31/1883   Monday    53   112/30/1895   Monday    53   1...					

Soluciones provisionales

Si utiliza las funciones de formato o DatePart , tiene que comprobar el valor devuelto y, cuando es 53, ejecute otra comprobación y forzar una devolución de 1, si es necesario. Este ejemplo de código demuestra una forma de hacerlo:
Function WOY (MyDate As Date) As Integer   ' Week Of Year  WOY = Format(MyDate, "ww", vbMonday, vbFirstFourDays)  If WOY > 52 Then    If Format(MyDate + 7, "ww", vbMonday, vbFirstFourDays) = 2 Then WOY = 1  End IfEnd Function				
se puede evitar el uso estas funciones para determinar número de semana escribiendo código que implementa las reglas de ISO 8601 descritas anteriormente. En el ejemplo siguiente se muestra una función de reemplazo para devolver el número de semana.

Ejemplo de paso a paso

  1. Inicie un proyecto EXE estándar en Visual Basic. Se creará Form1 de manera predeterminada.
  2. En el menú proyecto , agregue un nuevo módulo y pegue en el siguiente código:
    Option ExplicitFunction WeekNumber(InDate As Date) As Integer  Dim DayNo As Integer  Dim StartDays As Integer  Dim StopDays As Integer  Dim StartDay As Integer  Dim StopDay As Integer  Dim VNumber As Integer  Dim ThurFlag As Boolean  DayNo = Days(InDate)  StartDay = Weekday(DateSerial(Year(InDate), 1, 1)) - 1  StopDay = Weekday(DateSerial(Year(InDate), 12, 31)) - 1  ' Number of days belonging to first calendar week  StartDays = 7 - (StartDay - 1)  ' Number of days belonging to last calendar week  StopDays = 7 - (StopDay - 1)  ' Test to see if the year will have 53 weeks or not  If StartDay = 4 Or StopDay = 4 Then ThurFlag = True Else ThurFlag = False  VNumber = (DayNo - StartDays - 4) / 7  ' If first week has 4 or more days, it will be calendar week 1  ' If first week has less than 4 days, it will belong to last year's  ' last calendar week  If StartDays >= 4 Then      WeekNumber = Fix(VNumber) + 2   Else      WeekNumber = Fix(VNumber) + 1  End If  ' Handle years whose last days will belong to coming year's first   ' calendar week  If WeekNumber > 52 And ThurFlag = False Then WeekNumber = 1  ' Handle years whose first days will belong to the last year's   ' last calendar week  If WeekNumber = 0 Then     WeekNumber = WeekNumber(DateSerial(Year(InDate) - 1, 12, 31))  End IfEnd FunctionFunction Days(DayNo As Date) As Integer  Days = DayNo - DateSerial(Year(DayNo), 1, 0)End Function					
  3. Agregue un CommandButton a Form1.
  4. Pegue el código siguiente en la ventana de código de Form1:
    Private Sub Command1_Click()   Dim DateValue As Date, i As Integer      Debug.Print "   WeekNumber function:"   DateValue = #12/27/2003#   For i = 1 To 4   ' examine the last 4 days of the year       DateValue = DateAdd("d", 1, DateValue)       Debug.Print "Date: " & DateValue & "   Day: " & _          Format(DateValue, "ddd") & "   Week: " & WeekNumber(DateValue)   Next iEnd Sub					
  5. Mantenga presionada la tecla CTRL y presione la tecla G para abrir la ventana Inmediato.
  6. Ejecute el proyecto y haga clic en Command1 para ver los resultados siguientes en la ventana Inmediato:
       WeekNumber function:Date: 12/28/03   Day: Sun   Week: 52Date: 12/29/03   Day: Mon   Week: 1Date: 12/30/03   Day: Tue   Week: 1Date: 12/31/03   Day: Wed   Week: 1					
    nota que lunes se considera 1 semana como debería ser.

Propiedades

Id. de artículo: 200299 - Última revisión: 12/05/2015 10:27:20 - Revisión: 3.0

Microsoft Visual Basic 6.0 Edición de aprendizaje, Microsoft Visual Basic 6.0 Professional Edition, Microsoft Visual Basic Enterprise Edition for Windows 6.0, Microsoft Visual Basic Control Creation Edition, Microsoft Visual Basic 5.0 Learning Edition, Microsoft Visual Basic 5.0 Professional Edition, Microsoft Visual Basic 5.0 Enterprise Edition, Microsoft Visual Basic 4.0 Standard Edition, Microsoft Visual Basic 4.0 Professional Edition, Microsoft Visual Basic 4.0 32-Bit Enterprise Edition, Microsoft Visual Basic for Applications 5.0, Microsoft Visual Basic for Applications 6.0

  • kbnosurvey kbarchive kbmt kbbug kbdatetime kbpending KB200299 KbMtes
Comentarios