IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SQL Firebird Discussion :

conversion date depuis format unix


Sujet :

SQL Firebird

  1. #1
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2012
    Messages
    114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 114
    Points : 70
    Points
    70
    Par défaut conversion date depuis format unix
    Bonjour,

    Je dois convertir des dates stockées sous format unix en date, j'utilise la requête suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    WITH CTE AS (SELECT id, champs_date_unix FROM ma_table WHERE champs_date_unix >= 0
    UNION ALL
    SELECT id, (champs_date_unix + 999999999999999999) * -1 FROM ma_table WHERE champs_date_unix < 0)
    SELECT id , DATEADD(SECOND, champs_date_unix, CAST('1970:01:01' AS DATE)) FROM CTE
    Tout se passe bien sauf pour les dates très lointaines (exemple 31/12/1899 qui est stocké -999999997790924799), ou j'ai un message: arithmetic exception, numeric overflow, or string truncation numeric value is ot of range. Le nombre de secondes à retirées est trop grand.

    Avez-vous une solution, même s'il faut utiliser une autre table?
    Merci

  2. #2
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2012
    Messages
    114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 114
    Points : 70
    Points
    70
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT id, DATEADD(DAY, champ_date_unix/3600/24, CAST('1970:01:01' AS DATE))
    Semble fonctionner

  3. #3
    Membre expert
    Avatar de Barbibulle
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    2 048
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 2 048
    Points : 3 342
    Points
    3 342
    Par défaut
    Bonjour,

    Effectivement on dirait qu'il y a un dépassement de capacité dans la fonction DATEADD.

    Ca ressemble à un bug...


    Citation Envoyé par r038tmp5 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT id, DATEADD(DAY, champ_date_unix/3600/24, CAST('1970:01:01' AS DATE))
    Semble fonctionner

    En faisant ça vous perdez en précision, du moins si ce sont des timestamp, mais si vous ne traitez que des dates sans composante time, ça devrait le faire.

    Sinon on doit pouvoir contourner avec une procédure / execute block.

  4. #4
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2012
    Messages
    114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 114
    Points : 70
    Points
    70
    Par défaut
    J'ai juste besoin de la date

  5. #5
    Membre expert
    Avatar de Barbibulle
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    2 048
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 2 048
    Points : 3 342
    Points
    3 342
    Par défaut
    Sinon si on veut un timestamp avec toute la précision on doit pouvoir faire quelque chose du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    WITH CTE AS (SELECT id, champs_date_unix FROM ma_table WHERE champs_date_unix >= 0
    UNION ALL
    SELECT id, (champs_date_unix + 999999999999999999) * -1 FROM ma_table WHERE champs_date_unix < 0)
    SELECT id , DATEADD(SECOND, mod(champs_date_unix, 3600*24), DATEADD(DAY, champs_date_unix/3600/24, CAST('1970:01:01' AS timestamp))) FROM CTE

  6. #6
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2012
    Messages
    114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 114
    Points : 70
    Points
    70
    Par défaut
    Super, merci.
    Je vais la garder, je risque d'en avoir besoin un jour

  7. #7
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 380
    Points : 19 062
    Points
    19 062
    Par défaut
    Salut à tous.

    La représentation des dates sous unix pose quelques problèmes. Normalement, la plus petite date est le '1970/01/01 00:00:00' qui correspond à la valeur de stockage zéro.
    Et oui, sous Unix, une date contient aussi l'heure car le stockage s'exprime en seconde sous une représentation 32 bits signée mais uniquement en positif.
    Donc normalement l'amplitude va de +0 à +2.147.483.647 et la date maximale est le '2038/01/19 04:14:07'.
    Ceci est la norme Unix de la représentation d'une date et le stockage ne peut normalement pas être négatif.
    J'ai vérifié cela avec mon compilateur 'C' avec le format 'time_t'.

    Ceci n'est pas toujours respecté car parfois, on peut mettre un nombre négatif. C'est le cas en php !
    Si on met -2.147.483.647, la plus petite date donne : '1901-12-13 20:55:14'.
    Si vous utilisez une version php 64 bits, on peut outrepasser largement les contraintes du 32 bits ce qui est une nette amélioration de cette représentation des dates.

    Citation Envoyé par r038tmp5
    Tout se passe bien sauf pour les dates très lointaines (exemple 31/12/1899 qui est stocké -999999997790924799)
    Je ne sais pas d'où vous sortez ce nombre mais ce n'est pas ce que je trouve pour le '1899/12/31' : -2.209.075.761.
    J'ai extrait ce résultat à partir de ma version php '7.0.0RC6' la dernière version en date.
    Et je suppose que si vous dépassez allègrement le -2.147.483.647, c'est que vous êtes dans un représentation en 64 bits.
    Comment je le sais ? Et bien, j'ai utilisé sous php ceci : "$stamp = mktime(0, 0, 0, 12, 31, 1899);".

    Alors comment résoudre ce problème de conversion ?

    1) Et bien faire la conversion en php !
    Exemple : j'ai le nombre -2.209.075.761 et je sais que cela représente le '1899/12/31 00:00:00'.
    Pour la conversion, vous faites ceci, toujours en php : "date('Y-m-d H:i:s', $stamp)".
    Vous vous retrouvez avec une chaîne de caractères de ce format : '1899/12/31 00:00:00'.

    2) en FireBird, vous stockez cette chaîne de caractères sous le format char(19).
    Mais vous n'avez plus aucune possibilité de faire des opérations sous FireBird, genre un calcul de différence entre deux dates.
    Ceci devra automatiquement se faire en php.

    Juste une question : pourquoi avez-vous des dates en dehors de l'intervalle allant de '1970/01/01 00:00:00' à '2038/01/19 04:14:07' ?

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  8. #8
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2012
    Messages
    114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 114
    Points : 70
    Points
    70
    Par défaut
    Bonjour,

    On travaille sous Delphi.

    Après recherche dans le code, après la conversion au format unix, je vois que si la valeur est inférieur à 0, on fait: (999999999999999999 + valeur) x -1.
    La date est stockée dans un VARCHAR, et toujours sur 18 caractères et éventuellement le signe négatif.

    Dans la cadre de l'application, l'utilisateur peut saisir n'importe qu'elle date y compris des dates avant 1970.

  9. #9
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 134
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 134
    Points : 38 557
    Points
    38 557
    Billets dans le blog
    9
    Par défaut
    Citation Envoyé par r038tmp5 Voir le message
    La date est stockée dans un VARCHAR, et toujours sur 18 caractères et éventuellement le signe négatif.
    on se demande pourquoi les concepteurs de BDD prévoient des formats adaptés aux contenus, puisqu'il y a encore des personnes qui mettent tout dans du varchar
    Après tout, pourquoi faire des colonnes, on pourrait aussi tout concaténer dans un longvarchar...
    A votre place, j'irai personnellement tirer les oreilles du concepteur de ce gachis jusqu'à ce qu'il se décide à modéliser correctement la base !

  10. #10
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2012
    Messages
    114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 114
    Points : 70
    Points
    70
    Par défaut
    Une refonte de cette base est prévue pour corriger ce genre de problème, mais en attendant je m'adapte

  11. #11
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 380
    Points : 19 062
    Points
    19 062
    Par défaut
    Salut r038tmp5.

    Je reste convaincu que la mise en forme de votre date devrait se faire sous Delphi puisque c'est ce que vous utilisez, comme moi, mais sous php.

    Citation Envoyé par r038tmp5
    pour les dates très lointaines (exemple 31/12/1899)
    Vous ne m'avez pas répondu, en ce qui concerne le stockage de dates inférieures à 1970 ?
    Quel est l'usage que vous faites de ces dates ? Des calculs de différences ou juste des recherches d'égalités ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (champs_date_unix + 999999999999999999) * -1
    Quel est le type de la colonne 'champs_date_unix' ? Integer ? BigInt ?

    Est-ce que vous récupérez des dates depuis le système d'exploitation Unix (Linux) ?
    Je ne comprends pas l'intérêt de ce calcul. Pouvez-vous expliquer à quoi cela sert de procéder ainsi ?
    Soit vous utilisez la fonction abs() pour valeur absolue, mais cela ne résout en rien le problème.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  12. #12
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 038
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 038
    Points : 40 943
    Points
    40 943
    Billets dans le blog
    62
    Par défaut
    Bonsoir,

    @Artemus24 tu n'as pas lu que le champ en question était un varchar de longueur fixe = 18 partie soulignée qui me fait bien marrer et que escartefigue a carrément
    quoique il faudra m'expliquer le
    et toujours sur 18 caractères et éventuellement le signe négatif.
    du coup c'est un varchar(19)?

    il y a quand même une solution envisageable : faire une UDF, après tout vous avez les sources du programme qui enregistre les dates de cette manière disons peu conventionnelle, rien ne vous empêche de faire une petite dll pour encoder/decoder une date sous cette forme et de l'utiliser comme fonction (UDF) de Firebird
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  13. #13
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 380
    Points : 19 062
    Points
    19 062
    Par défaut
    salut à tous.

    @ SergioMaster : oui, je l'ai lu mais je n'avais pas compris qu'il s'agissait de la colonne 'champs_date_unix'.

    Citation Envoyé par r038tmp5
    (exemple 31/12/1899 qui est stocké -999999997790924799)
    J'aurai dû comprendre qu'il ne stocke pas la date (je parle de ceci : '1899/31/12 00:00:00' sur 19 caractères) comme je l'ai compris, mais de sa valeur numérique négative qui fait aussi 19 caractères.

    Merci pour la précision ! Oui, c'est du grand n'importe quoi.

    Citation Envoyé par SergioMaster
    il y a quand même une solution envisageable : faire une UDF, après tout vous avez les sources du programme qui enregistre les dates de cette manière disons peu conventionnelle, rien ne vous empêche de faire une petite dll pour encoder/décoder une date sous cette forme et de l'utiliser comme fonction (UDF) de Firebird
    Oui, je comprends très bien ton approche.
    Mais avant d'envisager quoi que ce soit, j'aimerai savoir l'usage qu'il va faire de la date sous forme de libellé (je parle de '1899/31/12 00:00:00').
    Je n'envisage pas un seul instant de stocker sa valeur numérique dans la base de données.

    Si c'est juste informationnelle, le libelle sous forme d'un char(19) est largement suffisant, puisque aucune opération de calcul ne sera fait dessus.
    On peut même envisager de l'éclater en une colonne 'date' et une colonne 'time'.

    Inversement, s'il envisage de faire des calculs dessus, cela ne pourra jamais fonctionner en FireBird, même en MySql d'ailleurs.
    C'est pourquoi, le stockage peut se faire sous FireBird, mais il devrai faire tous les calculs sous Delphi.

    Donc je n'ai pas compris l'intérêt de faire ceci sous FireBird :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    WITH CTE AS (SELECT id, champs_date_unix FROM ma_table WHERE champs_date_unix >= 0
    UNION ALL
    SELECT id, (champs_date_unix + 999999999999999999) * -1 FROM ma_table WHERE champs_date_unix < 0)
    SELECT id , DATEADD(SECOND, mod(champs_date_unix, 3600*24), DATEADD(DAY, champs_date_unix/3600/24, CAST('1970:01:01' AS timestamp))) FROM CTE
    Car selon moi, si le calcul se fait en Delphi, il n'y a aucun intérêt à faire cela en FireBird.

    La solution ne se trouve pas dans une quelconque astuce, mais dans le choix fonctionnel lié à la gestion de cette date.
    Sans plus d'information, il est difficile de se prononcer sur cette question.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  14. #14
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 038
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 038
    Points : 40 943
    Points
    40 943
    Billets dans le blog
    62
    Par défaut
    Bonjour,
    Citation Envoyé par Artemus24 Voir le message
    La solution ne se trouve pas dans une quelconque astuce, mais dans le choix fonctionnel lié à la gestion de cette date.
    on est d'accord, et r038tmp5 aussi puisque la structure de la base est remise en question

    si le calcul se fait en Delphi, il n'y a aucun intérêt à faire cela en FireBird.
    pas forcément, et c'est pour cela que je proposais l'utilisation d'une UDF (écrite en Delphi ou autre peut importe)
    1-l'algorithme de transformation est connu (du moins c'est ce qu'il me semble)
    2-imaginons que r038tmp5 ai besoin de faire une recherche sur la date dans cette future "ancienne base" avec la fonction UDF plus de difficulté

    Pour donner un exemple concret disons que j'ai besoin d'obtenir la valeur AnneeMois d'une date (normale ) je peux m'en sortir maintenant avec des extracts mais je peux aussi écrire une UDF qui va faire cela . A l'époque où j'ai écris cette fonction j'utilisai Interbase 5 les EXTRACTs n'existaient pas et les fonctions internes n'étaient pas légion, cette fonction me sert encore et fonctionne toujours aussi bien

    Code Pascal : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    unit timeFncs;
    interface
    uses sysutils,ibheader;
    ...
    function yearmonth(ib_date : PISC_QUAD) : integer; cedcl; export;
     
    implementation
    .....
    function yearmonth(ib_date : PISC_QUAD) : integer; 
    var tm_date : tm;
    begin
     isc_decode_date(ib_date,@tm_date);
     result:=(tm_date.tm_year+1900)*100+(tm_date.tm_month+1);
    end;
    end.
    il me suffit ensuite :
    1. de mettre la dll au bon endroit (répertoire <Firebird>\UDF)
    2. de la déclarer DECLARE EXTERNAL FUNCTION F_YEARMONTH Timestamp RETURNS Integer BY VALUE ENTRY_POINT 'YearMonth' MODULE_NAME 'nomdemadll.dll'

    ainsi je pourrai utiliser cette fonction F_YEARMONTH comme bon me semble, même pour un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT F_YEARMONTH(CAST('25.12.1889' AS TIMESTAMP)) FROM RDB$DATABASE
    pour obtenir 188912
    oui tu peux lever une objection qu'en est-il pour une date < JC, je doit avouer n'avoir jamais tenté d'ailleurs je ne sais même pas (au moment où j'écris ceci) comment indiquer une date avant JC
    [Edit] la question ne se pose plus :
    Valid dates are from January 1, 100 a.d. to February 29, 32768 a.d.
    ce qui est mieux que MS_SQL (January 1, 1753, to December 31, 9999) , MySQL ( '1000-01-01' to '9999-12-31') et même Oracle (à confirmer), reste qu'un archéologue de l'ancienne égypte voulant faire une bdd ne pourrait pas travailler avec le champ de type date

    Puisque r038tmp5 a le code Delphi de 'calcul/mise en forme' de la date cela devrait être assez facile de créer des fonctions de transformation (i.e. MADATEUNIX2DATE, DATE2MADATEUNIX) et ainsi de pouvoir l'utiliser très facilement
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  15. #15
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 380
    Points : 19 062
    Points
    19 062
    Par défaut
    Salut SergioMaster.

    Citation Envoyé par SergioMaster
    Citation Envoyé par Artemus24
    si le calcul se fait en Delphi, il n'y a aucun intérêt à faire cela en FireBird.
    pas forcément, et c'est pour cela que je proposais l'utilisation d'une UDF (écrite en Delphi ou autre peut importe)
    A moins de me tromper, quand j'utilise une 'UDF', c'est pour manipuler des données présentes sous FireBird.
    Or là, si j'ai bien compris, elles ne sont pas présentes sous FireBird, mais viennent d'un environnement Linux.
    Le but est de stocker une date (voir aussi un time) dans un format compréhensible sous FireBird.
    Je pense, mais vu que j'ignore totalement de la problématique que rencontre r038tmp5, qu'il serait plus judicieux de le traiter en Delphi, que sous FireBird.

    Et je reconnais qu'il peut exister plusieurs solutions à ce problème. Je ne dénigre personne, je cherche juste à mieux comprendre le problème.

    Citation Envoyé par SergioMaster
    1-l'algorithme de transformation est connu (du moins c'est ce qu'il me semble)
    Connu de ceux qui pratiques FireBird, or ce n'est pas mon cas.

    Citation Envoyé par SergioMaster
    2-imaginons que r038tmp5 ai besoin de faire une recherche sur la date dans cette future "ancienne base" avec la fonction UDF plus de difficulté
    Mais il n'y a jamais eu de problème pour faire une recherche. Il suffit de stocker la chaîne de caractères '1988/12/31 00:00:00' dans un type 'char' ou 'varchar'.
    Pourquoi la stocker sous une forme numérique ? Là, j'ai pas bien compris l'intérêt.

    Et la véritable problématique est de faire des calculs dessus. Par exemple, calculer une différence entre deux dates.
    Dans ce cas là, une UDF sera la bien venu car en dehors de l'intervalle '1970/01/01 00:00:00' jusqu'à '2038/01/19 04:14:07', je ne sais pas si FireBird est capable de gérer correctement les dates.
    Peux-tu me dire sous FireBird à quoi correspond l'intervalle valide des dates + times ?

    Citation Envoyé par SergioMaster
    ... ainsi je pourrai utiliser cette fonction F_YEARMONTH comme bon me semble, même pour un ...
    Ce que tu proposes ne me dérange nullement car tu as fait le choix du Delphi. Ce qui me dérange sous FireBird (ou n'importe quel autre SGBD), ce sont deux choses :

    --> stocker une valeur numérique et non le libellé de la date sous FireBird.
    J'entends par là, trouver une solution propre, en dehors des normes de FireBird.
    La valeur numérique n'est pas la bonne représentation d'une date. Le libellé l'est un peu plus, mais on ne peut pas faire des opérations dessus.

    Je tiens à préciser que sous gros système IBM, en Cobol, on gère les dates que sous la forme de libellé. Nous sommes obligé de créer les outils nécessaires pour faire des calculs.
    Mais la date est toujours stockées sous forme du libellé 'AAAAMMJJ' avec ou sans séparateur. On n'a pas de date pivot comme le cas avec '1970/01/01 00:00:00' dans le cas d'unix.

    Encore qu'au temps du bug de l'an 2000, il y avait des dates stockées sans les siècles. Il fallait faire un choix et quand on avait 'AA' < 70, on disait alors que 'SS' = '19 sinon '20'. On avait une amplitude de 100 ans, imposé justement par le stockage des années sous deux chiffres.

    --> traiter des calculs sur les dates, qui dans ce cas là, sont hors normes sous FireBird.
    Autrement dit, redéfinir des fonctions existantes car elles ne fonctionnent plus en dehors de l'intervalle officielle de gestion des dates sous FireBird.

    Citation Envoyé par SergioMaster
    oui tu peux lever une objection qu'en est-il pour une date < JC, je doit avouer n'avoir jamais tenté d'ailleurs je ne sais même pas (au moment où j'écris ceci) comment indiquer une date avant JC
    Je ne pose aucune objection votre honneur, car j'ai toujours travaillé dans le domaine bancaire.
    Donc une date inférieure à '1970/12/31' n'a aucun sens aujourd'hui.
    Dans les années '1980', cela pouvait avoir un sens car il y avait encore des rentes perpétuelles à 1%, dont la date d'émission datait d'après la seconde guerre mondiale
    Le problème d'aujourd'hui, c'est plutôt les dates d'échéances qui sont supérieures à '2038'.
    Je sais qu'il est temps de passer en 64 bits car ce problème de la limitation des dates est dû à la représentation 32 bits.

    Normalement, pour bien gérer les dates, cela devient vite une usine à gaz.
    Je ne parle même pas du calendrier julien et grégorien, mais plutôt des différents calendriers en vigueur dans le monde.

    Citation Envoyé par SergioMaster
    Puisque r038tmp5 a le code Delphi de 'calcul/mise en forme' de la date cela devrait être assez facile de créer des fonctions de transformation (i.e. MADATEUNIX2DATE, DATE2MADATEUNIX) et ainsi de pouvoir l'utiliser très facilement
    J'ai fait le test et comme lui, je me suis retrouvé avec une erreur d'overflow à l'exécution. Doit-on faire un cast pour résoudre ce problème ?

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  16. #16
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    245
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 245
    Points : 534
    Points
    534
    Par défaut
    Bonsoir,

    Avec Firebird, en dialecte 3, 3 types permettent de mémoriser la date et l'heure:
    DATE enregistre dans un mot de 32b une date comprise entre le 1 janvier 100 et le 29 février 32768
    TIME enregistre dans un mot de 32 bit une heure comprise entre 00:00 et 23:59:9999
    TIMESTAMP regroupe les deux dans un mot de 64b.
    La date/heure est saisie dans une requête sous forme littérale. Voir http://www.firebirdsql.org/en/firebird-date-literals/
    La doc dit que la date la plus ancienne est le 1/1/100 mais j'ai constaté qu'on pouvait entrer des dates du premier siècle en précédent l'année des "0" nécessaires pour avoir 3 caractères. Mais j'ignore l'exactitude des calculs sur ces années.
    Les fonctions internes EXTRACT, DATEADD, DATEDIFF permettent de faire des calculs certainement plus facilement que sur des chaînes.
    Quand à l'utilisation de fonctions UDF, je suis assez "mitigé", surtout maintenant que les fonctions internes ont été bien étendues.
    Tout d'abord, il me semble que les fonctions UDF ne peuvent avoir pour résultat qu'une seule valeur d'un type simple (pas de record par exemple).
    Ensuite l'installation d'une fonction UDF demande une installation dans les répertoires de Firebird lui-même, et il faut en prévoir une version (Windows, Linux) pour chaque système pouvant gérer votre base de données. Et rien ne garantit qu'une UDF développée par un autre prestataire ne rentrera pas en conflit avec la votre.
    J'ignore si c'est plus ou moins rapide, mais j'ai toujours préféré utiliser une procédure stockée dont le résultat peut être plus complexe.

    André

  17. #17
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 038
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 038
    Points : 40 943
    Points
    40 943
    Billets dans le blog
    62
    Par défaut
    A moins de me tromper, quand j'utilise une 'UDF', c'est pour manipuler des données présentes sous FireBird.
    Or là, si j'ai bien compris, elles ne sont pas présentes sous FireBird, mais viennent d'un environnement Linux.
    Le but est de stocker une date (voir aussi un time) dans un format compréhensible sous FireBird.
    Ne mélangeons pas tout : Delphi / Firebird etc....
    la problématique était de travailler sur une base existante , contenant un champ chaine de caractère, cette chaine étant en fait une date sous format UNIX
    (je ne reviendrai pas sur cette "bizarrerie") d'où venait cette date (système UNIX ou autre) comment elle était traité (apparemment via un programme Delphi), cela importe peu.

    le problème était traité ce champ varchar(19) existant comme une date , il y a donc la méthode procédure (Barbibulle) ou la méthode UDF (puisque ce n'est pas une transformation "classique")

    A moins de me tromper, quand j'utilise une 'UDF', c'est pour manipuler des données présentes sous FireBird.
    c'est bien le cas
    Or là, si j'ai bien compris, elles ne sont pas présentes sous FireBird, mais viennent d'un environnement Linux.
    Le but est de stocker une date (voir aussi un time) dans un format compréhensible sous FireBird.
    pas sûr, c'est le programme (Delphi en l’occurrence mais cela aurait put être PHP, C etc.. ) manipulant les données, d'où qu'elles viennent, qui enregistre une date sous ce format "polémique"
    1-l'algorithme de transformation est connu (du moins c'est ce qu'il me semble)
    Quand j'ai dit connu je parlais de la société où travaille r038tmp5 puisqu'il ont les source de ce fameux programme

    Ce que tu proposes ne me dérange nullement car tu as fait le choix du Delphi.
    non, là tu te focalises sur un langage or il ne s'agit pas de ça , j'aurais pu tout aussi bien (moins facilement peut être) écrire la fonction en C,QT etc... en fait tout langage proposant ou pas un EDI (delphi est avant tout un EDI pas un langage sensu stricto) mais permettant de créer une DLL

    Ce qui me dérange sous FireBird (ou n'importe quel autre SGBD), ce sont deux choses :

    --> stocker une valeur numérique et non le libellé de la date sous FireBird.
    J'entends par là, trouver une solution propre, en dehors des normes de FireBird.
    La valeur numérique n'est pas la bonne représentation d'une date. Le libellé l'est un peu plus, mais on ne peut pas faire des opérations dessus.

    Je tiens à préciser que sous gros système IBM, en Cobol, on gère les dates que sous la forme de libellé. Nous sommes obligé de créer les outils nécessaires pour faire des calculs.
    Mais la date est toujours stockées sous forme du libellé 'AAAAMMJJ' avec ou sans séparateur. On n'a pas de date pivot comme le cas avec '1970/01/01 00:00:00' dans le cas d'unix.

    Encore qu'au temps du bug de l'an 2000, il y avait des dates stockées sans les siècles. Il fallait faire un choix et quand on avait 'AA' < 70, on disait alors que 'SS' = '19 sinon '20'. On avait une amplitude de 100 ans, imposé justement par le stockage des années sous deux chiffres.
    Ce que tu nous écrit m'est bien connu (moi aussi j'ai travaillé sur des moyen système IBM 32/34/36) et j'ai été confronté au COBOL et de sa fameuse lacune sur les dates.

    La valeur numérique n'est pas la bonne représentation d'une date. Le libellé l'est un peu plus, mais on ne peut pas faire des opérations dessus.
    --> stocker une valeur numérique et non le libellé de la date sous FireBird.
    J'entends par là, trouver une solution propre, en dehors des normes de FireBird.
    encore une fois oui et la solution c'est les UDF qui sont bien des fonctions "en dehors" de Firebird

    Si toutes les SGBD actuelles propose un champ date au format numérique, rien ne t'empêche de stocker tes dates sous un format chaine (définir le format, le calendrier etc.. est un autre choix) à partir du moment où tu peux traiter ce format pour faire des opérations dessus plus de soucis. Un avantage des UDF est justement que tu peux "proposer" à Firebird un moyen de traiter cette représentation de date (quelque soit le langage de programmation) via SQL en faisant appel à la fonction idoine. (je ne pense pas que tous les SGBD propose ce genre de solutions)
    le stockage des dates sous forme numérique à cependant des avantages pour la construction d'index, les recherches etc...


    Citation Envoyé par alanglet
    Quand à l'utilisation de fonctions UDF, je suis assez "mitigé", surtout maintenant que les fonctions internes ont été bien étendues.
    oui, mais dans ce cas particulier je crois que cela s’appliquerait assez bien
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  18. #18
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 134
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 134
    Points : 38 557
    Points
    38 557
    Billets dans le blog
    9
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    Ce que tu nous écrit m'est bien connu (moi aussi j'ai travaillé sur des moyen système IBM 32/34/36) et j'ai été confronté au COBOL et de sa fameuse lacune sur les dates.
    c'est en marge du sujet, mais ce problème est sans rapport avec le langage COBOL qui sait gérer un date avec ou sans siècle, mais uniquement d'un problème historique :
    il y eut un temps ancien - que les moins de 20 ans ne peuvent pas connaître - où la mémoire vive comme la mémoire magnétique, coûtait très cher.
    C'est pour cette raison que les dates étaient stockées sans le siècle.

  19. #19
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 380
    Points : 19 062
    Points
    19 062
    Par défaut
    Salut à tous.

    Citation Envoyé par escartefigue
    c'est en marge du sujet, mais ce problème est sans rapport avec le langage COBOL
    Pas tant que cela. L'exemple du COBOL n'est qu'une solution (un peu ancienne) parmi d'autres solutions.
    En fait, il s'agit de la représentation des date + time en stockage et de leur exploitation (calculs).

    Au tant en COBOL, le stockage de la date me semble normal (question d'habitude, je pense), au tant il faut créer les outils pour faire des calculs, ce qui n'est pas très pratique.
    Oui mais voilà, l'amélioration proposé par Unix offre quelques avantages mais aussi quelques inconvénients.
    Entre autre, le fait que le stockage se fasse en 32 bits mais aussi la limitation des date + time valides.

    D'où, comme l'a indiqué SergioMaster dans son message N°14, la pluralité des solutions pour stocker une date + time. Et là, c'est vraiment pas bien.

    Citation Envoyé par escartefigue
    où la mémoire vive comme la mémoire magnétique, coûtait très cher.
    C'est ce que l'on dit, mais c'est faux. J'ai connu cette époque !
    Certains informaticiens ayant connus l'époque dont tu parles, on continué à appliquer des règles qui n'avaient plus cours.
    Ce sont des mauvaises habitudes qui ont continué à exister, même après le bug de l'an 2000.

    Citation Envoyé par alanglet
    DATE enregistre dans un mot de 32b une date comprise entre le 1 janvier 100 et le 29 février 32768
    TIME enregistre dans un mot de 32 bit une heure comprise entre 00:00 et 23:59:9999
    Merci alanglet pour cette précision. Maintenant, je comprends mieux l'erreur qu'à rencontré r038tmp5 dans son premier message.

    Citation Envoyé par SergioMaster
    non, là tu te focalises sur un langage or il ne s'agit pas de ça
    Je ne me focalise pas sur un langage, mais sur le langage que le développeur dispose.
    C'est au langage de programmation de résoudre ce problème et non à le faire dans le SGBD FireBird.
    Après, la façon de résoudre ce problème m'importe peu.

    Citation Envoyé par SergioMaster
    Si toutes les SGBD actuelles propose un champ date au format numérique, rien ne t'empêche de stocker tes dates sous un format chaîne (définir le format, le calendrier etc.. est un autre choix) à partir du moment où tu peux traiter ce format pour faire des opérations dessus plus de soucis.
    Le problème est l'amplitude des date + time que tu désires stockées. Que signifie une date avant Jesus Christ ?
    Si ta date est informationnel, je veux bien. Mais si tu veux faire des calculs, je ne comprends pas trop l'intérêt avec une date aussi éloignée d'aujourd'hui.
    En disant cela, j'ai en tête l'aspect financier, entre autre les emprunts indivis. Sinon quel est l'intérêt de faire un calcul ?

    Je crois que l'on a fait le tour de la question.
    Merci à tous les participants !

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  20. #20
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 134
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 134
    Points : 38 557
    Points
    38 557
    Billets dans le blog
    9
    Par défaut
    Citation Envoyé par Artemus24 Voir le message
    C'est ce que l'on dit, mais c'est faux. J'ai connu cette époque !
    Certains informaticiens ayant connus l'époque dont tu parles, on continué à appliquer des règles qui n'avaient plus cours.
    Ce sont des mauvaises habitudes qui ont continué à exister, même après le bug de l'an 2000.
    J'ai connu aussi et c'est la vérité, tout le matériel coutait une fortune

    J'ai même, pendant un an environ, c'est comme ça que j'ai commencé dans le milieu informatique, vendu des PC, les tous premiers PC IBM (avant même qu'ils soient renommés PC XT) ça nous positionne si je ne m'abuse en 1983 ou 84
    et bien, je l'aurai oublié si je n'avais pas retrouvé des tarifs de l'époque dans mes papiers à l'occasion d'un déménagement, un PC de cette époque avec 64K de RAM (oui 64k ) un écran monochrome CGA (c'est à dire une résolution 320*200 si je me souviens bien) et un disque dur de 10 mégas (on croit réver ) coutait à l'époque .... 40 000 FRF hors taxes !
    Et un disque dur supplémentaire, coutait 2500 FRF de plus

    Coté mainframe, je me souviens de l'époque vers fin 1980 ou tout début 1990, où l'on a remplacé dans la société où j'intervenais, les vieux 3380 par des disques RAIDS distribués par EMC (je ne me souviens plus du constructeur, il était très connu à l'époque)
    1 seule unité de nouveaux disques beaucoup plus rapide et plus puissante que les 3380 coutait moins cher que les 8 unités qu'elles remplaçait !

    Enfin, pour compléter, les mauvaises habitudes, bien sur, tout le monde en est convaincu, le truc c'est que le patrimoine applicatif comportait des milliers de fichiers, bases de données et programmes à revoir pour corriger tout ca, c'est la raison pour laquelle ces mauvaises habitudes ont perduré si longtemps !

    Ce n'est pas pour rien qu'il y a eu le fameux "projet an 2000", et ce fut un sacré bor#### pour corriger tout ça

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [MySQL] conversion date au format iso
    Par event dans le forum PHP & Base de données
    Réponses: 17
    Dernier message: 06/01/2012, 17h06
  2. problème conversion date en format yyMMdd
    Par CosaNostra dans le forum Collection et Stream
    Réponses: 2
    Dernier message: 08/06/2010, 13h41
  3. Regrouper des dates au format UNIX
    Par seb2020 dans le forum Langage
    Réponses: 3
    Dernier message: 08/09/2009, 19h24
  4. date en format unix
    Par scoobiflo dans le forum Shell et commandes GNU
    Réponses: 8
    Dernier message: 10/07/2009, 14h42

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo