Fechas

 

 

 

Todo lo que querías saber sobre las Fechas y No te atrevías a preguntar

 

 

 

Autor: César de Miguel - Aloa Informática S.L. - cesar@aloa.info

 

 

 

Parte 1ª: Fechas

(Tempus fugit: Así pasan los días)

En esta parte sólo hablaremos de fechas. Posteriormente hablaremos de horas (junto con las fechas).

Para empezar, entendamos algo que es básico.

Si alguien no lo entiende, que se lo crea. ¡Es una orden para seguir el curso!

 

Una fecha (un día concreto) en Access es un nº entero.

Una fecha en Access No es una combinación de palabras, letras, números y separadores, ni de palabras ni de formatos.

Insisto. Un día cualquiera es un número entero, y Hoy (el día en que esto escribo es) = 37940.

Hoy, día 15 de Noviembre del Año de Gracia de 2003, sábado es, para Access, el día 37940 (y así se almacena).

Lo pongas en el formato que quieras (un montón de posibles combinaciones), internamente es el 37940.

Ayer fue el 37939 y mañana será 37941. Y dentro de mil días será el 38940.

Ahora bien, para enseñarlo o hablar de hoy no decimos el día 37940, porque sería un rollo, sino que decimos o ponemos, entre otros formatos:

 

15 de Noviembre del Año de Gracia de 2003, sábado, ó

15-11-03, ó

15/11/2003, ó

15/XI/2003, ó

11/15/2003, ó

2003/15/11, ó

15 nov 2003, ó

15/2003/11/, ó

 

Simplemente hoy ó...  (más de tropecientas combinaciones sin contar las versiones del calendario musulmán, ni judío, ni chino, ni japonés tradicional).

 

Todos hablamos del mismo hecho, día, pero lo expresamos de distinta forma.

Así que, ¿son iguales todas ellas?. En expresión, no; pero en contenido, sí.

 

Lo podemos probar diciéndole a cualquiera que esto es una fecha (y aquí le das cualquiera de las versiones) y, por muy enrevesada que esté expresada, sabrá que se refiere al día de hoy. Es decir al 37940.

 

La idea es buena y simple: almacenamos el número y lo narramos como nos convenga.

El problema viene de que ciertos 'mensajes' son equívocos.

 

Por ejemplo, la fecha 2003/12/25, seguro que, incluso para el estadounidense medio de la América más profunda, será el Christmas que del año 2003, aunque le choque un poco porque no es esa su forma acostumbrada de expresarlo.

 

Pero si le dices 7/4/2004 no tendrá dudas de que es su fiesta nacional del año 2004, su cuatro de julio, mientras que para el menda, o sea César, es el día en que tengo que preparar el semillero de calabazas, porque ya es el siete de abril. ¿Veis lo equívoco del continente o formato del mensaje?

 

Así pues, al meter fechas en la base de datos no importa cómo la introduzcas, siempre que y cuando no sea equívoca. (De aquí sale un consejo: si lo metes en forma de número entero no habrá equivocaciones, o como aconseja Frank Rivera en OSI: aaaa/mm/dd).

 

Por lo tanto las fechas no se meten en la base de datos en formato de fecha corta, larga, semilarga, fusa o semifusa: las fechas se meten en formato fecha (entendiendo por ello cualquiera que entienda el sistema) siempre que no sea confusa.

 

Para que se entienda mejor, el hecho de variar el color de la fecha y ponerla en color rojo no afecta al valor de la fecha.

 

Es lo mismo 23/11/2006 que 23/11/2006 que 23/11/2006 que 23/11/2006 que ... ¿o es que se almacena de distinta forma?

 

Pues también es lo mismo 23/11/2006 que 11/23/2006, ó que 23/2006/11, ó que 2006/23/11, ó que .........Lo que sí sucede es que se presenta en cada circunstancia en el formato que convenga: rojo, letra  bastardilla (con perdón), Times, 12 pt, aa/mmm/dddd, ...

 

Cuándo es equívoca (cuidado con la configuración regional y con la diferencia entre el ámbito español del Access -consultas, formularios, informes- y al ámbito inglés -VBA y SQL-) es cuando vienen los líos, y eso es lo que hay que evitar.

Fin de esta parte.

 

 


 

Preguntas a esta parte :

1.- ¿Se puede acceder a ese número interno de fecha?. ¿Cómo?.

Variable = clng(MiFecha)

Ej. ?clng(date()) nos devuelve 37942 
Respuesta sólo válida para el día en que hoy (devuelto por la función date())era el 37942.

 

2.- ¿Se puede, una vez conocido ese número, pasarlo al formato que queramos?. ¡Siempre!. ¿Cómo?.

Por fuera, ámbito español: NúmeroVistoComoFecha = CDate(Número;"dd/mm/aaaa"). Usado en ámbito español, es decir en tablas, consultas, formularios e informes

Por dentro, ámbito inglés: NúmeroVistoComoFecha = CDate(Número,"mm/dd/yyyy"). En ámbito inglés, es decir en SQL y VBA .

 

 

3.- ¿Existe alguna manera de crear una fecha en access que diga exactamente" 3 de febrero de 2005"; y no como me sale con la fecha larga:"jueves, 3 de febrero de 2005"?

Crear lo que se dice crear, NO si quieres que sea un campo de tipo Fecha/hora, pero si le puedes dar el formato que pides:

 

Format(Date,"dd"" de ""mmmm"" de ""yyyy"), si es en Visual Basic

ó con

dd" de  "mmmm" de  "aaaa, si es consulta, formulario, ...

 

 

4.- ¿Sucede lo mismo en otras Bases de Datos?

En Access,  en Oracle, en SQL Server y en la inmensa mayoría de las BD actuales (no conozco ninguna excepción) un campo de tipo Date, ó DateTime, ó (como se llame en cada sitio) ..., es internamente una cifra entera.

 

Cada Sistema de Gestión de Base de Datos (SGBD) lleva un calendario continuo, un día tras otro, desde el origen que han querido poner. Tan simple y claro, como que hoy es ayer + 1, y pasado mañana será mañana + 1 ú hoy + 2 ó ayer + 3, ..., y no importa que en medio se cambie de año, mes, semana, siglo ó milenio. 

 

Del formato, que si juliano, que si gregoriano, que si ISO, que si OSI, que si EuroDate, que si DateBush (o que te den igual mejor), que si FoxFate, que si ..., son formas externas de ese nº. Son máscaras, por decirlo así, de presentación del mismo hecho. 

 

Eso sí, cada SGBD ha tenido libertad para fijar su propio origen, y así como nuestro calendario occidental contemporáneo difiere en el origen del chino, del musulmán, judío, romano antiguo, el de Access también puede diferir de los otros sistemas, y teniendo en cuenta los ajustes provocados voluntariamente a cada calendario (¿Sabes, p. ej.,  que Stª Teresa murió un 4 de octubre y fue enterrada al día siguiente, 15 de octubre?. Pues, sí, le pilló una reforma de calendario.)

 


 

 

 

 

Parte 2ª: Consolidación del concepto de fechas en Access

 

 

