PDA

Ver la Versión Completa : Resta de horas


didier
29-06-2005, 00:03:32
Resta de horas
Estimados amigos del club como puedo restar dos horas
Ejemplo1 : 12:00 - 14:00 = 2 horas bien
Ejemplo2 : 08:00 - 12:00 = 4 horas bien
Ejemplo3 : 22:00 – 08:00 = 14 horas malo deberian ser 10 horas

Estoy trabajando con el componente TdatetimePicker

Si alguien me sugiere otra se lo agradezco

Gracias

dec
29-06-2005, 01:39:29
Hola,

A ver qué tal esto:


uses
DateUtils;

procedure TForm1.Button1Click(Sender: TObject);
var
hora: TTime;
begin
// 2 más de la hora actual
hora := IncHour(now, 2);
// 2 menos de la hora actual
hora := IncHour(hora, -2);
// Mostramos la hora actual
ShowMessage(TimeToStr(hora));
end;

jachguate
29-06-2005, 15:55:10
Que tal esto otro:


Var
Horas : Double;
Begin
Horas := dtpHoraFinal.DateTime - dtpHoraInicio.DateTime;
ShowMessage(Format('Las horas transcurridas (en decimal) son: %5.3d', [Horas * 24]));
//mostrará 3.5 horas para 3:30, 10.3333 para 10:20, etc.


Hasta luego.

;)

Crandel
29-06-2005, 23:20:45
El problema te ocurre porque debes estar restando la propiedad Time cuando en realidad debes utilizar la porpiedad DateTime.

Porque en tu caso las 08:00 son del día siguiente, y si no incluis la parte del día no se va a reflejar.

Suerte

didier
30-06-2005, 16:00:20
Amigos del club he solucionado el problema de la siguiente manera, quizás no es la mas optima pero para mi problema esta OK, ya que necesito mostrar el día en un campo y la hora en otro aquí mando código por si alguien lo necesitara.

Gracias


//calcula cantidad de horas

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, DateUtils;

type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
DateTimePicker1: TDateTimePicker;
DateTimePicker2: TDateTimePicker;
Label2: TLabel;
DateTimePicker3: TDateTimePicker;
DateTimePicker4: TDateTimePicker;
Label3: TLabel;
Label4: TLabel;
Label5: TLabel;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
fecha : string;
Tfecha1 : TDateTime;
Tfecha2 : TDateTime;
begin
fecha := datetostr(DateTimePicker1.Date) + ' ' +
timetostr(DateTimePicker2.time);
Label1.Caption := fecha;
Tfecha1 := strtodatetime(fecha);
Label2.Caption := datetimetostr(Tfecha1);

fecha := datetostr(DateTimePicker3.Date) + ' ' +
timetostr(DateTimePicker4.time);
Label3.Caption := fecha;
Tfecha2 := strtodatetime(fecha);
Label4.Caption := datetimetostr(Tfecha2);

Label5.Caption := inttostr(HoursBetween(tfecha2 , tfecha1));
end;

end.

angara
31-12-2007, 22:58:26
Probe el codigo me funciona para las horas pero en mi caso tambien nececito los minuto y segundos, para un sistema de control de ingreso de personal
gracias

jachguate
02-01-2008, 17:39:48
Para ese caso, tenés también las funciones MinutesBetween y SecondsBetween.

Hasta luego.

;)

angara
05-01-2008, 20:11:59
Gracias,
ahora solo tengo que realizar las operaciones correspondiente.

saltamirano
23-01-2008, 16:05:39
Probe el codigo me funciona para las horas pero en mi caso tambien nececito los minuto y segundos, para un sistema de control de ingreso de personal
gracias

:o Saludos amigos:

He revisado este hilo y me ha servido de mucha utilidad, tengo dos DateTimePicker, en los cuales se ingresa Hora de Inicio y Hora de Fin, en mi aplicación requiero restar las dos horas para obtener el tiempo ocupado. Tengo el siguiente código:

procedure TForm_Soporte.DateTimePicker_HraIniChange(Sender: TObject);
var dMiHraIni : TTime;
var HraIniStr: string;
begin
dMiHraIni := DateTimePicker_HraIni.Time;
HraIniStr := (TimeToStr(dMiHraIni));
self.DBEdit_HraIni.Text := HraIniStr;
end;

procedure TForm_Soporte.DateTimePicker_HraFinChange(Sender: TObject);
var dMiHraFin, tiempo1, tiempo2 : TTime;
var HraFinStr, dif_hra, dif_min, dif_seg, time: string;
var dif_hra_int, dif_min_int : integer;
var min_calc, seg_calc: integer;

begin
dMiHraFin := DateTimePicker_HraFin.Time;
HraFinStr := (TimeToStr(dMiHraFin));
self.DBEdit_HraFin.Text := HraFinStr;
tiempo1:= DateTimePicker_HraFin.Time;
tiempo2:= DateTimePicker_HraIni.Time;

dif_hra := inttostr(HoursBetween(tiempo2 , tiempo1));
dif_hra_int := strtoint(dif_hra);

if dif_hra_int > 0 then
begin
min_calc := ((MinutesBetween(tiempo2 , tiempo1))mod (dif_hra_int * 60));
dif_min := inttostr(min_calc);
end
else
begin
dif_min := inttostr(MinutesBetween(tiempo2 , tiempo1));
end;

if min_calc > 0 then
begin
seg_calc := (SecondsBetween(tiempo2 , tiempo1))mod (min_calc * 60);
dif_seg := inttostr(seg_calc);
end
else
begin
dif_seg := inttostr(SecondsBetween(tiempo2 , tiempo1));
end;
}
time := dif_hra + ':'+ dif_min + ':'+ dif_seg;
self.DBEdit_time.Text := time;
self.DBEdit_time.Show
end;

Al restar las horas por ejemplo: 8:00 a 14:30 el resultado es de: 6:29 y no
6:30 como debería ser:mad:.

Por fa si alguien tiene idea de lo que está pasando necesito una ayudita. Mil Gracias!!

saltamirano
23-01-2008, 16:06:20
Probe el codigo me funciona para las horas pero en mi caso tambien nececito los minuto y segundos, para un sistema de control de ingreso de personal
gracias

:o Saludos amigos:

He revisado este hilo y me ha servido de mucha utilidad, tengo dos DateTimePicker, en los cuales se ingresa Hora de Inicio y Hora de Fin, en mi aplicación requiero restar las dos horas para obtener el tiempo ocupado. Tengo el siguiente código:

procedure TForm_Soporte.DateTimePicker_HraIniChange(Sender: TObject);
var dMiHraIni : TTime;
var HraIniStr: string;
begin
dMiHraIni := DateTimePicker_HraIni.Time;
HraIniStr := (TimeToStr(dMiHraIni));
self.DBEdit_HraIni.Text := HraIniStr;
end;

procedure TForm_Soporte.DateTimePicker_HraFinChange(Sender: TObject);
var dMiHraFin, tiempo1, tiempo2 : TTime;
var HraFinStr, dif_hra, dif_min, dif_seg, time: string;
var dif_hra_int, dif_min_int : integer;
var min_calc, seg_calc: integer;

begin
dMiHraFin := DateTimePicker_HraFin.Time;
HraFinStr := (TimeToStr(dMiHraFin));
self.DBEdit_HraFin.Text := HraFinStr;
tiempo1:= DateTimePicker_HraFin.Time;
tiempo2:= DateTimePicker_HraIni.Time;

dif_hra := inttostr(HoursBetween(tiempo2 , tiempo1));
dif_hra_int := strtoint(dif_hra);

if dif_hra_int > 0 then
begin
min_calc := ((MinutesBetween(tiempo2 , tiempo1))mod (dif_hra_int * 60));
dif_min := inttostr(min_calc);
end
else
begin
dif_min := inttostr(MinutesBetween(tiempo2 , tiempo1));
end;

if min_calc > 0 then
begin
seg_calc := (SecondsBetween(tiempo2 , tiempo1))mod (min_calc * 60);
dif_seg := inttostr(seg_calc);
end
else
begin
dif_seg := inttostr(SecondsBetween(tiempo2 , tiempo1));
end;
}
time := dif_hra + ':'+ dif_min + ':'+ dif_seg;
self.DBEdit_time.Text := time;
self.DBEdit_time.Show
end;

