Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Cálculo de fechas

2 views
Skip to first unread message

tatintin

unread,
Apr 4, 2008, 3:56:03 AM4/4/08
to
Hola a todos.
Tengo un problema para calcular una fecha.
Tengo en un formulario, que tiene como origen la tabla "Exps", hay
dato de fecha ([Fecha1]) y Hora Local ([HoraLT]). Necesitaría calcular
la hora UTC ([HoraUTC]) partiendo de la premisa de que desde el año
2006, el cambio horario en España es el siguiente
Año 2006
entre 26/03/2006 02:00 - 29/10/2006 03:00 HoraUTC = HoraLT -2 por
fuera de este rango HoraUTC = HoraLT-1
Año2007
entre 25/03/2007 02:00 - 28/10/2007 03:00 HoraUTC = HoraLT -2 por
fuera de este rango HoraUTC = HoraLT-1
Año 2008
entre 30/03/2008 02:00 - 26/10/2008 03:00 HoraUTC = HoraLT -2 por
fuera de este rango HoraUTC = HoraLT-1
Año 2009
entre 29/03/2009 02:00 - 25/10/2009 03:00 HoraUTC = HoraLT -2 por
fuera de este rango HoraUTC = HoraLT-1

Inserté un módulo para probar con el año 2006. Es el siguiente:

Public Function HoraUniversal() As Long
If [HoraLT] >= 38802.08333 And Me.[9_HoraLT] < 39019.125 Then
HoraUniversal = [HoraLT] - (0.041666667 * 2)
Else
HoraUniversal = [HoraLT] - 0.041666667
End If
End Function

Luego puse como origen de datos en el campo HoraUTC del formulario la
expresión HoraUniversal() pero la cosa no funciona.
¿Alguna pista?
Gracias
Tatintin

Patxi Sanz

unread,
Apr 4, 2008, 1:25:53 PM4/4/08
to
Hola Tatintin:

Si el valor que devuelve la función lo defines como Long (entero largo),
estás desestimando las horas, minutos y segundos que se almacenan en la
parte decimal, ya que este tipo de datos no admite decimales y los trunca. O
lo defines como Double o como lo que es: Date.

--
Un saludo,


Patxi Sanz
patxisanz[ARROBA]yahoo[PUNTO]es
http://es.geocities.com/patxisanz/index.html
Tudela (NA)

tatintin

unread,
Apr 7, 2008, 3:54:31 AM4/7/08
to
Creo que voy a pasar del módulo y directamente lo hago en el
formulario, ahí si me funciona ¿Porqué?.....¡Ni idea!
¿Que problema puedo tener al calcularlo sobre el formulario
directamente y no con una función creada en un módulo?
Gracias.

tatintin

unread,
Apr 7, 2008, 7:34:17 AM4/7/08
to
Pues no......no funciona la cosa definitivamente. Lo hice en un
formulari en otra base de datos que creé como de pruebas y a las mil
maravilas pero en la que me trae loco no.
Ahora metí un campo independiente en el formulario, que concatena la
fecha y la hora que están en los campos separados y la función la
modifiqué así:

