Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 20-07-2006
Avatar de kuan-yiu
[kuan-yiu] kuan-yiu is offline
Miembro Premium
 
Registrado: jun 2006
Ubicación: Galicia. España.
Posts: 1.017
Poder: 19
kuan-yiu Va camino a la fama
Cool Optimizar comparación de fechas

El título puede no ser del todo exacto, pero no se me ocurría otro mejor. Gracias de antemano a todos.
Es una cuestión algo tonta: me he planteado si lo estaré haciendo de un modo óptimo o por lo menos mínimo.

El problema:
Tengo que comparar 4 fechas más o menos lo que quiero saber es:
Cita:
fecha_creacion<=fecha_aprobacion<=fecha_emision_f_ant<=fecha_emision_f
Si esta comparación no se cumple no puedo dejar grabar los cambios.

Problema, los datos se obtienen de una consulta, están en DBEdits y algunos pueden llegar en blanco, y ese es el problema. Tengo un pequeño monstruo de if-else anidados para asegurarme de que no comparo cuando llegan en blanco y sí cuando tienen datos... que no me acaba de convencer.
Código Delphi [-]
function fechasValidas: Boolean;
begin
// fecha_creacion siempre tiene algún valor.
  if (fecha_aprobacion.Text<>'') then
  begin
  // fecha_aprobacion tiene algún valor
    result := StrToDate(fecha_creacion.Text)<=StrToDate(fecha_aprobacion.Text);
    if (result=FALSE) then
      exit;
    if (fecha_emision_f_ant.Text<>'') then
    begin
    // fecha_emision_f_ant tiene algún valor
      result := (StrToDate(fecha_aprobacion.Text)<=StrToDate(fecha_emision_f_ant.Text));
      if (result=FALSE) then
        exit;
      if (fecha_emision_f.Text<>'') then
        result := (StrToDate(fecha_emision_f_ant.Text)<=StrToDate(fecha_emision_f.Text));
    end
    else
    begin
    // fecha_emision_f_ant no tiene datos
      result := StrToDate(fecha_creacion.Text)<=StrToDate(fecha_aprobacion.Text);
      if (result=FALSE) then
        exit;
      if (fecha_emision_f.Text<>'') then
        result := (StrToDate(fecha_aprobacion.Text)<=StrToDate(fecha_emision_f.Text));
    end;
  end
  else
  // fecha_aprobacion no tiene datos, por lo que el resto tampoco pueden tenerlos.
    result := TRUE;
end;

Peculiaridades:
fecha_creacion: nunca llega en blanco.
fecha_aprobacion: si no existe las otras dos (fecha_emision_f_ant y fecha_emision_f) tampoco.


PD: Me ha costado escribir todo esto... creo que me voy a tomar una galleta para recuperarme .
Responder Con Cita
  #2  
Antiguo 20-07-2006
Avatar de delphi.com.ar
delphi.com.ar delphi.com.ar is offline
Federico Firenze
 
Registrado: may 2003
Ubicación: Buenos Aires, Argentina *
Posts: 5.932
Poder: 27
delphi.com.ar Va por buen camino
Si quieres optimizar el código para menor uso de procesador, yo evitaría convertir un string a un TDate para cada comparación. O a lo sumo excluír en en las primeras líneas las comparaciones que serán mas comunes!

Por otro lado, líneas como esta:
Código Delphi [-]
   result := StrToDate(fecha_creacion.Text)<=StrToDate(fecha_aprobacion.Text);
   if (result=FALSE) then
     exit;
no es lo mismo que esto? :
Código Delphi [-]
   if not StrToDate(fecha_creacion.Text)<=StrToDate(fecha_aprobacion.Text) then
     exit;
Yo personalmente prefiero evitar los Exit intentando que la lógica te lleve a la salida

Saludos!
__________________
delphi.com.ar

Dedique el tiempo suficiente para formular su pregunta si pretende que alguien dedique su tiempo en contestarla.

Última edición por delphi.com.ar fecha: 20-07-2006 a las 23:50:34.
Responder Con Cita
  #3  
Antiguo 21-07-2006
Avatar de Ñuño Martínez
Ñuño Martínez Ñuño Martínez is offline
Moderador
 
Registrado: jul 2006
Ubicación: Ciudad Catedral, Españistán
Posts: 6.000
Poder: 25
Ñuño Martínez Tiene un aura espectacularÑuño Martínez Tiene un aura espectacular
A raíz del último comentario, una forma de optimizar podría ser:
Código Delphi [-]
FUNCTON Comprobar: BOOLEAN;
 BEGIN
   Result := FALSE;
   IF A = B THEN
   BEGIN
     IF B = C THEN
       Result := TRUE;
   END;
 END;