Resumen/repaso de lo publicado (explícita o implícitamente):

En Access, una fecha (un día concreto) es un nº entero.

 

No importa el formato (tamaño, color, tipo de letra, d-m-aa, dd-mmm) en que se exprese.

 

El lío viene al introducirla en la base de datos, ya que varios de los formatos anteriores -valóralo tu mismo- no sirven para, de forma clara e inequívoca, decirle al ordenador/computadora a qué fecha nos referimos.

 

El problema más habitual es el del cambio de mes por el día y viceversa, porque 7/4/2003 no es la mismo para un americano de Los Estardos Unidos de Norteamérica, que para un hispano. (Por cierto, no sé si nuestras amigos mexicanos usan el formato mm/dd/aaaa, como estándar) Como sabéis, para uno es el 4 de julio y para el otro el 7 de abril.

 

Y este lío lo lleva Access, con no muy buen semblante, porque por fuera quiere ser hispano y por dentro americano. Y habla Espánglish ó Inglisñol a su manera. Entonces dependiendo de qué ambiente uses, Access te entenderá lo uno o lo otro y te armará líos a poco que te descuides.

 

Si trabajas en el ámbito externo, es decir, tablas, consultas, formularios, macros e informes lo entiende como siete de abril. Este ámbito se caracteriza por el hecho de que si usas inglés/americano para expresar conceptos, Access lo traduce. (Ej.: Escribes Not null, y, entonces, va Access y pone la turbadora traducción de Negado Nulo).

 

En cambio si estás en el ámbito más interno del producto, SQL y Visual Basic, allí el idioma de trabajo y el ámbito cultural es el inglés. Allí no puedes decir 35,24 euros, porque la coma no es el separador decimal (aunque hace esfuerzos a veces por traducirlo lo cual complica más las cosas) y si dices cdate("7/4/2004") te entenderá que es la fiesta nacional de E.E.U.U. de Norteamérica.

 

Y es de aquí de donde viene el embrollo, al cual yo no os voy a dar ninguna solución porque tampoco tengo una vía infalible (aunque tengo claro que si pusiéramos un sólo número entero nunca habría problemas). Pero creo que cada uno se buscará la más adecuada.

 

No obstante una cosa sabida de las manías de Access, es que si la fecha se la das en formato aaaammdd nunca confundirá el día con el mes, ni viceversa. En cuanto detecta que ese es el formato, no importa el ambiente hispano o anglo, ¡lo entiende bien!. P. ej. 20030407, es sin duda el siete de abril del año 2003.

 

 


 

Consecuencias:

Averiguar cuántos días han transcurrido entre dos fechas es, nada más fácil, restarlas:
      Clng(date()-MiFcNacimiento) -y a mí me sale la barbaridad de 20939
      (Ejercicio: ¿cuándo nació esta criatura?)

 

 

¿Qué día se cumplen los 10000 días de mi vida?: CDate(FcNacimiento + 10000)

Os paso un montón de ensayos aprovechando las posibilidades de ayuda, en depuración o en inmediato, de Access:
      ?FcNacimiento 28/05/1975 (que no es la mía)
      ?clng(FcNacimiento) 27542
      ?cdate(FcNacimiento) 28/05/1975
      ?cdate(clng(FcNacimiento)) 28/05/1975
      ?cdate(clng(FcNacimiento)+10000) 13/10/2002
      ?cdate(clng(FcNacimiento+10000)) 13/10/2002
      ?isdate(fcnacimiento) Verdadero
      ?isdate(27542) Falso
      ?#28/5/1975# 28/05/1975
      ?28/05/1975 2,835443E-03
      ?"28/05/1975" 28/05/1975
      ?isdate(28/05/1975) Falso
      ?isdate("28/05/1975") Verdadero
      ?clng(fcnacimiento)-date() 04/07/1871
      ?clng(date()-fcnacimiento) 10406
      ?clng(fcnacimiento-date()) -10406

 

 

 

Temas de la ayuda de Access.

Consejo: consultar los siguientes temas -especialmente los que están en negrita- y practicarlos

 

Obtener la fecha o la hora actuales. Date, Now, Time
Realizar cálculos de fechas. DateAdd, DateDiff, DatePart
Devolver una fecha. DateSerial, DateValue
Devolver una hora. TimeSerial, TimeValue
Establecer la fecha o la hora. Date, Time
Medir el tiempo de un proceso. Timer

Convertir entre tipos de datos. CBool, CByte, CCur, CDate, CDbl, CDec, CInt, CLng, CSng, CStr, CVar, CVErr, Fix, Int
Establecer tipos de datos intrínsecos. Boolean, Byte, Currency, Date, Double, Integer, Long, Object, Single, String, Variant (predeterminado)
Comprobar los tipos de datos. IsArray, IsDate, IsEmpty, IsError, IsMissing, IsNull, IsNumeric, IsObject

Funciones Day, Month, Year, WeekDay,

Format(expresión[, formato[, primerdíadesemana[, primerdíadeaño]]])

expresión Obligatorio. Cualquier expresión válida.
formato Opcional. Una expresión de formato definida por el usuario o con nombre válida.
primerdíadesemana Opcional. Una constante que especifica el primer día de la semana.
primerdíadeñao Opcional. Una constante que especifica la primera semana del año.

 

 


 

Ejercicios:

¿En que fecha comienza el calendario de Access?. ¿Cuál es día 1?

¿Tiene sentido una fecha negativa?

¿Cuál es la diferencia entre "25/12/2003", 25/12/2003 y #25/12/2003#

 

Para responder, probemos (en la depuración del Access 97 que es el que más a mano tenía. ¡Ojo que es ambiente americano!):

?cdate(1): 31/12/1899

?cdate(-1): 29/12/1899 Veamos que lo considera algo más que un número, si lo incluyes con intención de que sea una fecha.

 