Public Function HoraUniversal() As Date
If (FechaInfracc2 >= #3/26/2006 2:00:00 AM# And FechaInfracc2 <
#10/29/2006 3:00:00 AM#) Or _
(FechaInfracc2 >= #3/25/2007 2:00:00 AM# And FechaInfracc2 <
#10/28/2007 3:00:00 AM#) Or _
(FechaInfracc2 >= #3/30/2008 2:00:00 AM# And FechaInfracc2 <
#10/26/2008#) Or _
(FechaInfracc2 >= #3/29/2009 2:00:00 AM# And FechaInfracc2 <
#10/25/2009#) Then
HoraUniversal = FechaInfracc2 - (1 / 12) ' resta dos horas
Else
HoraUniversal = FechaInfracc2 - (1 / 24)' resta una hora
End If
End Function

Siendo FechInfracc2 la concatenación de HoraLT&" "&FechaEvento.
No me funciona
Será por poner la función en un módulo en donde tengo otra función
pública?
Una ayudita Please........

Patxi Sanz

unread,
Apr 7, 2008, 9:35:12 AM4/7/08
to
Para mí, que no funciona porque a la función no le indicas el parámetro
FechaInfracc2 de ninguna forma: ni como argumento en su declaración, ni
indicando que es un cuadro de texto de un formulario con la línea
Forms!NombreDelFormulario!FechaInfracc2.

Por otra parte, no indicas cómo la usas: si en la propiedad Origen del
control de un control, en un evento, etc, con lo que no se sabe cómo la
llamas y a qué le asignas el valor que devuelve.

Por cierto, dices que no funciona, pero no dices qué es lo que no funciona:
¿da un error, qué error, devuelve siempre la misma fecha, cierra Access,
sale un duende bailando en el centro de la pantalla?

tatintin

unread,
Apr 8, 2008, 2:01:10 AM4/8/08
to
Hola Patxi. Muchas gracias por tu ayuda.
Lo que me pasa es que el campo calculado (en donde aplico la función
HoraUniversal) no calcula nada, se queda en blanco.
¿De qué forma podría construir una función a la que se pasaran dos
parámetros, fecha y hora para que me calculara la hora UTC con base en
el post número 4?
Muchas gracias de nuevo. Por cierto, destripé el ejemplo de tu web con
uso de fechas y no me aclaro, intentaré guardarme para este fin de
semana mirarlo a consciencia.

Un saludo,


Tatintin.

tatintin

unread,
Apr 8, 2008, 6:40:24 AM4/8/08
to
Después de abusar de "la neurona", hice la siguiente modificación para
intentar crear una función con dos parámetros, Fecha y Hora. No sé
hasta qué punto está bien hecha aunque en principio debería funcionar
según las anotaciones que me hiciste Patxi:

Public Function HoraUniversal(FechaInfracc As Date, HoraLT As Date) As
Date
FechaInfracc = Form_F1_Expedientes.FechaInfracc
HoraLT = Form_F1_Expedientes.HoraLT
Dim Fecha2, Hora2 As Date
If (FechaInfracc >= #3/26/2006# And Fecha2 <= #10/29/2006#) Or
_
(FechaInfracc >= #3/25/2007# And FechaInfracc <= #10/28/2007#)
Or _
(FechaInfracc >= #3/30/2008# And FechaInfracc <= #10/26/2008#)
Or _
(FechaInfracc >= #3/29/2009# And FechaInfracc <= #10/25/2009#)
Then
If FechaInfracc = #3/26/2006# Or FechaInfracc = #3/25/2007# Or
FechaInfracc = #3/30/2008# Or FechaInfracc = #3/29/2009# Then
If HoraLT >= #2:00:00 AM# Then
Hora2 = HoraLT - 2
End If
Hora2 = HoraLT - 2
Else
Hora2 = HoraLT - 1
End If
End If
End Function

Luego pretendo que se calcule en el campo HoraUTC que tengo en el
formulario como valor por defecto =HoraUniversal([FechaInfracc],
[HoraLT])
¿Qué estoy haciendo mal?
Un saludo,
Tatintin

tatintin

unread,
Apr 8, 2008, 8:01:50 AM4/8/08
to
Aunque esto me funciona, me parece que es bastante carpintero (sin
ofender) quisiera saber como ahorrar código:

Private Sub Form_Current()
Dim HoraLT, HoraUTC As Date

If (Me.FechInfracc >= #3/26/2006# And Me.FechInfracc <=
#10/29/2006#) Or _
(Me.FechInfracc >= #3/25/2007# And Me.FechInfracc <= #10/28/2007#)
Or _
(Me.FechInfracc >= #3/30/2008# And Me.FechInfracc <= #10/26/2008#)
Or _
(Me.FechInfracc >= #3/29/2009# And Me.FechInfracc <= #10/25/2009#)
Or _
(Me.FechInfracc = #3/26/2006# And Me.HoraLT >= #2:00:00 AM#) Or _
(Me.FechInfracc = #3/25/2007# And Me.HoraLT >= #2:00:00 AM#) Or _
(Me.FechInfracc = #3/30/2008# And Me.HoraLT >= #2:00:00 AM#) Or _
(Me.FechInfracc = #3/29/2009# And Me.HoraLT >= #2:00:00 AM#) Or _
(Me.FechInfracc = #10/29/2006# And Me.HoraLT < #3:00:00 AM#) Or _
(Me.FechInfracc = #10/28/2007# And Me.HoraLT < #3:00:00 AM#) Or _
(Me.FechInfracc = #10/26/2008# And Me.HoraLT < #3:00:00 AM#) Or _
(Me.FechInfracc = #10/25/2009# And Me.HoraLT < #3:00:00 AM#) Then
Me.HoraUTC = Me.HoraLT - (1 / 12)
Else
Me.HoraUTC = Me.HoraLT - (1 / 24)
End If
End Sub
___
Funciona casi a la perfección, el problema es que en los registros
nuevos sale el típico mesaje de depuración porque HoraLT y FechInfracc
están vacíos.
------
Muchas gracias.
Tatintin

Patxi Sanz

unread,
Apr 8, 2008, 11:24:39 AM4/8/08
to
Veamos:

Si declaras argumentos en una función, es porque le vamos a pasar esos
valores, con lo que no necesitamos indicarlos luego. Así, si a tu función la
declaras como:

Public Function HoraUniversal(FechaInfracc As Date, HoraLT As Date) As Date

No necesitas ajustar luego esos parámetros:

FechaInfracc = Form_F1_Expedientes.FechaInfracc
HoraLT = Form_F1_Expedientes.HoraLT

Ya que se los vas a pasar cuando llames a la función. Eso es lo bueno de los
parámetros, cuando los has declarado puedes pasar luego, en tu caso, la
fecha y hora de 2 controles de un formulario, o de 2 controles de un
informe, o de 2 campos de una consulta, y la función funcionará igual, sin
necesidad de modificarla para el formulario, el informe o la consulta.

Te aconsejo que revises el manual de VBA del maestro Olaz:

- http://www.olaz.net

Patxi Sanz

unread,
Apr 8, 2008, 11:33:35 AM4/8/08
to
Si un campo está vacío, es normal que te salte un error. Debes comprobar si
está vacío con Nz o IsNull, antes de usar el valor que tiene.

Para reducir el código, debemos ver cómo se puede reducir:

1.- ¿Cuándo se hace el cambio de horario en verano? El último domingo de
marzo, a las 2 de la mañana
2.- ¿Cuándo se hace el cambio de horario en invierno? El último domingo de
octubre, a las 3 de la mañana.

Teniendo esto, ¿qué podemos hacer? Hay varias posibilidades:

1.- Comprobar el mes: si es Enero, Febrero, Noviembre o Diciembre, es
horario de invierno.
2.- Si el mes es Abril, Mayo, Junio, Julio, Agosto o Septiembre, el horario
es verano.
3.- Si el mes es Marzo u Octubre, calcular el último domingo. Si el día
pasado es anterior al último domingo de marzo, es horario de invierno. Si es
posterior, es horario de verano. Con Octubre, es parecido, pero al revés:
anterior al último domingo, horario de verano; posterior, horario de
invierno.

Otra posibilidad más reducida:

1.- Calcular el último domingo de Marzo y el último de Octubre.
2.- Si la fecha está entre las 2:00 del último domingo de marzo, y las 3:00
del último domingo de octubre, es horario de verano.
3.- Cualquier otra fecha es horario de invierno.

tatintin

unread,
Apr 9, 2008, 6:59:02 AM4/9/08
to
La verdad es que mirando un poco la BBDD de tu página con ejemplos de
cálculos de fecha, no me aclaro, la función que mas me podría servir
es la del domingo de pascua modificándola, pero no se por donde
cogerla ya que no tiene comentarios en las líneas de código y no se el
porqué de los números que allí aparecen.Por ejemplo, los cálculos para
definir la variable "d "y "e".
¿Me ayudarías a descifrarlo?
Un saludo,
Tatintín

Patxi Sanz

unread,
Apr 9, 2008, 11:23:31 AM4/9/08
to
El cálculo del Domingo de Pascua no es mío. Tal y como aparece en la
cabecera del módulo, está cogido de Wikipedia:

- http://es.wikipedia.org/wiki/Cálculo_de_la_fecha_de_Pascua

Y de un hilo en este mismo grupo que abrió el maestro Chea:

-
http://groups.google.es/group/microsoft.public.es.access/browse_thread/thread/a243153a2d0e32fc/57d2d727771def12?hl=es&lnk=gst&q=Sobre+el+c%C3%A1lculo+de+bisiestos+y+d%C3%ADas+m%C3%B3viles#57d2d727771def12

Pero en tu caso, no necesitamos una fecha móvil como tal, ya que siempre
necesitamos el último domingo de marzo o el último domingo de octubre. Si de
ese mismo módulo tomamos la función que calcula el último día de la semana
(LastDayOfWeek), tan sólo necesitamos pasarle el último día de marzo para
calcular el domingo. Y si la embebemos dentro de otra función para no
pasarnos de mes, obtendremos el último domingo de marzo. Y como en tu caso,
necesitamos que la hora sea siempre las 2 de la mañana, se la podemos
colocar directamente:

Public Function UltimoDomingoMarzo(QueAnio As Integer) As Date
Dim dat As Date

'Primero creamos el último día de marzo
dat = DateSerial(QueAnio, 3, 31)

'Ahora calculamos el último domingo para el 31 de marzo
dat = LastDayOfWeek(dat)

'Y mientras nos hayamos pasado de mes,
'reducimos en 7 días
Do While (Month(dat) > 3)
dat = dat - 7
Loop

'Ya tenemos el último domingo de marzo.
'Pero indicamos que deben ser las 2 de la mañana:
'Agregamos 2 horas sobre las 24 que tiene 1 día
UltimoDomingoMarzo = Int(dat) + 2 / 24
End Function

Para octubre es lo mismo, pero con el mes 10, claro está ;-)

tatintin

unread,
Apr 14, 2008, 2:10:58 AM4/14/08
to
Patxi........¡Fenómeno!........
Funciona a las mil maravillas.
Hice lo siguiente:
*****************************************************************************
Public Function InicioVerano(Optional queAno As Integer) As Date
If IsMissing(queAno) Then
queAno = CInt(2099)
End If

Dim a As Date 'último dia de marzo del año especificado
Dim b As Date 'último dia de la semana de a
Dim c As Date 'ultimo domingo de marzo

a = DateSerial(queAno, 3, 31) 'ultimo dia de marzo
b = a - Weekday(a, 0) + 7 '

Do While (Month(b) > CInt(Month(a)))
b = b - 7
Loop

c = CDate(b) 'último domingo de marzo

InicioVerano = Int(c) + (2 / 24)

End Function
**************************************************************************
Public Function FinVerano(Optional queAno As Integer) As Date
If IsMissing(queAno) Then
queAno = CInt(2099)
End If


Dim d As Date 'último dia de marzo del año especificado

Dim e As Date 'último dia de la semana de a
Dim f As Date 'ultimo domingo de marzo

d = DateSerial(queAno, 10, 31) 'ultimo dia de Octubre
e = d - Weekday(d, 0) + 7

Do While (Month(e) > CInt(Month(d)))
e = e - 7
Loop

f = CDate(e) 'último domingo de marzo
FinVerano = Int(f) + (3 / 24)

End Function

Luego simplemente calculo el campo HoraLT con base en el año del campo
FechInfracc y asunto arreglado.

Muchísimas, pero que muchísimas gracias por tu ayuda.

Tatintín

Patxi Sanz

unread,
Apr 14, 2008, 1:12:59 PM4/14/08
to
De nada :-)
0 new messages