Como ves, Result sólo se asigna en dos puntos y la propia lógica "te lleva fuera". Además reduces en operaciones ya que no tienes que hacer:

Código Delphi [-]
      result := StrToDate(fecha_creacion.Text)<=StrToDate(fecha_aprobacion.Text);
       if (result=FALSE) then ...
Responder Con Cita
  #4  
Antiguo 21-07-2006
Mick Mick is offline
Miembro
 
Registrado: may 2003
Posts: 405
Poder: 22
Mick Va por buen camino
Yo seguramente haria algo como:

Código:
function fechasValidas: Boolean;
var
 f1,f2,f3,f4: TDateTime;
begin
    f1:= StrToDateDef(fecha_creacion.text       ,MaxDouble);
    f2:= StrToDateDef(fecha_aprovacion.text    ,MaxDouble);
    f3:= StrToDateDef(fecha_emision_f_ant.text,MaxDouble);
    f4:= StrToDateDef(fecha_emision_f.text      ,MaxDouble);
    Result:= (f1<=f2) and (f2<=f3) and (f3<=f4);
end;
Aunque se podria optimizar, creo que en este caso no valdria la pena ya
que el codigo quedaria mucho mas enrevesado, y salvo que haya que llamar
miles de veces por segundo a esa funcion, la velocidad de ejecucion sera suficiente.

Saludos
Responder Con Cita
  #5  
Antiguo 21-07-2006
Avatar de kuan-yiu
[kuan-yiu] kuan-yiu is offline
Miembro Premium
 
Registrado: jun 2006
Ubicación: Galicia. España.
Posts: 1.017
Poder: 19
kuan-yiu Va camino a la fama
Antes de nada gracias a todos por vuestros comentarios
Por partes:

delphi.com.ar
He puesto los exit porque antes lo tenía todo con if-else y era múchísimo más grande y lioso, a mi entender, y en un caso como este no creo que sea un mal uso, y eso que a mi tampoco me gusta emplearlos.
Creo que es buena idea lo de hacer las transformaciones una única vez, al principio y luego usar directamente esos valores.

Ñuño Martínez
En el caso que pones no estás considerando las fechas nulas, que siempre deben ignorarse de la lógica de las comparaciones, por lo que ese sistema no me sirve en este caso concreto.
Quizá usar result una única vez sea lo mejor (lo tenía así al principio y en su lugar usaba una variable temporal).

Mick
Igualmente no estás considerando las fechas nulas que darían falsos negativos.
Y creo que definitivamente voy a hacer las transformaciones a "TDate" al principio.
Responder Con Cita
  #6  
Antiguo 21-07-2006
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 29
Lepe Va por buen camino
De todas las respuestas dadas, la que más me gusta es la de Mick, de hecho, yo haría algo así:
Código Delphi [-]
function fechasValidas: Boolean;
var
 creacion, aprobacion, emision_ant, emision_f: TDateTime;
begin
    creacion   := StrToDateDef(fecha_creacion.text       ,MaxDouble);
    aprobacion := StrToDateDef(fecha_aprovacion.text    ,MaxDouble);
    emision_ant:= StrToDateDef(fecha_emision_f_ant.text,MaxDouble);
    emision_f  := StrToDateDef(fecha_emision_f.text      ,MaxDouble);

    Result := aprobacion <> maxdouble;
    result := result and creacion <= aprobacion;

    if emision_ant <> maxdouble then
    begin

      result := result and aprobacion <= emision_ant;
      if emision_f <> maxdouble then
        result := result and emision_ant <= emision_f
    end;
    else
    begin
      result := result and creacion <= aprobacion;
      if emision_f <> maxdouble then
        result := result and aprobacion <= emision_F
    end;

end;
Si delphi tiene desactivada la directiva "Complete Boolean evaluation" (por defecto creo que sí en Tools --> enviroment), las comparaciones serían tremendamente efectivas.

El punto es usar Result una y otra vez y siempre como primera condición de comparación, si ya es false, Delphi detecta que está unida la comparación con un "and" y no evalúa la condición de la derecha del "and", directamente devuelve falso.

Creo que las comparaciones están correctas.

Saludos
__________________
Si usted entendió mi comentario, contácteme y gustosamente,
se lo volveré a explicar hasta que no lo entienda, Gracias.

Última edición por Lepe fecha: 21-07-2006 a las 10:31:45.
Responder Con Cita
  #7  
Antiguo 21-07-2006
Avatar de kuan-yiu
[kuan-yiu] kuan-yiu is offline
Miembro Premium
 
