[ Foro de Pascal ]

sumar fechas formato militar HH:MM

28-Jun-2011 10:48
oscar gomez
13 Respuestas

Cordial saludo profesor Nacho, mil gracias antes que todo por tu tiempo para con nosotros y lo excelente profesor que eres.

quiero realizar un programa en el que se involucran fechas en formato militar y entre otras cosas poder sumarlas para obtener totales y demas...

se tiene un vector que almacena los codigos de los empleados y una matriz donde se almacenan las horas laboradas por dicho trabajador, en donde en su orden a cada elemento del vector corresponde una fila de la matriz.
se tienen N trabajadores que laboran durante M dias. en un ejemplo seria algo asi: N=4 ; M=3


                        dias

 codigo          dia1      dia2    dia3  
  120            8:50      9:00    7:30  
  128            8:00     9:50    7:00  
  221            7:30     8:30    9:40  
  301           16:20     13:10   4:30  


se pide calcular e imprimir:
a)total de horas trabajadas por cada empleado
b)total de horas trabajadas por todos los empleados
c)el total de horas laboradas en cada jornada
d)el codigo del empleado que mas horas laboro
e)el numero del dia en que mas horas de laboro


bien profesor como primera duda que tengo es si lo trabajo como a)arrays paralelos o es mas conveniente trabajarlo como un
b)array de registros ???, para cada caso por favor corrigeme si lo estoy planteando mal o si es correcto:

para el caso a)

program horas_en_obra;
uses crt;
 const
       maxempleados=4;
       maxdias=3;

 type
      tiempo=record
         hh,mm:integer;
      end;

 var codigo:array[1..maxempleados] of string[3];
     horas_dias:array[1..maxempleados,1..maxdias] of tiempo;
     
  .....

aqui empiezan mis dudas, como hago para trabajar el array, horas_dias para ir sumando las horas en el formato dado para ellas??? ,deberia hacer alguna conversion primero o se puede sumar directamente porejemplo: 16:20 + 9:20 ...????


ahora para obtener la suma de las horas por empleado debo utilizar otro array, como porejemplo:

total_H_empleados:array[1..maxdias] of tiempo ???? si es asi como trabajaria este array dado que es de tipo tiempo? podria hacer algo como esto:

for i:=1 to maxempleados do
begin
 total_E_empleados[i]:=0;
   for j:=1 to maxdias do
    total_E_empleados[i]:=total_E_empleados[i]+ horas_dias[i][j]
   end;
       
       
aqui esta mi otra gran duda, si he definido la matriz horas_dias como tipo tiempo, es incorrecto hacer:
total_E_empleados[i]:=total_E_empleados[i]+ horas_dias[i][j]
como podria ser entonces para que sea correcto???



pra el caso b)podria ser:???

program  horas_en_obra;
uses crt;
 const
       maxempleados=4;
       maxdias=3;
 type
      tiempo=record
       hh,mm:integer;
      end;

       datos=record
          codigo:strin[3];
          horas_dias:array[1..maxdias] of tiempo;
        end;

   total_empleados=array[1..maxempleados] of datos;
 
 var empleados:total_empleados;
....

no se si este correcto mi planteamiento inicial, por favor corregirme y si es ok , vuelve mi duda como podria trabajar en este caso el array horas_dias, que es un campo de datos y es de tipo tiempo??????

le agradeceria profesor me ayudaras , mil gracias


29-Jun-2011 20:42
Nacho Cabanes (+32)

Hacer un array de struct es más elegante, pero también más laborioso. Trabajar en paralelo con dos arrays es más simple, pero es aceptable para problemas sencillos.

En cualquier caso, en un lenguaje como Pascal estándar, que no incluya un tipo de datos "fecha", deberás ser tú quien cree las funciones que se encarguen de sumar tiempos, o de calcular diferencias entre ellos. No es complicado, apenas tienes que tener presentes ciertos detalles como los desbordamientos:

- 50' + 40' = 1h 30 min

- 23h + 2h = ¿debe mostrarse como 1d 1h o contar siempre en horas y mostrar 25h?


01-Jul-2011 11:15
oscar gomez

Hola profesor Nacho, gracias por tu tiempo y en lo que puedas ayudarme.