Así por ejemplo, el día del descubrimiento de América se puede averiguar, al derecho y al revés:
      ?clng(cdate("12/10/1492")) -148732 (Observar el signo menos)
      ?clng(#10/12/1492#) -148732 . (Aquí se nota que hay que poner mm/dd/aaaa, como ya se había advertido).

 

"25/12/2003", es un texto. Efectivamente. Y lo usaremos para expresar una fecha cuando la función nos pide una cadena (string) de caracteres o para convertirlo en fecha mediante Cdate("25/12/2003").

 

25/12/2003, así al desnudo, tiene pinta de expresión aritmética con dos divisiones. Por ejemplo ?25/12/2003 nos da 0,001040107 (1,040107 E-03, en coma flotante)

 

#25/12/2003#. Es formato fecha y el sistema intenta interpretarlo como tal. Pero ¡cuidado! que depende del ambiente americano o hispano. Aquí, como no existe el mes 'veinticinco-embre', pues no existen dudas, como ha sucedido arriba, con #10/12/1492#..

 

 

 


 

 

 

 

 

Parte 3ª:  Hablemos de horas.

 

¿Y que pasa con las fracciones de día: el mediodía, la media tarde, la medianoche, el amaiketako, las cinco de la tarde, las tres y media después de almorzar, las doce y cuarto, media hora después de empezar el partido, un cuarto hora de antes de la hora de salida, tres minutos más tarde, ... ?

 

Resumen de lo publicado (explícita o implicitamente):

En Access, un día concreto es un nº entero, que se puede tratar como eso:
    un nº al que se pueden sumar o restar días para trasladarnos en el tiempo ó
    hacer semisumas para averiguar el momento equidistante entre dos fechas, ó ...  

 

Pues primera confesión: Os he mentido un poquito. Debo precisar algo más. 

En realidad un día concreto es la parte entera de un número decimal, guardado como double-doble en Access. 

 

Así que no es de extrañar que el mediodía del mencionado 15-11-2003, día que internamente es el 37940, sea 37940,5  (En americano 37940.5 -obsérvese el punto-).

 

Dicho de otra forma 37940,5 es en realidad 15-11-2003 12 h 

Y con precisión de ferrocarril (al minuto), 37940 es 15-11-2003 00:00 y 37940,5 es 15-11-2003 12:00 

 

Si se ha entendido esto, ya habéis entendido todo el rollo de las horas, los minutos y los segundos. 

 

Recordad aquellos problemas de secundaria de convertir grados sexagesimales a centesimales y viceversa y horas, o bien minutos y segundos a fracciones de día y tendréis una aproximación muy clarita a lo que aquí se cuece. Veámoslo haciendo unos ejercicios:

 

 


Ejercicios:

Si Jaimito entra al despacho de la directora a las once menos cuarto y sale veinte minutos más tarde, ¿a qué hora ha salido?

 

Pues, hagamos trabajar a la ventana de depuración (Access 97) o a la inmediato (2000 y sucesivas):

?#10:45# + #00:20#, nos da 11:05:00

 

o bien dado que veinte minutos expresados en fracción de día es 20/60/24 días
(20 minutos/60 que tiene la hora/24 horas que tiene el día):

?#10:45# + 20/60/24, pues también nos da lo mismo: 11:05:00

 

(Nota: 20/60/24 tiene formato de día. Si se me permite el chiste, podría decir que es el día 20 de sexagesimiembre de 2024  o quizá 1924?-. Esto nos hace reflexionar sobre el por qué, habitualemente para Access, 12/04/2007 no es lo mismo que #12/04/2007#. La primera expresión es una división y la segunda una fecha.)

 

 


 

Otro problema:

El padre de Jaimito trabaja en turno de noche en la fábrica de colchones ColcheX y entró a las 10 y media de la noche del 14/7/2003. El turno es de 7 horas y 33 minutos. ¿A qué hora salió?

Hago lo mismo:

 

?#14/7/2003 22:30# + #7:33#, lo que nos da como respuesta 15/07/2003 6:03:00 , totalmente correcta.

 

Hubiera sido lo mismo plantearlo como
"A la hora de entrada le sumo la fracción de día que suponen las 7h con 33m"
y nos debe dar lo mismo.Dado que dicha fracción puede representarse como

 

7m 33s = 7/24 + 33/60/24 = 0,3145833 (en americano 0.3145833), no es de extrañar que 

 

?#14/7/2003 22:30# + 0.3145833, también nos dé 15/07/2003 6:03:00   

            

ó que

 

?#14/7/2003 22:30# + 7/24 (minutos reducidos a días) + 33/60/24 (segundos reducidos a días),  

           

ó que


obtenga el mismo resultado 15/07/2003 6:03:00         

            

ó que

 

?#14/7/2003 22:30# + ((7 + 33) / 60) / 24, pues lo mismo.


 

 

Otro problema:  

El padre de Jaimito trabaja en turno de noche en la fábrica de fibra de vidrio "La Coronita" y entra todas las noches a las 10 y media. El turno es de 7 horas y 33 minutos. ¿A qué hora sale?

 

¡Esto está chupado!, nos decimos. Ponemos 

?#22:30# + #7:33#,


y nos da la sorprendente (si lo esperábamos ya no es sorpresa) respuesta de
31/12/1899 6:03:00  

En la que observo que la hora de salida es correcta, pero la fecha, ¿qué pasa con la fecha? 

 

Pues nada; que al no poner día nos considera las diez y media de la noche del día cero.

Recordemos que dicho día (el cero): 

 

?format(cdate(0),"dd/mm/yyyy, ddd") es el 30/12/1899, sáb 

 

Y como detrás del treinta viene el treinta y uno, pues no es de extrañar que el día siguiente sea el día de San Silvestre (Año Viejo) de 1899. 

 

Pues no lo hagáis caso. En realidad yo solo quería saber a qué hora salía, luego pido sólo la hora.

(No necesito el día: ya me se que es del día siguiente)  

 

¿Como?.

 

Pues con el Format correspondiente (solo horas y minutos).

?format(#22:30# + #7:33#, "hh:nn" ), obteniendo lo que cabía esperar: 06:03

 


 

Y otro:

¿Cual es el día que está entre el 30 de diciembre de 2003 y el 1 de Enero de 2004?

 

Pues la semisuma:
?format((#30/12/2003# + #1/1/2004#)/2, "d-m-yyyy") = 31-12-2003

 

Si no pongo format:  ?(#30/12/2003# + #1/1/2004#)/2 = 37986

 

Lo que es lo mismo, ya que ?format(37986, "d-m-yyyy") = 31-12-2003

 


 

Otro más , un pelín paradójico, porque pide una respuesta, digamos, rara:

 

¿Cual es el día que está entre el 30 de diciembre de 2003 y el San Silvestre de tal año o sea el 31de diciembre de 2003?

 

?format((#30/12/2003# + #31/12/2003#)/2, "d-m-yyyy") = 30-12-2003

 

¿Se ha confundido? No. Porque ha buscado el punto medio del día 30 (cuando empieza) y el del 31 (en su comienzo). ¿Dónde está dicho punto?. Pues en el mediodía del 30.

Veámoslo de otras formas:

 

 (#30/12/2003#  +  #31/12/2003#) / 2 = 37985,5 (día 30 y medio, podíamos decir).

 

Más claro:

?format((#30/12/2003#  +  #31/12/2003#)/2, "d-m-yyyy h:n") = 30-12-2003 12:0, ó

?format((#30/12/2003#  +  #31/12/2003#)/2, "d-m-yyyy h:nn") = 30-12-2003 12:00, ó

?format((#30/12/2003#  +  #31/12/2003#)/2, "d-m-yyyy h:nn:ss") = 30-12-2003 12:00:00,

 

donde segundos y minutos no son significativos, porque no existen, pero si dan idea de una mayor precisión.

 


 

Otro:

Quisiera sumar un minuto a la hora actual.

Respuesta:

          Now() + (1/1440).

Ó        Now() + (1 / 60 / 24)

 

En ambos casos la expresión entre paréntesis convierte el minuto en una fracción de día. Pues el día es la unidad en que se trabaja en esto de las fechas/horas


 

Más:

Dada una hora en un campo tipo date, llamado LaHora, ¿cómo redondear al cuarto de hora siguiente?

 

Respuesta:

cdate(clng ((LaHora * 24 + 0.2499) * 4) / 4 / 24)

 

(El truco está en trasladar el momento a –casi- un cuarto de hora más tarde y despreciar la fracción que sobre del cuarto de hora).


 

Y otro:

Dada una hora en LaHora, un campo tipo date, ¿cómo redondear al cuarto de hora más cercano?

Respuesta:

 

cdate(clng ((LaHora * 24 + 0.1249) * 4) / 4 / 24)

 

(En la misma línea que el anterior pero ahora traslado a la mitad del cuarto de hora más tarde)


 

Convertir una hora en una fracción de día, es un problema que admite varios enfoques en función de los datos que tengas y cómo los tengas.

 

Casos habituales.

Tienes separados o puedes separarlos los componentes del tiempo: horas, minutos y, quizá, segundos

 

Su fracción es:


 (horas / 24 + minutos / (24 * 60) + segundos) / (24 * 60 * 60)

 

ó su equivalente


 ((horas * 60 + minutos) * 60 + segundos)  / (24 * 60 * 60)


En el caso de la 8 y media, 8:30, 8,5 (que todos son lo mismo):


                 8 / 24  +  30 /(24 * 60)  =  0.354166

 

La hora, los minutos y los segundo forman parte de un campo de tipo fecha ó date:
Sabes que Access expresa un momento en el tiempo, como un número con parte entera y parte decimal:


                        día , fracción_del_día



 

¿Como verlo de esta forma?.


Tomemos el momento actual ó ahora: now(), que mi caso me da: now() =22/07/2004 8:04:11
(Si fuera un campo llamado momento, sería sustituir now() por momento)
Pues, para ver sus partes, puede ser así:


        cdbl(now()), lo que me da en este momento:  38190,3374537037 (Hoy es el día 38190. Ahora es la fracción 0,3374537037 de hoy)


Con lo que queda claro que la fracción del día en la que estamos es su parte decimal: 0,3374537037


Si la quiero tener separadita, pues le quito la parte entera.


¿Cómo?. Pues

 

Si quiero verlo en forma de h:m:s:


    cdbl(now()) - int(now()) = 8:04:11

 

Y si lo quiero ver en decimal


    cdbl(cdbl(now()) - int(now())) =  0,3374537037

 

 

 

Anexos:

De Leonardo Henrnández Ferreiro

 

Función para calcular el Domingo de Pascua:

Function DomingoPascua(Año As Integer) As Date   

    ' Esta función ha sido desarrollada por Leonardo Henrnández Ferreiro lhf@coiim.es

    ' Particularmente para los usuarios de la lista soloaccess. Puede utilizarse libremente

    ' cuantas veces se desee manteneniendo el origen de la misma    

    Dim R1 As Integer, R2 As Integer, R3 As Integer, TFECHA As Date

    R1 = (19 * (Año - Int(Año / 19) * 19) + 24) - Int((19 * (Año - Int(Año / 19) * 19) + 24) / 30) * 30

    R2 = (2 * (Año - Int(Año / 4) * 4) + 4 * (Año - Int(Año / 7) * 7) + 6 * R1 + 5) _

      - Int((2 * (Año - Int(Año / 4) * 4) + 4 * (Año - Int(Año / 7) * 7) + 6 * R1 + 5) / 7) * 7

    R3 = R1 + R2

    If R3 >= 10 Then TFECHA = (R3 - 9) & "/04/" & Año Else TFECHA = (R3 + 22) & "/03/" & Año

    DomingoPascua = TFECHA

End Function

 

'Sabiendo el Domingo de Pascua, ya podemos saber más datos, en forma de diferencia de días:

'Miércoles de Ceniza (Inicio cuaresma) 46 días antes del domingo de Pascua

'Domingo de Ramos 7 días antes del domingo de Pascua

'Domingo de Ascensión (antes jueves)  42 días después del domingo de Pascua.

'Domingo de Pascua de Pentecostés 49 días después del domingo de Pascua

'Domingo de Corpus Christi (antes jueves) 63 días después del domingo de Pascua

 

De Francisco Rivera:

 

' Trabajando con días laborables en VBA

' Author: Ken Getz

' Traducción y Adap: Francisco Rivera (fzombie)

 

VBA y Access no proveen ningún soporte para trabajar con los típocos días laborables el "VBA Developers Handbook" contiene varias funciones que proveen información sobre los días siguientes y los previos, y para encontrar el primero y el último día laborable en un mes. Para trabajar con vacaciones, la función original  SkipHolidays acepta una referencia a un recordset que contenga todas las fechas que quieres brincarte. Para incrementar la flexibilidad y facilidad de uso, las funciones originales han sido re-escritas para aceptar una array de vacaciones, como la función en Excel.

 

 

' ********* Inicio del Código **************

‘------------------------------------------------------------------------------------------------------------

Public Function AñadeDiasLab(lngDias As Long, Optional FechaIn As Date = 0, Optional ArrVacaciones As Variant) As Date

    ' Añade el número especificado de día laborables a la fecha indicada

    ' Entrada:

    '   lngDias: Número de días laborables que añadiremos a la fecha inicial

    '   FechaIn: Fecha en la cual comenzamos a buscar. Se usa la fecha actual no se especifica una

    '   ArrVacaciones (Opcional): Array que contiene las fechas de vacaciones. Puedes ser un solo valor

 

    ' Salida:

    '   Valor de Retorno : La fecha de los días trabajados tomando en cuenta fines de semana y vacaciones

    ' Ejemplo:

    '   AñadeDiasLab(10, #2/9/2000#, Array(#2/16/2000#, #2/17/2000#))

    '   nos regresa #2/25/2000#, el cual es la fecha más 10 días laborables

   

    Dim lngConteo As Long

    Dim dtmTemp As Date

   

    If FechaIn = 0 Then FechaIn = Date

   

    dtmTemp = FechaIn

    For lngConteo = 1 To lngDias

        dtmTemp = SigDiaLab(dtmTemp, ArrVacaciones)

    Next lngConteo

    AñadeDiasLab = dtmTemp

End Function

 

‘------------------------------------------------------------------------------------------------------------

Public Function SigDiaLab(Optional FechaIn As Date = 0,Optional ArrVacaciones As Variant = Empty) As Date

   

    ' Obtiene el siguiente día laborable después de la fecha especificada.

    ' Requiere:

    ‘   SaltarVacaciones

    '   EsFindeSemana

   

    ' Entrada:

    '   FechaIn: Fecha en la cual comenzamos a buscar. Se usa la fecha actual no se especifica una.

    '   ArrVacaciones (Opcional): Array que contiene las fechas de vacaciones. Puedes ser un solo valor

 

    ' Salida:

    '   Valor de Retorno: La fecha del siguiente día laborable tomando en cuenta fines de semana y vacaciones

    ' Ejemplo:

    '   FechaIn = SigDiaLab(#5/23/1997#, #5/26/97#)

 

    If FechaIn = 0 Then FechaIn = Date

   

    SigDiaLab = SaltarVacaciones(ArrVacaciones, FechaIn + 1, 1)

End Function

 

‘------------------------------------------------------------------------------------------------------------

Public Function AntDiaLab(Optional FechaIn As Date = 0,Optional ArrVacaciones As Variant = Empty) As Date

   

    ' Obtiene el anterior día laboral antes dela fecha especificada.

    ' Requiere:

    ‘   SaltarVacaciones

    '   EsFindeSemana

   

    ' Entrada:

    '   FechaIn: Fecha en la cual comenzamos a buscar. Se usa la fecha actual no se especifica una.

    '   ArrVacaciones (Optional): Array que contiene las fechas de vacaciones. Puedes ser un solo valor

    ' Salida:

    ‘   Valor de Retorno: La fecha del anterior día laborable tomando en cuenta vacaciones y fines de semana

    ' Ejemplo:

    '   FechaIn = AntDiaLab(#1/1/2000#, Array(#12/31/1999#, #1/1/2000#))

  

    If FechaIn = 0 Then FechaIn = Date

   

    AntDiaLab = SaltarVacaciones(ArrVacaciones, FechaIn - 1, -1)

End Function

 

‘------------------------------------------------------------------------------------------------------------

Public Function PrimerDiaLabMes(Optional FechaIn As Date = 0, Optional ArrVacaciones As Variant = Empty) As Date

   

    ' Obtiene el primero día laborable del mes especificado

    ' Requiere:

    ‘   SaltarVacaciones

    '   EsFindeSemana

   

    ' Entrada:

    '   FechaIn: Fecha del mes que nos interesa. Usa la actual si no especificamos una

    '   ArrVacaciones (Opcional): Array que contiene las fechas de vacaciones. Puedes ser un solo valor

    ' Salida:

    ‘   Valor de Retorno: La fecha del primer día laborable en el mes, tomando en cuenta vacaciones y fines de semana

    ' Ejamplo:

    '   FechaIn = PrimerDiaLabMes(#1/1/1999#, #1/1/1999#)

   

    Dim dtmTemp As Date

    If FechaIn = 0 Then FechaIn = Date

   

    dtmTemp = DateSerial(Year(FechaIn), Month(FechaIn), 1)

    PrimerDiaLabMes = SaltarVacaciones(ArrVacaciones, dtmTemp, 1)

End Function

 

‘------------------------------------------------------------------------------------------------------------

Public Function UltimoDiaLabMes( Optional FechaIn As Date = 0, Optional ArrVacaciones As Variant = Empty) As Date

   

    ' Obtiene el último día laboral en el mes especificado.

    ' Requiere:

    ‘   SaltarVacaciones

    '   EsFindeSemana

   

    ' Entrada:

    '   FechaIn: Fecha del mes que nos interesa

    '   ArrVacaciones (Opcional): Array que contiene las fechas de vacaciones. Puedes ser un solo valor

    ' Salida:

    ‘   Valor de Retorno: La fecha del ultimo día laborable en el mes, tomando en cuenta vacaciones y fines de semana

    ' Ejamplo:

    '   FechaIn = UltimoDiaLabMes(#12/1/1999#, #12/31/1999#)

   

    Dim dtmTemp As Date

    If FechaIn = 0 Then FechaIn = Date

   

    dtmTemp = DateSerial(Year(FechaIn), Month(FechaIn) + 1, 0)

    UltimoDiaLabMes = SaltarVacaciones(ArrVacaciones, dtmTemp, -1)

End Function

 

‘------------------------------------------------------------------------------------------------------------

Public Function ContarDiasLab(ByVal dtmInicio As Date, ByVal dtmFin As Date, Optional ArrVacaciones As Variant = Empty) As Integer

    ' Cuenta los días laborables (sin fines de semana ni vacaciones en una rango de fechas )  

    ' Requiere:

    ‘   SaltarVacaciones

    '   CountHolidays

    '   EsFindeSemana

   

    ' Entrada:

    '   dtmInicio: Fecha que especifica el inicio del rango

    '   dtmFin: Fecha que especifica el fin del rango

    '   ArrVacaciones (Opcional): Array que contiene las fechas de vacaciones. Puedes ser un solo valor

    ' Salida:

    ‘   Valor de Retorno: Número de días laborables, sin contar fines de semana y opcionalmente vacaciones

    ' Ejamplo:

    '   ContarDiasLab(#7/2/2000#, #7/5/2000#, )

   

    Dim intDias As Integer, dtmTemp As Date, intExtrae As Integer

   

    If dtmFin < dtmInicio Then

        dtmTemp = dtmInicio

        dtmInicio = dtmFin

        dtmFin = dtmTemp

    End If

   

    dtmInicio = SaltarVacaciones(ArrVacaciones, dtmInicio, 1)

    dtmFin = SaltarVacaciones(ArrVacaciones, dtmFin, -1)

    If dtmInicio > dtmFin Then

            ContarDiasLab = 0

    Else

        intDias = dtmFin - dtmInicio + 1

       

        intExtrae = (DateDiff("ww", dtmInicio, dtmFin) * 2)

        

        intExtrae = intExtrae + _

         ContarVacacionesA(ArrVacaciones, dtmInicio, dtmFin)

       

        ContarDiasLab = intDias - intExtrae

    End If

End Function

 

‘------------------------------------------------------------------------------------------------------------

Private Function ContarVacacionesA(ArrVacaciones As Variant,dtmInicio As Date, dtmFin As Date) As Long

    ' Contamos las vacaciones entre dos fechas finales.

    ' Requerida por:

    '   ContarDiasLaborables

    ' Requiere:

    '   EsFindeSemana

   

    Dim lngItem As Long

    Dim lngConteo As Long

    Dim blnEncontrado As Long

    Dim dtmTemp As Date

   

    On Error GoTo ManejoError

    lngConteo = 0

    Select Case VarType(ArrVacaciones)

        Case vbArray + vbDate, vbArray + vbVariant

            For lngItem = LBound(ArrVacaciones) To UBound(ArrVacaciones)

                dtmTemp = ArrVacaciones(lngItem)

                If dtmTemp >= dtmInicio And dtmTemp <= dtmFin Then

                    If Not EsFindeSemana(dtmTemp) Then

                        lngConteo = lngConteo + 1

                    End If

                End If

            Next lngItem

        Case vbDate

            If ArrVacaciones >= dtmInicio And ArrVacaciones <= dtmFin Then

                If Not EsFindeSemana(ArrVacaciones) Then

                    lngConteo = 1

                End If

            End If

    End Select

ExitHere:

    ContarVacacionesA = lngConteo

    Exit Function

   

ManejoError:

    Resume ExitHere

End Function

Private Function FindItemInArray(varItemToFind As Variant, _

avarItemsToSearch As Variant) As Boolean

    Dim lngItem As Long

   

    On Error GoTo ManejoError

   

    For lngItem = LBound(avarItemsToSearch) To UBound(avarItemsToSearch)

        If avarItemsToSearch(lngItem) = varItemToFind Then

            FindItemInArray = True

            GoTo ExitHere

        End If

    Next lngItem

   

ExitHere:

    Exit Function

   

ManejoError:

    Resume ExitHere

End Function

 

‘------------------------------------------------------------------------------------------------------------

Private Function EsFindeSemana(dtmTemp As Variant) As Boolean

    ' Si tus fines de semana no son Sábado (día7) ó Domingo (Día 1) cambiamos la rutina para devolver

    ' True para cualquier días que uses como tus fines de semana

    ' Requerida por:

    ‘   SaltarVacaciones

    '   PrimerDiaLabMes

    '   UltimoDiaLabMes

    '   SigDiaLab

    '   AntDiaLab

    '   ContarDiasLab

   

    If VarType(dtmTemp) = vbDate Then

        Select Case DiadeSemana(dtmTemp)

            Case vbSaturday, vbSunday

                EsFindeSemana = True

            Case Else

                EsFindeSemana = False

        End Select

    End If

End Function

 

‘------------------------------------------------------------------------------------------------------------

Private Function SaltarVacaciones( ArrVacaciones As Variant, dtmTemp As Date, intIncrement As Integer) As Date

    ' Nos saltamos los fines de semana y vacaciones en un arreglo referido como  by ArrVacaciones.

   

    ' Requerida por:

    '   PrimerDiaLabMes

    '   UltDiaLabMes

    '   SigDiaLab

    '   AntDiaLab

    '   ContarDiasLab

   

    ' Requiere:

    '   EsFindeSemana

   

    Dim strCriterio As String

    Dim strNomCampo As String

    Dim lngItem As Long

    Dim blnEncontrado As Boolean

   

    On Error GoTo ManejoError

   

    Do

        Do While EsFindeSemana(dtmTemp)

            dtmTemp = dtmTemp + intIncrement

        Loop

        Select Case VarType(ArrVacaciones)

            Case vbArray + vbDate, vbArray + vbVariant

                Do

                    blnEncontrado = FindItemInArray(dtmTemp, ArrVacaciones)

                    If blnEncontrado Then

                        dtmTemp = dtmTemp + intIncrement

                    End If

                Loop Until Not blnEncontrado

            Case vbDate

                If dtmTemp = ArrVacaciones Then

                    dtmTemp = dtmTemp + intIncrement

                End If

        End Select

    Loop Until Not EsFindeSemana(dtmTemp)

   

ExitHere:

    SaltarVacaciones = dtmTemp

    Exit Function

   

ManejoError:

    Resume ExitHere

End Function

 

' ********* Fin del Código **************

 

 

 

' Tiempo, añadir y quitar, y hojas de tiempo.

' Author: Robin Stoddart-Stones

' Traducción y Adap: Francisco Rivera (fzombie)

 

Ha habido un reciente debate sobre como "Añadir tiempo", "Convertir horas en minutos", y "Trabajar sobre las 24 horas", y existen métodos interesantes Access 97/2000 tienes el campo Fecha/Hora que tiene algunas propiedades interesantes.

 

Preparando el campo Fecha/Hora

Si especificamos el campo Fecha como Fecha/Hora, toma la fecha y hora actual del sistema. Esto nos da un simple formato de fecha pata aplicaciones de tiempo.

 

Vamos a usar la ventana Inmediato para probar esto (suponiendo que saben manejar la ventana Inmediato)

 

Usar un botón para almacenar la Fecha y Hora en un campo Fecha (o una variable de Fecha)

Esto sería:

 

Dim lsdt as Date (en el módulo) y en la ventana Inmediato (ó ventana de depuración)

lsdt=Date + Time

? lsdt= "17/02/99 17:10:49" (correcto al momento de escribir)

 

Un campo fecha puede ser extraido de otro y el resultado sería la fracción del día

 

Esto sería:

lsdt=#16:00#-#15:45#

?lsdt

1.04166666666666E-02

 

? (24*60)*1.04166666666666E-02

14.9999999999999 (aproximadamente 15 minutos para n/1000ths de un segundo)

 

En otras palabras, extraer un tiempo de otro para obtener una respuesta aritmética. Añadimos varias de esas fracciones juntas y obtenemos el tiempo total.

 

?1.04166666666666E-02 +1.04166666666666E-02

2.08333333333332E-02

?(24*60)*2.08333333333332E-02

29.9999999999998 (Lo suficientemente cerca a 30 minutos)

 

Si el resultado está debajo de las  24 horas podemos mostrar el total de manera muy simple sin usas matemáticas, usando format (x, "Short Timer")

Esto sería:

 

?format(2.08333333333332E-02,"short time")

00:30

Lo cual es muy útil.

Por ejemplo si tus cobros son 11.50 por hora entonces tu promedio diario es = 24*11.50 y el cargo para 30 minutos de trabajo sería:

 

?24*11.50 * 2.08333333333332E-02

5.74999999999996

 

Así, en un campo fecha tienes almacenados el numero de las horas trabajadas, y una opción de formato nos dice a los usuarios de ese tiempo en un cálculo simple y podemos obtener el costo aun debajo de 24 horas totales de trabajo

 

Pero que pasa si hemos trabajado más de 24 horas ?? Simple, si añadimos incrementos pequeños. Veamos una demostración  de 47 medias horas a 49 medias horas

 

?47*2.08333333333332E-02

0.97916666666666

?24* 0.97916666666666

23.4999999999998 (47 medias horas son 23.5 horas)

 

?48*2.08333333333332E-02

0.999999999999994

?24*0.999999999999994

23.9999999999999 (24 horas)

 

?49*2.08333333333332E-02

1.02083333333333

?24*1.02083333333333

24.4999999999999 (24.5 Horas)

 

Ahora, si calculamos la duración podemos añadir esta duración de 24.5 horas a una fecha y encontrar la fecha final

 

lsdt=#01-dic-99#

?lsdt

01/12/99

lsdt=lsdt+1.02083333333333

?lsdt

02/12/99 00:30:00

 

En otras palabras, la medianoche entre el 30/Nov/99 y el 1/Dic/99 + 24.5 horas es pasada la medianoche del 2 de Diciembre. El único problema es que aqui no tenemos un formato rápido para decir que número de días y horas tenemos si hemos ido más allá de las 24.

 

?format(1.02083333333333,"short Time")

00:30

 

Pero no nos tomará mucho probar si el valor el mayor que uno ó calcular la fracción de las 24 horas que restan

 

lsdt=1.020833333333

dias=Int(lsdt)

?dias

1

 

Horas=24*(lsdt-dias)

?horas

0.499999999991999

 

minutos=(horas-int(horas))*60

?minutos

29.99999999952

 

Y si trabajamos sobre la medianoche, entonces:

 

?#02-dic-99 00:30# - #01-dic-99 00:00#

1.02083333333576

 

Lo cual está lo suficientemente cerca para mi en este momento (La diferencia es la precisión de la máquina cuando multiplica 49 veces)(y 49 medias horas se convierte en 1.0208333333)

 

Haciendo el proceso al revés:

Si estás trabajanod hojas de tiempo en dónde se escriben las horas y los minutos en lugar de Tiempos, entonces:

 

minutos =mins/(24*60)

 

Horas=hrs/24

 

Tiempo=horas + minutos

 

?#07:30#-#00:00#

0.3125

minutos=30/(24*60)

horas=7/24

?horas+minutos

0.3125

 

 

Yo suelo tener definidas unas constates públicas que me lo tienen preparado. 

 

Const hora As Single = 1 / 24

Const minuto As Single = 1 / 24 / 60

Const segundo As Single = 1 / 24 / 60 / 60

 

Así que cuando quiero restar n minutos de un campo Fecha/hora llamado, p.ej. instante, 

resultado = instante -  n * minuto

 

 

' Cuantos domingos hay entre dos fechas

' Author: Michel Walsh

' Traducción y Adap: Francisco Rivera (fzombie)

 

Por una observación inicial hecha por Lyle Fairfield, aqui hay una solución para obtener el número de, digamos, miércoles entre dos fechas indicadas: 

 

Public Function CuantosD(FechaIni As Date,FechaFin As Date,WD As Long)

   ' Puedes usar el manejo de errores como quieras.

    CuantosD = DateDiff("ww", FechaIni, FechaFin, WD)- Int(WD = WeekDay(FechaIni))

End Function

 

De la misma forma, alguien puede fácilmente obtener el número de días de la semana (excluyendo fines de semana) simplemente quitando el número de sábados y domingos:

 

Public Function CuantosDSem(FechaIni As Date,FechaFin As Date,Optional FechaFinesIncluida As Boolean = True)

    CuantosDSem = DateDiff("d", FechaIni, FechaFin) - FechaFinesIncluida - CuantosD(FechaIni, FechaFin, vbSunday) - CuantosD(FechaIni, FechaFin, vbSaturday)

End Function

 

 

 

FUNCION DIAS LABORABLES

Function Dias_Lab (FechaIni As Variant, FechaFin As Variant) As Integer

'Esta función no trabaja con vacaciones

Dim Semanas As Variant

Dim DateCnt As Variant

Dim DiasFin As Integer

FechaIni = DateValue(FechaIni)

FechaFin = DateValue(FechaFin)

      Semanas = DateDiff("w", FechaIni, FechaFin)

      DateCnt = DateAdd("ww", Semanas, FechaIni)

      DiasFin = 0

      Do While DateCnt < FechaFin

        If Format(DateCnt, "ddd") <> "Sun" And _

                          Format(DateCnt, "ddd") <> "Sat" Then

            DiasFin = DiasFin + 1

         End If

         DateCnt = DateAdd("d", 1, DateCnt)

      Loop

      Dias_Lab = Semanas * 5 + DiasFin

End Function

 

 

' Como manejar la medianoche en los cálculos de tiempo

' Author: Robin Stoddard-Stones

' Traducción: Francisco Rivera (fzombie)

 

Si quieres incluir a la medianoche en tus cálculos de tiepo, una manera sencilla

es incluir el operador de medianoche (1)

 

    Sería: #23.45# -1 = 00:15:00

 

Si necesitas ir más allá de la medianoche entonces necesitas incluir el operador

(y formatear el resultador para poder entenderlo)

 

        #23:45# - 1-#00.15# = -2.08333333333333E-02

 

    pero

 

        format(#23:45#-1-#00:15#,"short time") = 00:30

 

    y

 

        format(-2.08333333333333E-02, "short time")= 00:30"

 

 

 

 

FUNCIONES VARIAS PARA EL MANEJO DE FECHAS

 

'*************************** Inicio de Código *******************************

'Este código fué originalmente escrito por Lewis Moseley.

'Eres libre de usarlo en tus aplicaciones, 'siempre y cuando se quede este copyright.

 

' Adaptado por Francisco Rivera (fzombie)

'Código cortesía de Lewis Moseley

'

Function PrimeroMes(LaFecha As Date)

'  Obtiene la fecha que es el primer dia del mes de la fecha indicada

Dim D As Integer, M As Integer, Y As Integer

    If IsNull(LaFecha) Then

        PrimeroMes = Null

    Else

        D = Day(LaFecha)

        M = Month(LaFecha)

        Y = Year(LaFecha)

        PrimeroMes = DateSerial(Y, M, 1)

    End If

End Function

 

 

 

Function UltimoMes(LaFecha As Date)

'  Obtiene la fecha que es el último día del mes, de la fecha indicada

Dim D As Integer, M As Integer, Y As Integer

   

    If IsNull(LaFecha) Then

        UltimoMes = Null

    Else

        D = Day(LaFecha)

        M = Month(LaFecha)

        Y = Year(LaFecha)

        ' Encontramos el primer día del siguiente mes y regresamos un día

        UltimoMes = DateAdd("m", 1, DateSerial(Y, M, 1)) - 1

    End If

End Function

 

 

 

Function MesSig(LaFecha As Date)

' Obtiene una fecha con un mes más adelantado a partir de la fecha indicada

    MesSig = DateAdd("m", 1, LaFecha)

End Function

 

 

 

Function MesPas(LaFecha As Date)

' Obtiene una fecha con un mes de retraso a partir de la fecha indicada

   MesPas = DateAdd("m", -1, LaFecha)

End Function

 

 

 

Function DiadelMes(LaFecha As Date, DiaEsp As Integer)

' Obtiene la fecha que es el día especificado del mes y año indicado

Dim M As Integer, Y As Integer

    If IsNull(LaFecha) Then

        DiadelMes = Null

    Else

        M = Month(LaFecha)

        Y = Year(LaFecha)

        DiadelMes = DateSerial(Y, M, DiaEsp)

    End If

End Function

'*************************** Fin Código *******************************

 

 

 

‘ Obtener una fecha en el futuro con una fecha determinana

‘ Author: Dev Ashish

‘ Traducción y Adap: Francisco Rivera (fzombie)

 

(P) ¿ Como  puedo tomar una fecha y obtener la misma fecha con una año de adelanto ?

    tmpFecha = #1/Ene/97#

    NuevaFecha= DateSerial(year(tmpFecha)+1, month(tmpFecha), day(tmpFecha))

 

Deberíamos obtener un valor de  1/Ene/98para la variable NuevaFecha.

También podemos usar la función function forde esta manera:

 

        NuevaFecha = DateAdd( 1, "yyyy", tmpFecha)

 

 

 

 

‘Calcular la edad de una persona

‘Author: Dev Ashish, Michel Walsh & Tim Walters

‘ Traducción y Adap: Francisco Rivera (fzombie)

 

(P) Como puedo calcular la edad de una persona conociendo su fecha de nacimiento?

 

Asumimos que el campo de la fecha de nacimiento se llama [FechaNac] y es del tipo Fecha, podemos usar el siguiente cálculo:

 

   Edad=DateDiff("yyyy", [FechaNac], Now())+Int( Format(now(), "mmdd") < Format( [FechaNac], "mmdd") )

 

Alternativa: Puedes usar esta función para calcular la edad

 

Function Edad(FechaIni, FechaHoy) As Integer

    If Month(FechaHoy) < Month(FechaIni) Or (Month(FechaHoy) = Month(FechaIni) And Day(FechaHoy) < Day(FechaIni)) Then

            Edad = Year(FechaHoy) - Year(FechaIni) - 1

    Else

            Edad = Year(FechaHoy) - Year(FechaIni)

    End If

End Function

 

 

Esta es otra función para edad, más detallada

 

Public Sub CalcEdad(vFecha1 As Date, vFecha2 As Date, ByRef vYears As Integer, ByRef vMeses As Integer, ByRef vDias As Integer)

' Calcula la edad en Años, Meses y Días

vMeses = DateDiff("m", vFecha1, vFecha2)

vDias = DateDiff("d", DateAdd("m", vMeses, vFecha1), vFecha2)

If vDias < 0 Then

vMeses = vMeses - 1

vDias = DateDiff("d", DateAdd("m", vMeses, vFecha1), vFecha2)

End If

vYears = vMeses \ 12

vMeses = vMeses Mod 12

End Sub

 

 


P.- ¿Qué formato aplicar al 1/1/2004 para que salga como “1 de Enero de 2004”?

R.- Prueba con el siguiente formato: d" de "mmmm" de "aaaa 


 

 

P. Necesito saber cómo generar el día juliano mediante una fecha, ya sea con una consulta o en un campo calculado en un formulario.

R. No sé qué entiendes por día juliano.

 

En mis tiempos de Cobol (¡qué tiempos aquellos!) significaba el nº de día consecutivo a partir del 1 de enero de ese año.

 

Si es así, la cosa es una simple resta de fechas.

 

DíaJuliano = Fecha - cdate("1/1/" & year(Fecha)) + 1, donde Fecha es aquella para la que quieres el día juliano.

 

Nosotros llamábamos Fecha Juliana, en contraposición a la Fecha Gregoriana, a la que se de daba en formato

aajjj ó aaaajjj,

 

donde a es el año en dos o cuatro cifras y jjj el día juliano anteriormente definido.

 

FechaJuliana = format(Fecha, "yy") &  format(DíaJuliano,"000") ó  format(Fecha, "yyyy") & format(DíaJuliano,"000") , si es en ámbito interno ó

FechaJuliana = format(Fecha;"aa") &  format(DíaJuliano;"000") ó  format(Fecha; "aaaa") & format(DíaJuliano;"000") , si lo es en el externo


 

P.       Quiero pasar un numérico a un tipo fecha/hora. Por

ejemplo pasar 120 minutos a un formato hora, es decir, 2:00 horas para luego almacenar esas 2:00 horas en campo fecha/hora.

R. Access almacena un determinado momento del tiempo como un nº, el cual

en su parte entera nos habla del día
(es un nº consecutivo desde el 1, referido al día (cdate(1)=) 31/12/1899, en que comienza el calendario de Access), y

en su parte decimal de la fracción del día que corresponda.

 

Así, por ejemplo, el instante señalado como

 

el segundo nº 14 del minuto 30 de las 3 de la tarde del 17 de Mayo del año de gracia de 2002, es para Access el nº

 

37393,6459953704

 

El que lo veamos como 17/5/2002 15:30:14 es puro maquillaje. Eso lo hace el formato que se aplica.

 

Si pides, port ejemplo,

 

cdate(37393.6459953704) (entre otras formas), tienes la respuesta en tu formato regional para fechas y horas. Yo obtengo: 17/05/2002 15:30:14

 

Así pues, para transformar cualquier concepto de tiempo al formato Fecha/Hora debes convertirlo en días.

 

Si tu número entero habla de minutos, tendrás que dividirlo entre (24 X 60 =) 1440 minutos que tiene el día y así lo tendrás con el valor justo.


Ej. tiempo = minutos / 1440

(donde tiempo es un campo Fecha/hora y minutos es el campo numérico que comentabas)

segundos, habría que dividirlo entre 86400 (24 X 60 X 60)

 

milisegundos, entre 8640000 que es el resultado de 24 X 60 X 60 X 1000 horas, 24 semanas, habría que multiplicarlo por 7 y así sucesivamente.


 

 

 

P- Averiguar el nº de días de la semana escogido que hay entre dos fechas dadas.

 

Function Pasados(Inicio As Date, Fin As Date, DíaSemana As Byte) As Integer
''Calcula el número de días de la semana prefijados (lunes, martes, ...)
'' pasados entre dos fechas puras, inclusive ambas
''Es decir, de un lunes al siguiente lunes, devolvería 2
''DíaSemana: 1 si es Domingo, 2 si Lunes, ... (El estándar de que el Domingo sea 1, puede cambiarse en el programa)


Dim Semanas As Integer, Quedan As Byte, OtroMás As Byte, ElInicioEs As Integer, ElÚltimoEs As Byte
If Int(Fin) < Int(Inicio) Then MsgBox "Las fechas deben estar en orden. Sin embargo " & Inicio & " es posterior a " & Fin: Exit Function
If DíaSemana < 1 Or DíaSemana > 7 Then MsgBox "El d��������������a de la semana ha de estar entre 1 y 7": Exit Function


Semanas = Int((Fin - Inicio) / 7): Quedan = (Int(Fin) - Int(Inicio)) - (7 * Semanas)
ElInicioEs = Weekday(Inicio): ElÚltimoEs = Weekday(DateAdd("D", Quedan, Inicio))
If ElÚltimoEs < ElInicioEs Then
   OtroMás = Abs(DíaSemana >= ElInicioEs) + Abs(DíaSemana <= ElÚltimoEs)
Else
   OtroMás = Abs(DíaSemana >= ElInicioEs And DíaSemana <= ElÚltimoEs)
End If
Pasados = Semanas + OtroMás
End Function


 

 

 

Calcular en minutos el retraso de entrada de una persona

 

Como no tengo tu modelo de datos, cosa que cuando se pide ayuda es muy interesante incluir, vamos a ver como calcularía el retraso en minutos de un señor que teniendo que entrar a las 7:55 entra a la hora que indica su ficha de Marcaje.

 

Llamo MarcaEntrada al now() del marcaje de la ficha en un día determinado.

Supongo, pues, que este marcaje incluye el día y la hora.

 

No me voy a fijar en el día (supongo por muy retrasado que entre los hará en el mismo día. Si fuera turno de noche que empieza a las 23:55 y el empleado entra a las 00:17, estaríamos en otro caso).

 

HoraDeEntrar = 7/24 + 55/24/60                        '<<No hacemos caso del día

HoraDeEntrada = MarcaEntrada - int(MarcaEntrada)                 '<<No hacemos caso del día, y nos quedamos con su fracción

 

if HoraDeEntrar < HoraDeEntrada then

          RetrasoEnFracciónDeDía = (HoraDeEntrada -HoraDeEntrar)         'días

          RetrasoEnFracciónDeHora = (HoraDeEntrada -HoraDeEntrar) * 24          'horas

          RetrasoEnFracciónDeMinuto = (HoraDeEntrada -HoraDeEntrar) * 24 * 60         'minutos

          RetrasoEnFracciónDeSegundoo = (HoraDeEntrada -HoraDeEntrar) * 24 * 60 * 60        'segundos

Else

          'No hay retraso

End if

 

Si acumulas el tiempo retrasado tendrás el retraso total (en la unidad de tiempo que hayas escogido).   Si no ha sido en minutos, lo puedes transformar de forma fácil, según hemos hecho.

FIN !!

 

[Atrás]