Al restar las horas por ejemplo: 8:00 a 14:30 el resultado es de: 6:29 y no
6:30 como debería ser:mad:.

Por fa si alguien tiene idea de lo que está pasando necesito una ayudita. Mil Gracias!!

Crandel
23-01-2008, 16:30:56
cuales son los segundos de los dos tiempos?

asegurate que sean cero sino te interesan.

saltamirano
23-01-2008, 21:25:38
Gracias por tu preocupación amigo,

los segundos en la hora son cero, sin embargo no entiendo porque al restar las horas algunas veces saca datos exactos, pero en otros no como en el caso del ejemplo.

Mil gracias por su ayuda

Saludos ;)

jachguate
23-01-2008, 22:18:27
Creo que estas haciéndote un lio para la operación.

Con el ejemplo citado, podrías indicarnos que resultado te da esta operación:


ShowMessage(TimeToStr(DateTimePicker_HraFin.Time - DateTimePicker_HraIni.Time));


Seguramente hay fracciones de segundo por allí involucradas.. ;)

BlueSteel
03-04-2008, 23:15:37
Hola

estaba revisando este hilo... y me queda una duda...

el problema es que tengo la hora 09:16:00 pero lo tengo en formato de String...

para convertirlo utilizo el StrToTime(hora)

con

HoursBetween(HoraFin, HoraIni) me entrega las horas que existen entre ambas... pero en que formato las estaría entregando ???

Salu2

Caral
03-04-2008, 23:22:49
Hola
Pues el formato lo puedes poner tu:

Edit1.Text:= FormatDateTime('hh.mm.ss',Time);
Me parece.
Saludos

jhonny
03-04-2008, 23:27:44
Hola

estaba revisando este hilo... y me queda una duda...

el problema es que tengo la hora 09:16:00 pero lo tengo en formato de String...

para convertirlo utilizo el StrToTime(hora)

con

HoursBetween(HoraFin, HoraIni) me entrega las horas que existen entre ambas... pero en que formato las estaría entregando ???

Salu2

HoursBetween devuelve un tipo de dato Int64, que significan el valor de horas entre una y la otra, por ejemplo (Este ejemplo lo saco de la ayuda de Delphi):

Si yo quiero saber cuantas son las horas entre 9:00 AM y 9:59:59 AM esta funcion me devolvera 0.


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.

BlueSteel
03-04-2008, 23:29:49
Es decir...

tendria entonces que preguntar por los minutos transcurridos entre dos horas..

el valor dividirlo por 60 para así obtener la cantidad de horas y minutos...

Ok...

veré como realizo esto...

Salu2:p:D

Caral
03-04-2008, 23:33:39
var
hora1, hora2: TTime;
horat: TTime;
begin
hora2:= StrToTime(Edit2.Text);
hora1:= StrToTime(Edit3.Text);
horat := hora1 - hora2;
Edit4.Text:= TimeToStr(horat) ;
end;

BlueSteel
04-04-2008, 00:27:02
Ya.. tengo lista una parte...

me explico... como los valores los tomo de un StringGrid, en donde tiene las sgtes columnas

0 -> Dias de Semana (Lun, Mar, Etc)
1 -> Fecha
2 -> Hora de Entrada1
3 -> Hora de Salida1
4 -> Hora de Entrada2
5 -> Hora de Salida1
6 -> Hora de Entrada3
7 -> Hora de Salida1
8 -> Suma de Horas Trabajadas

El problema lo tengo cuando en una celda específica no existe nada... y preguntar por cada uno.. me dará mucho trabajo... existe una forma de que si el valor es vacio no me de error...

y el otro problema que se me puede ocacionar es si solo existe hora de entrada y no de salida....???? o Viceversa

Bueno, se supone que en la columna 8 del StringGrid debo poner esto (se que esta en minutos.. pero despues lo arreglo)

Marcado.Rows[i][8]:= IntToStr( MinutesBetween(StrToTime(Marcado.Rows[i][3]),StrToTime(Marcado.Rows[i][2]))
+ MinutesBetween(StrToTime(Marcado.Rows[i][5]),StrToTime(Marcado.Rows[i][4]))
+ MinutesBetween(StrToTime(Marcado.Rows[i][7]),StrToTime(Marcado.Rows[i][6])));

Espero me hayan entendido...

Salu2:p:D

Caral
04-04-2008, 00:40:00
Hola
Ahora veo lo que estas haciendo, es algo asi. (http://www.terawiki.clubdelphi.com/archivos/Delphi-Win32/Ejemplos/Control%20de%20Asistencias%20de%20Empleados.zip)
Saludos

BlueSteel
04-04-2008, 00:40:07
se me ocurrio realizar lo sgte


i : Integer;
Ent1, Ent2, Ent3 : TTime;
Sal1, Sal2, Sal3 : TTime;
begin
i:= 1;
For i:=1 to Marcado.RowCount-1 Do
Begin
If Marcado.Rows[i][2] = ' ' Then Ent1 := StrToTime('0') Else Ent1 := StrToTime(Marcado.Rows[i][2]);
If Marcado.Rows[i][3] = ' ' Then Sal1 := StrToTime('0') Else Sal1 := StrToTime(Marcado.Rows[i][3]);
If Marcado.Rows[i][4] = ' ' Then Ent2 := StrToTime('0') Else Ent2 := StrToTime(Marcado.Rows[i][4]);
If Marcado.Rows[i][5] = ' ' Then Sal2 := StrToTime('0') Else Sal2 := StrToTime(Marcado.Rows[i][5]);
If Marcado.Rows[i][6] = ' ' Then Ent3 := StrToTime('0') Else Ent3 := StrToTime(Marcado.Rows[i][6]);
If Marcado.Rows[i][7] = ' ' Then Sal3 := StrToTime('0') Else Sal3 := StrToTime(Marcado.Rows[i][7]);
Marcado.Rows[i][8] := IntToStr(MinutesBetween(Sal1,Ent1)+ MinutesBetween(Sal2,Ent2)+ MinutesBetween(Sal3,Ent3));
End;


pero igual me esta dando el sgte error

el problema de esto es que hay dias en que no se marca tarjeta... u otras personas marcan solo 2 veces al día.. y otros 4 o 6 veces al día segun corresponda...



raised exception class EConvertError with message "' is not a valid time'.

Bueno..igual seguiré intentando...

Salu2

jhonny
04-04-2008, 00:47:52
Mira, seguramente te servirá el siguiente ejemplo que acabo de probar:

- Coloca dos TDateTimePicker en el Form, sus propiedades Kind en dtkTime y un botón con el siguiente código en su OnClick:

ShowMessage(FormatDateTime('HH:MM:SS', DateTimePicker2.Time-DateTimePicker1.DateTime));

Y Listo, veras como funciona de bonito sin complicarte tanto la vida ;).