mira he decidido tomar tu consejo ( "por elegancia")de realizar este programa por medio de array de registros, pero claro el problema que tengo es cuando leo los datos por registro y debo leer los tiempos que estan en formato militar, pues intento crear una funcion primero que me convierta cada fecha de empleado en formato militar a solo minutos con el fin de poder sumar minutos y al final cuando tenga el subtotal para cada empleado o el total de la suma de las horas de todos los empleados en minutos haga uso de una segunda funcion que me convierta esos totales en formato militar,pero me encuentro con el problema de como serian los parametros que recibe la funcion que yo llamare convertirAminutos o si como lo estoy haciendo es correcto o incorrecto, por favor ayudame en lo que mas puedas por que la verdad lo necesito, mira lo que yo hago, por favor corrigeme y orientame a traves de codigo si te es posible en lo que mas puedas agradeciendotelo de antemano.


program horas_en_obra;
uses crt;
const maxempleados=4;
      maxdias=3;
type
      tiempo=record
       hh,mm:integer;
      end;

      datos=record
        codigo:string[3];
        horas:array[1..maxdias] of tiempo;
       end;

      total_empleados=array[1..maxempleados] of datos;

var
    empleados:total_empleados;
    i,j:integer;
    sumasXempleado:array[1..maxdias] of tiempo;
    sumasXjornada:array[1..maxempleados] of tiempo;
    sumaHtotales:tiempo;



function convertir_A_minutos(th:tiempo,tm:tiempo):longint;
begin
  convertir_A_minutos:=th.hh*60 +tm.mm;
end;

begin
clrscr;
for i:=1 to maxempleados do
 begin
  writeln('digite el codigo del empleado:');
  read(empleados[i].codigo;
  for j:=1 to maxdias do
   begin
    writeln('introduzca tiempos del empleado ',i,':');
    read(empleados[i].horas[j].hh);
    read(empleados[i].horas[j].mm);
    minutos:=convertir_A_minutos(empleados[i].horas[j].hh,empleados[i].horas[j].mm);
    sumasXempleado[i]:=sumasXempleado[i]+ minutos;
   sumaHtotales:=sumaHtotales +minutos;
 end;
end;
end.

hasta aqui lo dejo para que por favor me indiques si es correcto lo que llevo hasta el momento y me indiques si estoy realizando correctamente la lectura de los datos y en especial si la funcion la tengo correctamente definida en cuanto a los parametros que recibe y en cuanto al calculo como tal,ojala me puedas ayudar por que quiero poderlo realizar pues me parece claro en mi humilde opinion que es un programa interesante.
mil gracias profesor ayudame porfavor.


03-Jul-2011 12:05
Nacho Cabanes (+32)

A ver... aquí hay varios errores...

Algunos de ellos son simplemente errores sintácticos, y te los dice el propio compilador. Por ejemplo:

- En la línea 26, los parámetros tienes que separarlos con punto y coma (;)

- En la línea 36, te falta cerrar el paréntesis.

- En la linea 42, usas una variable "minutos" que no has declarado previamente.


Pero tambien hay algún error de concepto. Por ejemplo:

- La función "convertir_A_minutos" recibe... ¿dos tiempos?  ¿no debería ser un único dato de tipo "tiempo" o bien dos datos numéricos que representen las horas y los minutos?


03-Jul-2011 18:42
oscar gomez

Hola profesor Nacho.como siempre MIL GRACIAS POR TU TIEMPO Y TU AYUDA.


en cuanto a los errores de sintaxis ,es verdad que los habia pasado pero ya lo he tenido presente.

ahora bien respecto al error de concepto es que precisamente es ahi donde tengo el problema,bien lo hice y me resulta utilizando en la funcion dos datos numéricos que representan las horas y los minutos, pero se que lo interesante seria la otra forma que me indicas <<un único dato de tipo "tiempo">> el problema  que tengo y que no entiendo es si estoy leyendo por separado las horas y los minutos, es decir:
for i:=1 to maxempleados do
 begin
 writeln('digite el codigo del empleado:');
 read(empleados[i].codigo);
 for j:=1 to maxdias do
   begin
   writeln('introduzca tiempos del empleado ',i,':');
   read(empleados[i].horas[j].hh);
   read(empleados[i].horas[j].mm);
   ....

como hago al llamar a la funcion para que en ella utilice un unico dato de tipo tiempo? pues intente hacerlo de la siguiente forma pero parece que no recibe los parametros correctamente:

es decir yo lo intento hacer asi:


program horas_en_obra;
uses crt;
const maxempleados=4;
     maxdias=3;
type
     tiempo=record
       hh,mm:integer;
     end;

     datos=record
       codigo:string[3];
       horas:array[1..maxdias] of tiempo;
       end;

     total_empleados=array[1..maxempleados] of datos;

var
   empleados:total_empleados;
   i,j:integer;
   t:tiempo;
   minutos:integer;
   sumaminutos:array[1..maxempleados] of integer;
   


function convertir_A_minutos(t:tiempo):integer;
begin
 with t do
  convertir_A_minutos:=hh*60 +mm;
end;


begin
clrscr;
writeln;writeln;writeln;writeln;

 for i:=1 to maxempleados do
  begin
   writeln('digite el codigo del empleado:');
   read(empleados[i].codigo);
   writeln('introduzca tiempos del empleado ',i,':');
   sumaminutos[i]:=0;
   for j:=1 to maxdias do
    begin
     write('escriba las horas:');
     read(empleados[i].horas[j].hh);
     write('escriba los minutos:');
     read(empleados[i].horas[j].mm);
     minutos:=convertir_A_minutos(t);
    end;
   sumaminutos[i]:=sumaminutos[i] + minutos;
   writeln('la suma para empleado ',i, 'vale: ',sumaminutos[i]);
  end;
end.


Por favor profesor Nacho ayudame a indicarme en que estoy mal y como seria lo correcto para poder alcanzarlo,tengo mi duda si lo que esta mal es cuando hago despues de leer, es decir en el llamado a la funcion:
 minutos:=convertir_A_minutos(t);???? como seria lo correcto?
sabes que me estoy esforzando dame esa mano de ayuda para poderme superar...gracias


03-Jul-2011 22:50
Nacho Cabanes (+32)

Veo cosas raras, como éstas:

> read(empleados[i].horas[j].mm);
> minutos:=convertir_A_minutos(t);

En primer lugar, usa "readLn" en vez de "read". Es mas previsible.

En segundo lugar, si los datos los lees en "empleados[i].horas[j].mm", lo razonable sería algo como

minutos:=convertir_A_minutos( empleados[i].horas[j] );

es decir, convierte a minutos lo que has leído, no una variable "t" que no usas en ningún sitio.


04-Jul-2011 09:48
oscar gomez

Gracias profesor Nacho por tu ayuda gracias a ella he podido solucionar ya el programa y tenias toda la razon con lo de t, es incorrecto,gracias por fin lo solucione ,sin tu ayuda quiza no hubiese sido capaz.


06-Jul-2011 12:01
oscar gomez

Hola profesor Nacho.

profesor es que ya resolvi los tres primeros puntos a, b y c, y voy a rsolver :
d)el codigo del empleado que mas horas laboro
e)el numero del dia en que mas horas de laboro