Registrado: jun 2006
Ubicación: Galicia. España.
Posts: 1.017
Poder: 19
kuan-yiu Va camino a la fama
Que curioso, acabo de hacer una segunda versión de la función que toma detalles que todos me habéis indicado y que se parece mucho a la tuya Lepe
Código Delphi [-]
{ Compara las fechas para asegurar que no son incongruentes entre si. }
function TfEditPpto.fechasValidas: Boolean;
var
  fec1,fec2,fec3, fec4: TDateTime;
  condi: Boolean;
begin
// Primero se transforman todos los datos.
  fec1 := StrToDateDef(fecha_creacion.Text, 0);
  fec2 := StrToDateDef(fecha_aprobacion.Text, 0);
  fec3 := StrToDateDef(fecha_emision_f_ant.Text, 0);
  fec4 := StrToDateDef(fecha_emision_f.Text, 0);
// Determina si las fechas son válidas.
  condi := TRUE;
  if (fec2>0) then
    condi := condi and (fec1<=fec2);
  if (fec3>0) then
  begin
    condi := condi and (fec2<=fec3);
    if (fec4>0) then
      condi := condi and (fec3<=fec4);
  end
  else
    if (fec4>0) then
      condi := condi and (fec2<=fec4);
  result := condi;
end;
Esta ya me gusta más, ¡¡MUCHAS GRACIAS A TODOS!!
Responder Con Cita
  #8  
Antiguo 21-07-2006
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 29
Lepe Va por buen camino
Si... pero en la mia uso variables más descriptivas y me ahorro la Booleana

Saludos
__________________
Si usted entendió mi comentario, contácteme y gustosamente,
se lo volveré a explicar hasta que no lo entienda, Gracias.

Última edición por Lepe fecha: 21-07-2006 a las 18:48:44.
Responder Con Cita
  #9  
Antiguo 21-07-2006
Mick Mick is offline
Miembro
 
Registrado: may 2003
Posts: 405
Poder: 22
Mick Va por buen camino
El codigo que he puesto si tiene en cuenta las fechas nulas.
Precisamente por eso se usa un StrToIntDef con valor por defecto MaxDouble, simplemente esta hecho asi a proposito para ahorrarnos los IFs posteriores. Es decir el uso de MaxDouble en los STrToIntDef hace que no sea necesario poner ningun IF posterior de comprobacion. Porque esos IFS estan implicitos en la comparacion final:

Result:= (f1<=f2) and (f2<=f3) and (f3<=f4);

Si las fecha es nula el strtointdef da error y devuelve MaxDouble de modo que las comparaciones posteriores dan el resultado correcto (por lo menos el mismo que el codigo inicial que se ha puesto).

Saludos
Responder Con Cita
  #10  
Antiguo 26-07-2006
Avatar de kuan-yiu
[kuan-yiu] kuan-yiu is offline
Miembro Premium
 
Registrado: jun 2006
Ubicación: Galicia. España.
Posts: 1.017
Poder: 19
kuan-yiu Va camino a la fama
Que cosas... entonces "MaxDouble" es una constante definida en alguna unidad, ¿en cual? No la conocía.
Responder Con Cita
  #11  
Antiguo 26-07-2006
Avatar de delphi.com.ar
delphi.com.ar delphi.com.ar is offline
Federico Firenze
 
Registrado: may 2003
Ubicación: Buenos Aires, Argentina *
Posts: 5.932
Poder: 27
delphi.com.ar Va por buen camino
Cita:
Empezado por kuan-yiu
Que cosas... entonces "MaxDouble" es una constante definida en alguna unidad, ¿en cual? No la conocía.
Unit Math!
__________________
delphi.com.ar

Dedique el tiempo suficiente para formular su pregunta si pretende que alguien dedique su tiempo en contestarla.
Responder Con Cita
  #12  
Antiguo 27-07-2006
Avatar de kuan-yiu
[kuan-yiu] kuan-yiu is offline
Miembro Premium
 
Registrado: jun 2006
Ubicación: Galicia. España.
Posts: 1.017
Poder: 19
kuan-yiu Va camino a la fama
Cita:
Empezado por delphi.com.ar
Unit Math!
Gracias
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Optimizar con Case XXX of TIKIMORE Varios 9 10-07-2010 17:21:20
comparación de fechas Nelly Varios 2 27-10-2005 17:30:42
Comparación de Fechas sierraja Varios 5 19-06-2005 06:56:20
Optimizar Vistas repo Firebird e Interbase 1 02-03-2005 18:13:43
Optimizar Paradox en red Sick boy Conexión con bases de datos 0 26-02-2005 13:31:48


La franja horaria es GMT +2. Ahora son las 14:07:59.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi