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
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. –
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. –
@ 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% ..) ;-) –