2010-06-20 5 views
1

INFORMIX-SQL 7.32 (SE) Exécuter l'écran:Comment puis-je déterminer combien de mois, de semaines et de jours se sont écoulés entre deux dates?

Disons que j'ai une date de début de FEB-15-2010 et une date de fin de MAI-27-2010. Je peux calculer le nombre de jours écoulés avec 'let elapsed_days = end_date - start_date', mais comment puis-je convertir ce nombre de jours en 3 mois, 1 semaine et 5 jours?

Un calcul brut que j'ai vu utilisé, arrondi chaque mois à 31 jours, puisque si vous prenez le nombre de jours dans chaque mois, additionnez-les et divisez-les par 12 vous donne 30,5 jours par mois, puis prendre des jours écoulés et le diviser par 31 produit 3,31 mois, mais cette méthode est inacceptable pour mes besoins.

+1

semaines et jours Détermination entre les dates est essentiellement trivial - il existe une formule entièrement déterministe pour le faire. Dès que vous mentionnez des «mois» aussi, vous vous promenez le long du sentier étroit et droit dans le sous-bois enchevêtré. Vous devez définir (rigoureusement) ce que signifie un mois, en toutes circonstances, en vous rappelant de tenir compte des jours bissextiles. Là où ça devient intéressant, c'est avec des combinaisons comme 2010-02-28 et 2010-05-29, ou 2012-02-29 et 2012-05-28 (29, 30, 21), etc. Comme 'un mois' est une variable quantité, nous devons savoir quel sens vous voulez attribuer au mois pour savoir quelle valeur donner. –

+1

FWIW: La fonction MONTHS_BETWEEN() d'Oracle donne des résultats intéressants pour les paires de dates citées - les valeurs sont: 3.03225806451613, 2.96774193548387, 3.0, 3.03225806451613, 3.0 respectivement. Notez que le nombre de mois entre le 30 mai et le 29 février est supérieur au nombre de mois entre le 31 mai et le 29 février. C'est la définition de MONTHS_BETWEEN(). Vous devez savoir à ce sujet pour l'utiliser. Bien sûr, MONTHS_BETWEEN d'Oracle n'est pas implémenté dans SE, seulement dans IDS. Mais le point reste - sans la définition requise de MONTH, personne ne peut produire le code pour vous. –

+0

@ Jonathan- OK, vous souvenez-vous de la table de consultation des dimensions de dates que mon application utilise (voir la publication: "Date de la table de correspondance 1990-01-01: 2041-12-31")? .. Pouvez-vous penser à une méthode dans laquelle je pourrait concevoir un algorithme qui accomplirait mon but? .. ou devrais-je juste employer 30.5 jours moyens, arrondir tous les mois à 31 jours pour baser YMWD calcs? .. il serait à tous les clients l'avantage que chaque mois est basé sur 31 jours , quand certains mois ont réellement 28, 29 et 30 jours parce que les clients recevront ces jours gratuitement quand calcking leurs intérêts, (par exemple 16 à 31 jours = intérêt de 20%, 32 à 36 jours = 25% ..) ;-) –

Répondre

3

Cela pourrait probablement tenir une certaine tests plus rigoureux, et il est certainement possible de ranger la sortie (par exemple enlever « 0 mois ») sous-chaînes, mais je pense qu'il vous obtient la plupart du chemin ...

CREATE PROCEDURE informix.datediff(d1 DATE, d2 DATE) RETURNING VARCHAR(255); 
    DEFINE yrcount, mthcount, wkcount, daycount INTEGER; 
    DEFINE dx DATE; 

    LET mthcount = ((YEAR(d2) - YEAR(d1)) * 12) + MONTH(d2) - MONTH(d1); 
    IF DAY(d1) <= DAY(d2) THEN 
     LET daycount = DAY(d2) - DAY(d1); 
    ELSE 
     LET dx = MDY(MONTH(d1),1,YEAR(d1))+1 UNITS MONTH; 
     LET daycount = dx - d1;  -- elapsed days from last month 
     LET daycount = daycount + DAY(d2) - 1; -- elapsed days from this month 
    END IF; 

    LET yrcount = mthcount/12; 
    LET mthcount = MOD(mthcount,12); 
    LET wkcount = daycount/7; 
    LET daycount = MOD(daycount,7); 

    RETURN d1 || " - " || d2 || ": " || yrcount || " years, " || mthcount 
     || " months, " || wkcount || " weeks and " || daycount || " days "; 
END PROCEDURE; 

-à-dire:

execute procedure datediff(TODAY, "19/03/2011"); 
(expression) 21/06/2010 - 19/03/2011: 0 years, 9 months, 4 weeks and 0 days 

execute procedure datediff(TODAY, "22/03/2011"); 
(expression) 21/06/2010 - 22/03/2011: 0 years, 9 months, 0 weeks and 1 days 

execute procedure datediff("08/02/2010", "08/05/2011"); 
(expression) 08/02/2010 - 08/05/2011: 1 years, 3 months, 0 weeks and 0 days 

execute procedure datediff("31/03/2010", TODAY); 
(expression) 31/03/2010 - 21/06/2010: 0 years, 3 months, 3 weeks and 0 days 

execute procedure datediff(TODAY-3, TODAY); 
(expression) 18/06/2010 - 21/06/2010: 0 years, 0 months, 0 weeks and 3 days 

execute procedure datediff(TODAY-33, TODAY); 
(expression) 19/05/2010 - 21/06/2010: 0 years, 1 months, 0 weeks and 2 days 
+0

Idéal pour un SPL, mais la fonctionnalité doit être accomplie dans la section des instructions de l'écran Perform de ISQL. –

+1

Cela fait probablement 15 ans que j'ai joué avec ISQL, ACE et Perform, et je n'ai jamais utilisé SE. Mais serait-il possible de lier l'écran Perform à une vue de votre table qui inclut cette colonne virtuelle? – RET

+0

Peut-être avec IDS .. Il est probablement préférable de créer et d'appeler un cfunc 'cymwd (start_date, end_date)' pour retourner: siècles, années, mois, semaines, jours et pf_putval avec ESQL/C. –

Questions connexes