Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Firebird e Interbase (https://www.clubdelphi.com/foros/forumdisplay.php?f=19)
-   -   Tratamiento de fechas en Firebird (https://www.clubdelphi.com/foros/showthread.php?t=82025)

santiago14 16-01-2013 23:17:56

Tratamiento de fechas en Firebird
 
Creo que puse este Post en el lugar incorrecto, pido por favor a algún moderador que lo mueva a su lugar correspondiente.

Bueno, resulta que quiero traer un campo de tipo fecha desde Firebdir 2.1 hacia mi formulario., hago lo siguiente

Código SQL [-]
Select IIF(e.fecha >= '2011/12/31', 'Fecha es mayor a 2011', e.fecha)'
From tabla e

El caso es que cuando me tiene que devolver la fecha (o sea que e.fecha < 2011/12/31 --> lo pongo de la forma aaaa/mm/dd porque es la única forma que Firebird me hace la comparativa correctamente), lo hace de la siguiente manera: 2009-10-30; yo quiero que me lo devuelva de la forma: 30/10/2009 que es como el usuario lo cargó en la BD y como figura en las tablas.

Bueno, esto me está causando un problema, ¿alguien sabe la manera de arreglarlo para que Firebird me devuelva bien las fechas?

Gracias, Santiago.

santiago14 16-01-2013 23:34:06

Encontré una forma, aunque poco elegante a mi entender, funciona muy bien.
Código SQL [-]
Select IIF(e.fecha >= '2011/12/31', 'Fecha mayor a 2011',
EXTRACT(DAY FROM e.fecha | '/' | EXTRACT(MONTH FROM e.fecha | '/' | EXTRACT(YEAR FROM e.fecha)) AS FECHA

Esto está muy bien, pero el problema sigue cuando hago un LIST() de fechas, me las muestra al revés....

Santiago.

Al González 16-01-2013 23:40:18

Esa fecha está bien. Es una fecha en formato ISO. :)

Otra cosa es como quiera uno que se muestre en la pantalla. Por ello la siguiente pregunta: ¿esa consulta la tienes asociada a un conjunto de datos, cuyo campo de fecha (el resultado de la consulta) muestras en algún formulario?

¿Qué razón hay para hacer trabajar al servidor (y a la conexión de red) encargándole devolver la cadena 'Fecha es mayor a 2011'? Quizá una mejor idea sería emplear un campo fecha normal y usar en Delphi su evento OnGetText para condicionar qué es lo que debe mostrar o cómo debe mostrarlo.

Saludos.

santiago14 17-01-2013 00:33:28

Cita:

Empezado por Al González (Mensaje 453541)
Esa fecha está bien. Es una fecha en formato ISO. :)

Otra cosa es como quiera uno que se muestre en la pantalla. Por ello la siguiente pregunta: ¿esa consulta la tienes asociada a un conjunto de datos, cuyo campo de fecha (el resultado de la consulta) muestras en algún formulario?

¿Qué razón hay para hacer trabajar al servidor (y a la conexión de red) encargándole devolver la cadena 'Fecha es mayor a 2011'? Quizá una mejor idea sería emplear un campo fecha normal y usar en Delphi su evento OnGetText para condicionar qué es lo que debe mostrar o cómo debe mostrarlo.

Saludos.

Estoy de acuerdo, pero no del todo, el Select lo puse así a modo de ejemplo porque en realidad el problema era que no podía ver la fecha en un formato en el cual la habían cargado.
Igualmente, usando EXTRACT se arregla.

En este caso, la consulta se hace a través de un MDOQuery y luego la mando a una grilla para que se puedan ver los datos.
Gracias.

Al González 17-01-2013 00:44:17

Cita:

Empezado por santiago14 (Mensaje 453546)
[...] en realidad el problema era que no podía ver la fecha en un formato en el cual la habían cargado [...] la consulta se hace a través de un MDOQuery y luego la mando a una rejilla para que se puedan ver los datos

Considera que en la mayoría de los motores de bases de datos, como es el caso de Firebird, las fechas no se guardan tal como el texto que fue capturado. Una fecha se guarda en formato binario y a la hora de presentarla a un humano puede emplearse uno de muchos formatos posibles (día/mes/año, mes/día/año, año/mes/día, año-mes-día, etcétera).

Si el problema es entonces de mera presentación, tan sólo basta que le indiques al campo, a través de su propiedad DisplayFormat, el formato que debe usar, por ejemplo: dd/mm/yyyy. Lo más fácil es hacerlo con el inspector de objetos, y también se puede por código:
Código Delphi [-]
ObjetoCampo.DisplayFormat := 'dd/mm/yyyy';

Espero haberme explicado. :)

santiago14 17-01-2013 01:17:54

Exacto, ahora sí.
Les comento como me fue cuando haga las pruebas pertinentes.

Gracias, Santiago.

RONPABLO 17-01-2013 06:37:48

El problema radica en la forma como trata el mensaje:

Código SQL [-]
Select IIF(e.fecha >= '2011/12/31', , e.fecha)' From tabla e

Ahí se maneja un solo tipo de dato, firebird en ese IIF hace un cast sobre "e.fecha" y lo regresa como varchar ya que el texto 'Fecha es mayor a 2011' no lo puede tratar como tipo fecha,así pues al dar displayFormat a el texto creo que sacará una excepción...

Al González 17-01-2013 15:44:02

Cita:

Empezado por RONPABLO (Mensaje 453559)
[...] lo regresa como varchar ya que el texto 'Fecha es mayor a 2011' no lo puede tratar como tipo fecha,así pues al dar displayFormat a el texto creo que sacará una excepción...

Claro, pero la sugerencia de usar DisplayFormat es con un campo de fecha normal, a raíz de que Santiago dijera que se trataba más bien de una cuestión de formato / presentación. :)

santiago14 28-01-2013 02:03:44

1 Archivos Adjunto(s)
Bueno, siguiendo con el tema, les mando una consulta en la cual muestro una lista de fechas armada con LIST.
Los resultados salen de la forma: aaaa-mm-dd, yo quisiera que salgan de la forma dd-mm-aaaa, pueden ver el resultado en el .jpg adjunto.

Gracias, Santiago.

Código SQL [-]
Select s.fecha_sumario, LPAD(s.nro_op, 9, '0') AS nro_op,
LPAD(ec.pto_vta_fact, 4, '0') || ' - ' || LPAD(ec.nro_fact, 8, '0') AS nro_factura,
ts.nombre_tit,
(Select LIST(fs.fecha_sumario, ', ')
From fechas_sumario fs
Where fs.nro_op = s.nro_op) AS fechas_sumarios
From sumarios s, enc_factura ec, titulos_sec ts
Where s.cod_fact = ec.cod_factura
and s.cod_sec = ts.cod_sec
and s.renglon_tit = ts.renglon_tit
and CAST(s.fecha_sumario AS DATE) BETWEEN '01/01/2011' AND '12/31/2011'
and ec.cod_sucursal = 1

La verdad es que encuentro inquietante no poder configurar la salida de las fechas a la manera que yo necesite.

Santiago.

santiago14 28-01-2013 02:26:00

1 Archivos Adjunto(s)
Acabo de encontrar una forma, está buena...

Código SQL [-]
Select s.fecha_sumario, LPAD(s.nro_op, 9, '0') AS nro_op,
LPAD(ec.pto_vta_fact, 4, '0') || ' - ' || LPAD(ec.nro_fact, 8, '0') AS nro_factura,
ts.nombre_tit,
(Select LIST(LPAD(EXTRACT(DAY FROM fs.fecha_sumario), 2, '0') || '/' ||
      LPAD(EXTRACT(MONTH FROM fs.fecha_sumario), 2, '0') || '/' ||
      LPAD(EXTRACT(YEAR FROM fs.fecha_sumario), 4, '0'), ', ')
From fechas_sumario fs
Where fs.nro_op = s.nro_op) AS fechas_sumarios
From sumarios s, enc_factura ec, titulos_sec ts
Where s.cod_fact = ec.cod_factura
and s.cod_sec = ts.cod_sec
and s.renglon_tit = ts.renglon_tit
and CAST(s.fecha_sumario AS DATE) BETWEEN '01/01/2011' AND '12/31/2011'
and ec.cod_sucursal = 1

Con esto se me soluciona un drama, por lo menos en el LIST, bastante grande. Todos mis clientes me andan reclamando que tienen que "mirar la fecha de atrás para adelante". Envío el adjunto con el resultado.

Gracias a todos por su atención.

Santiago.

Delphius 28-01-2013 09:20:16

Pero es que eso se soluciona muy fácil con la propiedad DisplayFormat tal como te lo han recomendado antes. Se ve que no has prestado atención al hilo.

En como interprete internamente las fechas firebird déjalos a los componentes, que bien saben hacer su trabajo. Ese esfuerzo inútil en hacer una consulta para "armar" la fecha como gustas se puede ahorrar.
Tu error está en concebir que las fechas se ingresan a tu forma. No... cada motor tiene la propia y si no la respetas allí tu.
Es por eso que los componentes ya disponen de las funcionalidades para solventar todo esto. Por ejemplo, quieres pasar una fecha pues basta con un:

Código Delphi [-]
MiDataSet.FieldByName('CampoFechaHora').asDateTime := MiFechaHora;

Siendo MiFechaHora una variable del tipo TDateTime, o si quieres algo directo le puedes pasar desde un TDtateTimePicker por ejemplo:

Código Delphi [-]
MiDataSet.FieldByName('CampoFechaHora').asDateTime := MiDTP.DateTime;

Ahora no interesa el formato de presentación que tengas... si es mm/dd/yyyy o yyyy/aa/mm o el que fuese. Los componentes se encargan del trabajo sucio y traducen este formato al interno que espera la base de datos.

A la inversa, al momento de presentar o leer los datos hay varias posibilidades de como encararlo. Puedes aprovechar el evento OnGetText o más fácil aún la propiedad DisplayFormat.

También esto aplica a los parámetros. En tu consulta se ve en el where un Between. ¡Pasa los datos como parámetros!

Código SQL [-]
BETWEEN :Fecha1 AND :Fecha2

Luego en tus parámetros les asignas los valores. Los parámetros harán el trabajo sucio y al final traduciran al formato adecuado que interprete Firebird.

Y si dicha evaluación con las fechas será fija, aprende y comprende que debes ceñirte al formato interno (que en el caso de Firebird es: dd.mm.yyyy hh:mm:ss.nnnn) en lo más posible ya que no obligas al motor que interprete, o mejor dicho intente, reconocer si lo escrito cumple con alguno de los formatos (véase la tabla 10-2) que es capaz de aceptar ya que con eso pierdes tiempo.

Esa consulta tarde o temprano será lentísima.
Ha decir verdad no se comprende ni hay una razón fundada que te impida seguir las recomendaciones que te han dado. No me queda otra explicación más que tu ignorancia sobre el tema y el desconocimiento, y asombro de tu parte, al notar el porqué firebird guarda "una fecha extraña" y en una cerradez de que "debe almacenar siempre como y lo que ingreso". No sabía que los campos de un motor de base de datos deban ser WYSIWYG. :rolleyes: ¿O acaso tienes alguna explicación al respecto?

Saludos,

santiago14 28-01-2013 13:00:20

Cita:

Y si dicha evaluación con las fechas será fija, aprende y comprende que debes ceñirte al formato interno (que en el caso de Firebird es: dd.mm.yyyy hh:mm:ss.nnnn) en lo más posible ya que no obligas al motor que interprete, o mejor dicho intente, reconocer si lo escrito cumple con alguno de los formatos (véase la tabla 10-2) que es capaz de aceptar ya que con eso pierdes tiempo.
La evaluación no será con fechas fijas, uso los parámetros. Nuevamente fue para que la cosa se graficara mejor.

Cita:

Esa consulta tarde o temprano será lentísima.
Ha decir verdad no se comprende ni hay una razón fundada que te impida seguir las recomendaciones que te han dado. No me queda otra explicación más que tu ignorancia sobre el tema y el desconocimiento, y asombro de tu parte, al notar el porqué firebird guarda "una fecha extraña" y en una cerradez de que "debe almacenar siempre como y lo que ingreso". No sabía que los campos de un motor de base de datos deban ser WYSIWYG. :rolleyes: ¿O acaso tienes alguna explicación al respecto?

Saludos,
Estoy de acuerdo, por ello es que estoy buscando algo que me ayude a optimizarla. Lo de "fecha extraña" lo puse para que fuera mas gráfico el ejemplo y lo que buscaba, yo se, al igual que uds., que Firebird o cualquier motor guarda sus fecha en un formato adecuado.


Estoy probando el asunto de DisplayFormat, gracias nuevamente.

Un saludo Delphius, desde Salta a otro salteño.

Santiago.

RONPABLO 28-01-2013 16:14:40

El displayFormat tampoco funcionará en esta consulta, ya que el list manda una cadena de texto, en este caso una o más de una fecha separada por comas, o mejor dicho, sí hay una sola fecha se podría tratar el dato como tipo Date y Delphi se encargaría solito de darle el formato según el PC en que se ejecute, pero acá no va a pasar eso ya que existe la pocibilidad (muy alta creo yo) de tener varias fechas sumario, por lo cual el que se encarga de hacer el cast de el campo tipo Date a varchar es Firebird y por lo tanto mandara un texto ordenado por año, mes día separado por guiones... sería bueno ver si Firebird tiene algo similar al DisplayFormat de Delphi aunque en el FAQ recomiendan hacer algo muy similar a extract

santiago14 28-01-2013 18:04:09

Cita:

Empezado por RONPABLO (Mensaje 454123)
El displayFormat tampoco funcionará en esta consulta, ya que el list manda una cadena de texto, en este caso una o más de una fecha separada por comas, o mejor dicho, sí hay una sola fecha se podría tratar el dato como tipo Date y Delphi se encargaría solito de darle el formato según el PC en que se ejecute, pero acá no va a pasar eso ya que existe la pocibilidad (muy alta creo yo) de tener varias fechas sumario, por lo cual el que se encarga de hacer el cast de el campo tipo Date a varchar es Firebird y por lo tanto mandara un texto ordenado por año, mes día separado por guiones... sería bueno ver si Firebird tiene algo similar al DisplayFormat de Delphi aunque en el FAQ recomiendan hacer algo muy similar a extract

En este caso la consulta que puse mas arriba está mas o menos bien encaminada...
Tengo varios casos en donde debo presentar una lista de fechas.

Santiago.


La franja horaria es GMT +2. Ahora son las 12:21:20.

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