2017-05-02 1 views
0

Je dois reproduire la fonction Datedif de la bouilloire dans le langage de programmation R. J'ai besoin de l'option 'datedif month'. Je pensais que la reproduction serait assez facile mais j'ai un «comportement étrange» dans pentaho. A titre d'exemple:Kettle Daté mois numéro

ID DATE_1 Date_2 monthly_difference_kettle daydiff_mysql

15943 31/12/2013 28/07/2014 7 209

15943 31/12/2011 27/07/2012 6 209

Donc, dans la bouilloire pentaho, j'ai utilisé la formule-étape et la fonction DATEDIF (date2, date1, "m"). Comme vous pouvez le voir lorsque je calcule la différence quotidienne en mysql, je reçois pour les deux enregistrements le même nombre de jours en différence (209), cependant, quand la différence mensuelle est calculée via l'étape de la formule dans pentaho, je reçois un résultat différent en mois (7 et 6 respectivement). Je ne comprends pas comment cela est calculé ...

Quelqu'un peut-il produire le code source de la fonction 'DATEDIF mois' dans pentaho? Je voudrais le reproduire en R pour obtenir exactement les mêmes résultats.

Merci à l'avance, meilleures salutations,

+0

Pourquoi y a-t-il des dates différentes dans vos lignes d'échantillonnage? La deuxième ligne comprend un mois de février de 29 jours parce que 2012 est une année bissextile alors que 2014 ne l'est pas. C'est probablement un bug dans le maniement de l'année bissextile d'un côté ou de l'autre. – Cyrus

Répondre

2

ne suis pas sûr mysql, mais je pense qu'il est le même. Dans PostgreSQL, la différence de date donne une valeur entière (en jours). Cela signifie que les deux lignes ont une correspondance totale en jours.

Calcul de la différence de mois non trivial. Qu'est-ce que le mois (28, 30, 31 jours)? Allons-nous compter si le mois n'est pas plein?

Etats Documentation S'il n'y a pas un mois complet entre les dates, 0 seront retournés

Mais selon le code source facile à comprendre comment calculé DATEDIF:

code source disponible via GitHub https://github.com/pentaho/pentaho-reporting/blob/f7defbcfc0e8f48ad2b139fe9820445f052e0e78/libraries/libformula/src/main/java/org/pentaho/reporting/libraries/formula/function/datetime/DateDifFunction.java

private int addFieldLoop(final GregorianCalendar c, final GregorianCalendar target, final int field) { 
c.set(Calendar.MILLISECOND, 0); 
c.set(Calendar.SECOND, 0); 
c.set(Calendar.MINUTE, 0); 
c.set(Calendar.HOUR_OF_DAY, 0); 

target.set(Calendar.MILLISECOND, 0); 
target.set(Calendar.SECOND, 0); 
target.set(Calendar.MINUTE, 0); 
target.set(Calendar.HOUR_OF_DAY, 0); 

if (c.getTimeInMillis() == target.getTimeInMillis()) { 
    return 0; 
} 

int count = 0; 
while (true) { 
    c.add(field, 1); 
    if (c.getTimeInMillis() > target.getTimeInMillis()) { 
    return count; 
    } 
    count += 1; 
} 
} 

Append 1 mois à la date de début jusqu'à ce qu'il deviendra alors plus la date de fin

+2

Il vaut la peine de mentionner la façon dont la méthode GregorianCalendar.add() fonctionne par rapport aux mois. Une fois que vous ajoutez 1 mois au 31/12/2013, vous obtenez le 31/01/2014. Ensuite, vous aurez 28/02/2014 puis 28/03/2012, et ainsi de suite. De cette façon, à la septième itération, vous arriverez exactement au 28/07/2014, et vous aurez besoin d'une nouvelle itération pour dépasser la date cible. En partant du 31/12/2011 après les mêmes 7 itérations, vous arriverez au 29/07/2014, dépassant ainsi la date cible. La valeur renvoyée par addFieldLoop est le numéro d'itération - 1. – user4637357

+0

Merci pour cette précision, cela aide beaucoup. Donc, quand on passe en février, ça fait quelque chose de bizarre qu'au lieu d'aller jusqu'à la fin des prochains mois, ça ne va qu'au nombre de jours en février? Serait-ce la même situation dans le cas suivant: dire que je dois aller de 31/03/2015 à 30/09/2016: commencer: 31/03/2015 + 1 mois 30/04/2015 + 1 mois 30/05/2015 -> au lieu de normalement 31/05/2015 + 1 mois 30/06/2015 + 1 mois 30/07/2015 -> au lieu de normalement 31/07/2015 Alors règle serait prendre le plus bas «nombre de jour» pour aller plus loin dans la boucle? merci d'avance – tibo

+1

Oui, il semble que oui. C'est la ligne imprimée par cette boucle, après avoir mis print juste après c.add() pour aller du 31/03/205 au 30/09/2016 (j'ai incrémenté mois par 1, de sorte qu'il ne va pas commencer à partir de 0): 2015/4/30 -> 2015/5/30 -> 2015/6/30 -> 2015/7/30 -> 2015/8/30 -> 2015/9/30 -> 2015/10/30 -> 2015/11/30 -> 2015/12/30 -> 2016/1/30 -> 2016/2/29 -> 2016/3/29 -> 2016/4/29 -> 2016/5/29 - > 2016/6/29 -> 2016/7/29 -> 2016/8/29 -> 2016/9/29 -> 2016/10/29 – user4637357