Ir al contenido


Foto

Calcular diferencia entre horas


  • Por favor identifícate para responder
13 respuestas en este tema

#1 JRichard

JRichard

    Advanced Member

  • Miembros
  • PipPipPip
  • 67 mensajes

Escrito 24 enero 2014 - 02:05

Saludos, tengo un problemita que espero puedan ayudarme a solucionar.

Actualmente me encuentro desarrollando una aplicación donde necesito calcular la diferencia entre dos horas, por ejemplo:

hora1 = 5:00 AM
hora2 = 3:00 AM

Sacando la diferencia entre hora1 y hora2 la diferencia sería de 2 horas.

Bueno esto es básicamente lo que necesito, el detalle esta en que en mi país (Venezuela) comúnmente se trabaja con horas en formato de 01:00 a 12:00 indicando si es AM o PM.

Ahora, para obtener la hora1, en un combo llamado Hora Inicial almaceno las horas de 01:00 a 12:00 y usando otro combo selecciono si es AM o PM. Lo mismo hago para obtener la hora2 almaceno las horas de 01:00 a 12:00 en un combo llamado Hora Final y con otro combo selecciono si esta hora es AM o PM. (Adjunto voy a dejar una imagen del formulario para que puedan visualizarlo).

Los combos con valores AM y PM los uso para transformar las horas a el formato de 24 horas conocido a nivel mundial y así poder hacer uso de la función "HourSpan". Por ejemplo, cuando selecciono 3:00 PM transformo la hora 3:00 a 15:00:00 y así sucesivamente con todas las horas que sean PM (02:00 PM = 14:00:00, etc), si son AM las dejo normal pues el formato AM es de 01:00 a 12:00.

Qué función en Delphi puedo usar para calcular la diferencia cuando por ejemplo seleccione:

hora1 = 3:00 PM
hora2 = 1:00 AM

Lo que seria calcular las horas de las tres de la tarde (15:00:00 en formato de 24 horas) a la una de la mañana, teniendo como resultado 10 horas de diferencia.

Actualmente estoy utilizando la función HourSpan a la cual le paso dos parámetros la hora1 y la hora2, esta función me realiza los cálculos perfectamente pero solo si la hora1 es AM y la hora2 PM del resto me regresa valores que no son.

Como podría solucionar este caso, ya que se me exige que trabaje con el formato de hora 01:00 a 12:00 AM y PM.

 



 

Archivos adjuntos


  • 0

#2 Caral

Caral

    Advanced Member

  • Moderador
  • PipPipPip
  • 4.266 mensajes
  • LocationCosta Rica

Escrito 24 enero 2014 - 02:38

Hola
Me parece que la funcion DateUtils tiene lo que necesitas.
No entiendo bien la razon de convertir la hora a formato de 24 horas.
Tal vez algo asi:



delphi
  1. uses DateUtils
  2. ..
  3.  
  4. var
  5.   horaEntrada : TTime;
  6.   horaSalida : TTime;
  7. begin
  8.   horaentrada := Now;
  9.   //incrementamos 5 horas a la hora de salida (para ver el resultado)
  10.   horaSalida := IncHour(now, 5);
  11.   ShowMessage ('Horas empleadas: ' + FloatToStr (HourSpan(horaSalida, horaEntrada)));
  12. end;



Saludos

PD: no veo el formato delphi.. :


Edito: Ya estoy trabajando en ello :)
  • 0

#3 JRichard

JRichard

    Advanced Member

  • Miembros
  • PipPipPip
  • 67 mensajes

Escrito 24 enero 2014 - 03:23

Hola Caral, gracias por responder, estoy usando ese método para calcular la diferencia entre horas, el detalle esta en que cuando intento calcular la diferencia entre valores como 01:00:00 a.m. y 04:00:00 p.m. La diferencia me da 15. Lo cual es correcto y, si intento calcular la diferencia de  04:00:00 p.m. a  01:00:00 a.m. me da 15 también, lo cual es correcto ya que la función HourSpan me calcula la diferencia entre dos horas. Ahora para el uso que necesito darle no sería correcto.

O sea, suponiendo que un empleado llegue a 01:00:00 a.m. y salga a las 04:00:00 p.m. La diferencia de 15 sería correcta. Pero si este empleado llega a las 04:00:00 p.m. y sale a la 01:00:00 a.m. Lógicamente sería incorrecto ya que duro 9 horas laborando.