mi pregunta es saber que  entiendes tu o que seria lo mas conveniente pues no se me parece ambigua las dos preguntas d , y e, es decir:
cuando me piden el codigo del empleado que mas horas laboro lo tomo en funcion al total de horas obtenido por cada uno de ellos y de ellos tomar el mayor , o mejor de todas las horas busco la mayor y su correspondiente empleado?
asi seria para el punto e), podrias orientarme gracias


06-Jul-2011 19:32
oscar gomez

cordial saludo profesor Nacho.

en primera instancia profesor queria pedirte orientacion
en cualquiera de los dos casos del ejercicio (d) y e),¿con que valor podria iniciar la variable mayor dado que lo que tengo es una fecha de tipo tiempo, como podria ser, porejemplo, mayor_tiempo:=0; seria correcto dado que como te indico he definido cada hora en formato militar(hh:mm)??orientame por favor, como siempre muy agradecido. gracias


P.D. profesor te adjunto el ejecutable de los tres primeros puntos que pide el ejercicio, asi como una captura de ejemplo con datos de ejemplo en ejecucion, para que me indiques  por favor que puedo estar haciendo mal para que las fechas me esten saliendo desfazadas y no me permita una visualizacion ordena. la parte de codigo en la que realizo la visualizacion es la siguiente:


gotoxy(22,6);
 writeln('*** INFORME DE DATOS Y RESULTADOS ***');
 writeln;
 gotoxy(58,19);
 writeln('total tiempo por');
 gotoxy(10,20);
 writeln('Codigo            Dia1      Dia2      Dia3          empleado ');
 gotoxy(10,21);
 write('-------           ----      ----      ----      ----------------- ');

 for i:=1 to maxempleados  do
   begin
     gotoxy(10,21+i);
     write(empleados[i].codigo,' ');
     gotoxy(28,21+i);
      for j:=1 to maxdias do
        begin
          write(empleados[i].horas[j].hh,':');
          write(empleados[i].horas[j].mm);
          write(' ':7);/***NO SE SI AQUI ESTA EL PROBLEMA**?

        end;
        convertir_A_militar(sumaminutosXempleado,i,t);
        gotoxy(63,21+i);
       write(t.hh:2,':',t.mm:2);
       writeln;
    end;
    gotoxy(28,23+maxempleados);
    write('----      ----      ----');
   gotoxy(10,24+maxempleados);
   write('TotalXjornada');
   gotoxy(28,24+maxempleados);
     for j:=1 to maxdias do
     begin
       convertir_A_militar_jornadas(sumasXjornada,j,t);
       write(t.hh:2,':',t.mm:2);
       write(' ':5);
       end;

Que puedo hacer para que me salga ok,mil gracias por tu valiosa ayuda y tu tiempo.



06-Jul-2011 20:03
oscar gomez


Perdoma profesor este es el ultimo codigo no el anterior:

gotoxy(22,6);
 writeln('*** INFORME DE DATOS Y RESULTADOS ***');
 writeln;
 gotoxy(58,14);
 writeln('total tiempo por');
 gotoxy(10,15);
 writeln('Codigo            Dia1      Dia2      Dia3          empleado ');
 gotoxy(10,16);
 write('-------           ----      ----      ----      ----------------- ');

 for i:=1 to maxempleados  do
   begin
     gotoxy(10,16+i);
     write(empleados[i].codigo,' ');
     gotoxy(28,16+i);
      for j:=1 to maxdias do
        begin
          write(empleados[i].horas[j].hh,':');
          write(empleados[i].horas[j].mm);
          write(' ':7);

        end;
        convertir_A_militar(sumaminutosXempleado,i,t);
        gotoxy(63,16+i);
       write(t.hh:2,':',t.mm:2);
       writeln;
    end;
    gotoxy(28,19+maxempleados);
    write('----      ----      ----');
   gotoxy(10,20+maxempleados);
   write('TotalXjornada');
   gotoxy(28,20+maxempleados);
   for j:=1 to maxdias do
    begin
     convertir_A_militar_jornadas(sumasXjornada,j,t);
     write(t.hh:2,':',t.mm:2);
     write(' ':5);
    end;

bueno  el problema ocurre cuando solo digito minutos con una sola cifra porejemplo 8:0 en ves de 8:00, o 16:30 en vez de porejemplo 9:45. Como puedo validar para obligar al usuario a que me digite tanto las horas y minutos estrictamente con dos cifras respectivamente? y no de a una, para que no se me desface la tabla en los resultados de ejecucion?, aunque tambien intente probar con un gotoxy en la parte que te pongo los *** pero no fui capaz ,intentando que cada vez que lea un tiempo sea con una o dos cifras en su horas o minutos salte siempre a la misma columna cuando cambie de empleado(fila).

intente enviarte una captura de ejecucion para que lo pudieras ver pero ni en .zip me permitio enviartelo, incluso ni en un mensaje solo con asunto, pues el tamaño comprimido me da 12k y tu solo permites 10k, como puedo hacer para enviartelo o si con lo que te explique es suficiente, mil gracia Nacho.



07-Jul-2011 12:22
Nacho Cabanes (+32)

La solución elegante y amigable no es obligar al usuario a teclear con dos cifras, sino filtrarlo tú posteriormente.

Basta con usar "WriteLn(dato:2)" si quieres que se rellene con espacios (que no es lo habitual), o bien crearte un procedimiento que escriba en pantalla un número, y ponga antes un cero si el número es menor de 10:

procedure Escribir2cifras(var num: integer);
begin
 if (num < 10) Write('0');
 write(num);
end;


07-Jul-2011 17:04
oscar gomez

Hola nacho.

lo del procedimiento que me indicas no es quiza la solucion por que imaginate que te escriban una hora como las 8:35 en vez de las
08:35 o porejemplo esto otro, 8:5, segun el procedimiento que me planteas quedaria las 8:50 ,que realmente no seria, pues el usuario imaginate que quiere es las 8 y 5 minutos, es decir 8:05, como vez el cero que pones es con un write y por lo tanto se ubicaria es a la derecha del numero que se haya tomado tanto para hora o minutos;
como podria ser entonces dicho procedimiento?


gracias


07-Jul-2011 17:09
oscar gomez

ah bueno seria cambiar la posicion del write('0') verdad? es decir,
si es para las 08:35 porejemplo,entonces seria

...
write('0');
write(num);

o si fuese porejemplo para el caso de minutos como ,las 8:05, lo mismo solo que en la escritura de los minutos, supongo , o por favor corrigeme si no es correcta mi apreciacion.


07-Jul-2011 18:18
oscar gomez

Gracias profesor por tu ayuda, solucionado lo de mostrar siempre en formato hh:mm, es decir con dos cifras tanto para hora como minutos.






(No se puede continuar esta discusión porque tiene más de dos meses de antigüedad. Si tienes dudas parecidas, abre un nuevo hilo.)