BlueSteel
04-04-2008, 01:19:49
Hola
Ahora veo lo que estas haciendo, es algo asi. (http://www.terawiki.clubdelphi.com/archivos/Delphi-Win32/Ejemplos/Control%20de%20Asistencias%20de%20Empleados.zip)
Saludos


Si tienes razon... el problema es que los datos los capturo de un reloj control biometrico de estos (http://www.genera.cl/Horus.asp)

entonces los datos que capturo son del sgte formato


1 01005 20080218 1519
1 02003 20080218 1525
1 01012 20080218 1525
0 01012 20080218 1526
1 06012 20080218 1533
1 06014 20080218 1535
1 02001 20080218 1537
0 02010 20080218 1538
0 02011 20080218 1538
1 02019 20080218 1544
1 01012 20080218 1749
0 06012 20080218 1821
0 06014 20080218 1822


donde :

la primera columna es el tipo de entrada
0 -> salida
1 -> entrada

la segunda columna es la ficha del trabajador
la tercera columna es la fecha
la cuarta columna es la hora

entonces eso lo traspaso a un tabla de SQL... (Horario) y se me almacena de la sgte forma

Hor_Numero -> Numero autoincremental
Per_Nro -> ficha del trabajador
Hor_Tipo -> Tipo de marcado (1 Entrada / 0 Salida )
Hor_Fecha -> Fecha y hora de marcado

para rescatar los datos de un trabajador en especifico realizo una consulta así.. ej. Ficha 1015


Select Per_Nro, Hor_Tipo,
CONVERT(Char(10), Hor_Fecha, 103) As Fecha,
CONVERT(Char(8), Hor_Fecha, 108) As Hora
From Horario
Where Per_Nro=1015
Order By Fecha, Hora


con el siguiente codigo... traspaso los datos a un StringGrid... con el sgte formato:

Dia Semana / Fehca / ent 1 / sal 1 / ent 2 / sal 2 / ent 3 / sal 3 / total hras

el sgte codigo me genera un StringGrid de x Fila segun el rango de fecha que se haya señalado.. y además, me va agregando la el dia de la semana y la fecha en la primera y segunda columna del stringgrid


Marcado.RowCount := Trunc(vFecH.Date - vFecD.Date)+2;
i:= 1;
For i:=1 to Marcado.RowCount-1 Do
Begin
Marcado.rows[i][0] := FormatDateTime('ddd', (Trunc(vFecD.Date-1)+i));
Marcado.rows[i][1] := DateToStr(Trunc(vFecD.Date-1)+i);
End;


despues si ejecuto este codigo me empieza a buscar segun la ficha ingresada y segun la fecha de la columna fecha del StringGrid.. los datos y los va distribuyendo dentro del StringGrid


i:= 1;
For i:=1 to Marcado.RowCount-1 Do
Begin
Datos.AQ_Horario.First;
While Not Datos.AQ_Horario.Eof Do
Begin
if Datos.AQ_Horario['Fecha'] = StrToDAte(Marcado.Rows[i][1]) Then
If Datos.AQ_Horario['Hor_Tipo'] = 0 Then
Begin
if Marcado.Rows[i][3] = '' Then
Marcado.Rows[i][3] := Datos.AQ_Horario['Hora']
Else
if Marcado.Rows[i][5] = '' Then
Marcado.Rows[i][5] := Datos.AQ_Horario['Hora']
Else
Marcado.Rows[i][7] := Datos.AQ_Horario['Hora'];
End
Else
Begin
if Marcado.Rows[i][2] = '' Then
Marcado.Rows[i][2] := Datos.AQ_Horario['Hora']
Else
if Marcado.Rows[i][4] = '' Then
Marcado.Rows[i][4] := Datos.AQ_Horario['Hora']
Else
Marcado.Rows[i][6] := Datos.AQ_Horario['Hora'];
End;
Datos.AQ_Horario.Next;
End;
End;



eso me entrega un resultado como el de la sgte imagen

http://bluesteel.clubdelphi.com/imagenes/pantalla.jpg

como veras pueden haber dias que no tenga nada de marcado.. otros que solo han marcado 4 veces.. y otros seis veces...

Salu2:p:D

PS: estube revisando tu programa.. me parece genial.. pero tu de antemano le pides si marca 1, 2 , 3 o 4...

gonza_619
18-11-2010, 15:37:53
bueno mi pregunta es , como hora pero con segundos siempre en 00 sin tener q cambiarlo utilizando un dtpicker?, yo en la propiedad format del dtpicker coloq: HH:mm pero al gaurdar simpre em guarda con segundos en 52 y quisisera q lo guarde en 00 simpre, gracias a todos

jachguate
18-11-2010, 23:11:54
Revisá la hora con la que inicia el componente. Seguramente esta tiene los 52 segundos (1:14:52), como el usuario solo puede cambiar horas y minutos, esto queda constante.

Otra opción es que trunques "a mano" los segundos que pueda traer... por ejemplo:


uses DateUtils;

function TruncateSeconds(const AValue: TDateTime): TDateTime;
begin
Result := AValue - SecondOf(AValue) / SecsPerDay;
end;


Podrías probar la función así:


procedure TForm2.Button1Click(Sender: TObject);
begin
Label1.Caption := DateTimeToStr(Now) + ' => ' + DateTimeToStr(TruncateSeconds(Now));
Label2.Caption := DateTimeToStr(DatePicker1.DateTime) + ' => ' + DateTimeToStr(TruncateSeconds(DatePicker1.DateTime));
end;


Saludos.