La función HourSpan acepta dos parámetros para calcular diferencia, indiferentemente de la posición en que coloque los parámetros me da como resultado 15. :( 

 
  • 0

#4 santiago14

santiago14

    Advanced Member

  • Miembros
  • PipPipPip
  • 334 mensajes
  • LocationCerrillos - Salta - Argentina

Escrito 24 enero 2014 - 03:28

HoursBetween en DateUtils es lo que se necesita.

La ayuda dice:

Returns the number of whole hours between two specified TDateTime values.

Unit

DateUtils

Category

datetime routines

Delphi syntax:

function HoursBetween(const ANow, AThen: TDateTime): Int64;

Description

Call HoursBetween to obtain the difference, in hours, between two TDateTime values. HoursBetween counts only entire hours. Thus, HoursBetween reports the difference between 9:00 AM and 9:59:59 AM as 0 because the difference is one second short of an entire hour.

Creo que esto es un buen comienzo para el problema que tienes.

Ahora que lo veo, HourSpan es mejor:

Returns the number of Hours (including fractional Hours) between two specified TDateTime values.

Unit

DateUtils

Category

datetime routines

Delphi syntax:

function HourSpan(const ANow, AThen: TDateTime): Double;

Description

Call HourSpan to obtain the difference, in hours, between two TDateTime values. Unlike the HoursBetween function, which only counts entire hours, HourSpan reports incomplete hours as a fraction of an entire hour.


Lo raro es que no te funcione. Tal vez la cosa está en la forma en que envías las fechas/horas.


Santiago.
  • 0

#5 santiago14

santiago14

    Advanced Member

  • Miembros
  • PipPipPip
  • 334 mensajes
  • LocationCerrillos - Salta - Argentina

Escrito 24 enero 2014 - 03:35

Hola Caral, gracias por responder, estoy usando ese método para calcular la diferencia entre horas, el detalle esta en que cuando intento calcular la diferencia entre valores como 01:00:00 a.m. y 04:00:00 p.m. La diferencia me da 15. Lo cual es correcto y, si intento calcular la diferencia de  04:00:00 p.m. a  01:00:00 a.m. me da 15 también, lo cual es correcto ya que la función HourSpan me calcula la diferencia entre dos horas. Ahora para el uso que necesito darle no sería correcto.

O sea, suponiendo que un empleado llegue a 01:00:00 a.m. y salga a las 04:00:00 p.m. La diferencia de 15 sería correcta. Pero si este empleado llega a las 04:00:00 p.m. y sale a la 01:00:00 a.m. Lógicamente sería incorrecto ya que duro 9 horas laborando.

La función HourSpan acepta dos parámetros para calcular diferencia, indiferentemente de la posición en que coloque los parámetros me da como resultado 15. :( 



Ahhh, ya se lo que está pasando:
A ver si me explico, cuando un empleado entra a las 1:00 am y sale a las 6:00 pm (del mismo día), tenemos una diferencia de 17 hs.
Eso lo hacen bien HourSpan y HourBetween, pero si un tipo entra a las 4:00 pm (de un día) y sale a la 1:00 am (del día que sigue) la cosa no va bien. La diferencia debería ser de 9 hs.
Mas bien lo que habría que hacer es mandarle a HourSpan dos campos fecha-hora (TDateTime) para que haga el cálculo correcto. O sea:
Hora entrada: 24/01/2014 4:00 pm
Hora salida: 25/01/2014 1:00 am
Diferencia: 9 hs.

Espero sirva.
  • 0

#6 JRichard

JRichard

    Advanced Member

  • Miembros
  • PipPipPip
  • 67 mensajes

Escrito 24 enero 2014 - 03:49

Hola Santiago, voy a probar con HoursBetween. Por el nombre creo que si me puede servir jejejeje, y pues estoy enviando las horas en el formato "01:00:00 a.m." que es el que toma delphi del sistema. Llevo rato analizando el HourSpan y pues tiene lógica que no me funcione para lo que necesito ya que el calcula la diferencia de horas entre una hora y otra en un día, por lo que si intento calcular la diferencia entre "01:00:00 a.m." y "04:00:00 p.m." indiferentemente de la posición de los parámetros siempre me va a dar 15 lo cual es correcto :) .

Lo que necesito es un método que me cuente las horas que existen entre una hora y otra pero tomando en cuenta la hora de inicio, "01:00:00 a.m." a "04:00:00 p.m." existen 15 horas de diferencia y de "04:00:00 p.m." y "01:00:00 a.m.", 9 horas.

Tal vez el HoursBetween me sirva, ojala jejeje, sino ya estaba pensando en crearme algún procedimiento y función donde se itere hasta que la hora de inicio sea igual que la hora final y dichas iteraciones se sumen dando como resultado la cantidad que necesito :D, creo que también puede ser una solución, pero primero intentare utilizar cualquier método o función.




  • 0

#7 santiago14

santiago14

    Advanced Member

  • Miembros
  • PipPipPip
  • 334 mensajes
  • LocationCerrillos - Salta - Argentina

Escrito 24 enero 2014 - 03:54

Como comenté unos posts mas arriba, ambas funciones funcionan correctamente, inclusive creo que HourSpan es mejor.
Lo que hay que hacer es enviarle a HourSpan (u HoursBetween si lo prefieres) valores tipo fecha-hora y no valores tipo hora solamente.

Hora entrada: 24/01/2014 4:00 pm
Hora salida: 25/01/2014 1:00 am
Diferencia: 9 hs.


Con eso, las funciones te devolverán la cantidad de horas siempre de manera correcta.

Saludos.
  • 0

#8 santiago14

santiago14

    Advanced Member

  • Miembros
  • PipPipPip
  • 334 mensajes
  • LocationCerrillos - Salta - Argentina

Escrito 24 enero 2014 - 04:02

Estoy mirando la imagen que pusiste. Me parece que en lugar de poner "Hora inicial" y dos combos con las horas y el AM/PM sería mejor usar un TDateTimePicker, está en la pestaña Win32. Luego le cambiamos la propiedad Kind a dtkTime y queda listo para que pongas la hora en el formato que la PC tenga (AM/PM o de 24 hrs), al momento de ejecutar, sin que el usuario se preocupe y el programador tampoco, por este problema.
Pido ayuda a la población del foro para que recomiende un componente mas apropiado, si lo hay, para este caso.

También agregaría en el formulario alguna manera de indicar que el horario de entrada es en un día y el de salida es en el día siguiente, o ambos en el mismo día. Todo esto para que después le enviemos a la función dos variables de tipo fecha-hora (TDateTime) y el cálculo se haga correctamente.

Saludos.
  • 0

#9 santiago14

santiago14

    Advanced Member

  • Miembros
  • PipPipPip
  • 334 mensajes
  • LocationCerrillos - Salta - Argentina

Escrito 24 enero 2014 - 04:04

PD: no veo el formato delphi.. :
Edito: Ya estoy trabajando en ello :)


Por favor, no te olvides de poner las etiquetas para sql también.

Santiago.
  • 0

#10 Caral

Caral

    Advanced Member

  • Moderador
  • PipPipPip
  • 4.266 mensajes
  • LocationCosta Rica

Escrito 24 enero 2014 - 04:12

Hola
En el ejemplo las variables son TTime.
HourSpan acepta también del tipo DateTime
Como dice santiago14 si se hace una resta de fechas y estas pasan las 24 horas que tiene un día ya se convierten en el día siguiente por lo que es necesario la colocación de la fecha completa o día de semana y hora para que la función la entienda.
Hay que recordar que retorna float. *-) (y)

Saludos
  • 0

#11 JRichard

JRichard

    Advanced Member

  • Miembros
  • PipPipPip
  • 67 mensajes

Escrito 24 enero 2014 - 06:08

Muchas Gracias por su ayuda! Voy a probar como me va aplicando sus métodos!  (b)
  • 0

#12 Caral

Caral

    Advanced Member

  • Moderador
  • PipPipPip
  • 4.266 mensajes
  • LocationCosta Rica

Escrito 24 enero 2014 - 06:21

Hola
Y si no te sale esperaremos a los que si saben y así aprendemos todos. (y)
Saludos
  • 0

#13 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 25 enero 2014 - 10:12

El mejor sistema es el que use TDateTime, pero si los datos los introducimos de forma que sólo incluimos la hora, la diferencia estará siempre viciada pues no hemos cambiado de día.

Un TDateTime es un double cuya parte entera representan días y la parte decimal fracciones de día (24h). Si restamos 16:00:00 - 01:00:00 obtenemos un numero negativo equivalente a 15 horas. Siempre que sea negativo debemos sumar la unidad (un día).

Ejemplo:


delphi
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   Time: TDateTime;
  4. begin
  5.   Time:= DateTimePicker2.DateTime-DateTimePicker1.DateTime;
  6.   if Time < 0 then Time:= Time+1;
  7.   Label1.Caption:= TimeToStr(Time);
  8. end;



Saludos.

  • 0

#14 santiago14

santiago14

    Advanced Member

  • Miembros
  • PipPipPip
  • 334 mensajes
  • LocationCerrillos - Salta - Argentina

Escrito 27 enero 2014 - 06:17

El mejor sistema es el que use TDateTime, pero si los datos los introducimos de forma que sólo incluimos la hora, la diferencia estará siempre viciada pues no hemos cambiado de día.

Un TDateTime es un double cuya parte entera representan días y la parte decimal fracciones de día (24h). Si restamos 16:00:00 - 01:00:00 obtenemos un numero negativo equivalente a 15 horas. Siempre que sea negativo debemos sumar la unidad (un día).

Ejemplo:


delphi
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   Time: TDateTime;
  4. begin
  5.   Time:= DateTimePicker2.DateTime-DateTimePicker1.DateTime;
  6.   if Time < 0 then Time:= Time+1;
  7.   Label1.Caption:= TimeToStr(Time);
  8. end;



Saludos.


Ah sí, esto me gustó. Creo que aquí está la mejor solución para el problema planteado.

Gracias.
  • 0




IP.Board spam blocked by CleanTalk.