Date et heure DATEDIFF_AMJ4

patricktoulon

XLDnaute Barbatruc
Bonjour a tous
j'avais fait une fonction "DATEDIFFAMJ" il y a quelque temps pour obtenir la différence entres deux date ans mois et jour
et un demandeur a faite une demande concernant la différence entre deux dates
sauf que lui avait besoins de faire la différence de dates 1 et 2 (entre deux siècles)
et pour couronner le tout avec des dates en dessous l'année 1900
j'ai donc repris ma fonction de base et utilisé une astuce simple
si pour la date la plus ancienne c'est une année divisible par 4 ou 400 je la décale en 2020( fevrier 28/29) sinon je la décale en 1904
j'ai ajouté un argument optional "JustYear" pour me donner uniquement la différence en année
j'ai mis date2 en optional aussi histoire d'avoir l'anniversaire
en dessous 1800 non garantie
la fonction:
VB:
Function DATEDIFF_AMJ4$(ByVal dat1 As Date, Optional ByVal dat2 As Date = 0, Optional JustYear As Boolean = False)
  '**************************************
'fonction DateDiffAMJ V°4
'auteur:patricktoulon sur Exceldownloads
'date de mise en jour V°4:04/07/2021
' mise a jour supplementaire
' ajout de l'argument boolean "JustYear" pour ne récuprérer que les années
'*************************************
  Dim A$, M$, J$, Dtemp$, et$, yeardécalée&, y
    If dat2 = 0 Then dat2 = Date
    If dat1 > dat2 Then Dtemp = dat2: dat2 = dat1: dat1 = Dtemp
    If Year(dat1) < 1904 Then If Year(dat1) Mod 4 <> 0 Or Year(dat1) Mod 400 <> 0 Then y = 2020 Else y = 1905
    If Year(dat1) < y Then
        'on decale la date la plus ancienne (Dat1)à l'année 1904
        yeardécalée = Abs((Year(dat1) - y))
        dat1 = DateSerial(Year(dat1) + yeardécalée, Month(dat1), Day(dat1))
        dat2 = DateSerial(Year(dat2) + yeardécalée, Month(dat2), Day(dat2))
    End If
    A = Evaluate("=DATEDIF(" & CLng(dat1) & "," & CLng(dat2) & ",""y"")")
    M = Evaluate("=DATEDIF(" & CLng(dat1) & "," & CLng(dat2) & ",""ym"")")
    J = Evaluate("=DATEDIF(" & CLng(dat1) & "," & CLng(dat2) & ",""md"")")
    A = IIf(A = 0, "", IIf(A = 1, A & " an", A & " ans"))
    M = IIf(M = 0, "", IIf(M = 1, M & " mois", M & " mois"))
    J = IIf(J = 0, "", IIf(J = 1, "1  jour", J & " jours"))
    et = IIf(Val(A) > 0 Or Val(M) > 0, IIf(Val(J) > 0, " et ", " "), "")
    DATEDIFF_AMJ4 = Application.Trim(A & IIf(Not JustYear, " " & M & " " & et & J, ""))
End Function

exemple d'utilisation en formule :

résultat complet souhaité
Code:
=datediff_amj4(A2;B2)

juste les années souhaitées
Code:
=datediff_amj4(A2;B2;1)

pour un anniversaire résultat complet (ans mois jour),on a besoins uniquement de la date 1
Code:
=datediff_amj4(A2)

pour un anniversaire juste les "ans",on a besoins uniquement de la date 1 et de l'argument "Justyear" (0 ou 1)
Code:
=datediff_amj4(A2;;1)
petite démo
1625415572835.png


l'utilisation en VBA se fait de la même manière

et sauf erreur de ma part elle est compatible All version Excel
 
Dernière édition:

Etoto

XLDnaute Barbatruc
Bonjour a tous
j'avais fait une fonction "DATEDIFFAMJ" il y a quelque temps pour obtenir la différence entres deux date ans mois et jour
et un demandeur a faite une demande concernant la différence entre deux dates
sauf que lui avait besoins de faire la différence de dates 1 et 2 (entre deux siècles)
et pour couronner le tout avec des dates en dessous l'année 1900
j'ai donc repris ma fonction de base et utilisé une astuce simple
si pour la date la plus ancienne c'est une année divisible par 4 ou 400 je la décale en 2020( fevrier 28/29) sinon je la décale en 1904
j'ai ajouté un argument optional "JustYear" pour me donner uniquement la différence en année
j'ai mis date2 en optional aussi histoire d'avoir l'anniversaire
en dessous 1800 non garantie
la fonction:
VB:
Function DATEDIFF_AMJ4$(ByVal dat1 As Date, Optional ByVal dat2 As Date = 0, Optional JustYear As Boolean = False)
  '**************************************
'fonction DateDiffAMJ V°4
'auteur:patricktoulon sur Exceldownloads
'date de mise en jour V°4:04/07/2021
' mise a jour supplementaire
' ajout de l'argument boolean "JustYear" pour ne récuprérer que les années
'*************************************
  Dim A$, M$, J$, Dtemp$, et$, yeardécalée&, y
    If dat2 = 0 Then dat2 = Date
    If dat1 > dat2 Then Dtemp = dat2: dat2 = dat1: dat1 = Dtemp
    If Year(dat1) < 1904 Then If Year(dat1) Mod 4 <> 0 Or Year(dat1) Mod 400 <> 0 Then y = 2020 Else y = 1904
    If Year(dat1) < y Then
        'on decale la date la plus ancienne (Dat1)à l'année 1904
        yeardécalée = Abs((Year(dat1) - y))
        dat1 = DateSerial(Year(dat1) + yeardécalée, Month(dat1), Day(dat1))
        dat2 = DateSerial(Year(dat2) + yeardécalée, Month(dat2), Day(dat2))
    End If
    A = Evaluate("=DATEDIF(" & CLng(dat1) & "," & CLng(dat2) & ",""y"")")
    M = Evaluate("=DATEDIF(" & CLng(dat1) & "," & CLng(dat2) & ",""ym"")")
    J = Evaluate("=DATEDIF(" & CLng(dat1) & "," & CLng(dat2) & ",""md"")")
    A = IIf(A = 0, "", IIf(A = 1, A & " an", A & " ans"))
    M = IIf(M = 0, "", IIf(M = 1, M & " mois", M & " mois"))
    J = IIf(J = 0, "", IIf(J = 1, "1  jour", J & " jours"))
    et = IIf(Val(A) > 0 Or Val(M) > 0, IIf(Val(J) > 0, " et ", " "), "")
    DATEDIFF_AMJ4 = Application.Trim(A & IIf(Not JustYear, " " & M & " " & et & J, ""))
End Function

exemple d'utilisation en formule :

résultat complet souhaité
Code:
=datediff_amj4(A2;B2)

juste les années souhaitées
Code:
=datediff_amj4(A2;B2;1)

pour un anniversaire résultat complet (ans mois jour),on a besoins uniquement de la date 1
Code:
=datediff_amj4(A2)

pour un anniversaire juste les "ans",on a besoins uniquement de la date 1 et de l'argument "Justyear" (0 ou 1)
Code:
=datediff_amj4(A2;;1)
petite démo
Regarde la pièce jointe 1110159

l'utilisation en VBA se fait de la même manière

et sauf erreur de ma part elle est compatible All version Excel
Bonjour,

Déjà merci de ta fonction qui est superbe, tu sais quelle est l'année minimum possible pour la fonction ? 1800 ou moins ? Je suis curieux et je voudrais savoir.
 

patricktoulon

XLDnaute Barbatruc
bonjour @Etoto
normalement je vais même beaucoup plus bas
mais je cite @Victor21
Imposé par Grégoire XIII dans les États pontificaux, le calendrier grégorien fut aussi immédiatement adopté par l'Espagne, l'Italie, la Pologne et le Portugal.
En France, Henri III l'adopta le 9 décembre 1582, dont le lendemain fut le 20 décembre 1582
mais les différents parlements ont approuvé ce changement plus ou moins tardivement.
De plus, les provinces suivantes n'étaient pas françaises à l'époque :
Alsace : le 5 février 1682 est suivi par le 16 février 1682.
Lorraine : le 16 février 1760 est suivi par le 28 février 1760...

donc il serait inutile de descendre plus bas que 1761 surtout si on travaille des dates d’événement historique

cela dit si je teste
avec une date du genre 05/03/0365 avec "=DateDiff_AMJ4(A21) "j’obtiens bien 1656 ans et 4 mois

donc mathématiquement parlant la fonction est valide jusqu'en l'an 0100 mais pas plus bas
car vba interprète le nombre de l'année > que 9 de plus ou = à la dizaine de l'année en cours comme 20xx par contre si c'est >= alors 19xx
exemple
VB:
Sub test()
    MsgBox CDate("03/06/0020")
    MsgBox CDate("03/06/0022")
    MsgBox CDate("03/06/0029")
    MsgBox CDate("03/06/0030")
    MsgBox CDate("03/06/0036")
End Sub

donc je le redis mathématiquement parlant la fonction est valide jusqu'en l'an 0100
voila ;)
 

Etoto

XLDnaute Barbatruc
Re,
Imposé par Grégoire XIII dans les États pontificaux, le calendrier grégorien fut aussi immédiatement adopté par l'Espagne, l'Italie, la Pologne et le Portugal.
En France, Henri III l'adopta le 9 décembre 1582, dont le lendemain fut le 20 décembre 1582
mais les différents parlements ont approuvé ce changement plus ou moins tardivement.
De plus, les provinces suivantes n'étaient pas françaises à l'époque :
Alsace : le 5 février 1682 est suivi par le 16 février 1682.
Lorraine : le 16 février 1760 est suivi par le 28 février 1760...
Ok oui, c'est vrai que après les dates dessous 1761 peuvent êtres considérées comme erronées (même si je ne sais pas en quelle année le nouveau calendrier grégorien fut adopté en Suisse)
mathématiquement parlant la fonction est valide jusqu'en l'an 0100
Mais, l'an 100 c'est cool ça, merci de ta superbe fonction, je butais un peu avec les dates avant 1900 mais grâce à toi, j'ai déjà une superbe base.
 

patricktoulon

XLDnaute Barbatruc
re
je pourrais même ajouter - 11 jours si date en <= 9 décembre 1760 histoire d'aller plus loin
mais je sais pas si on devrait le considérer comme ça en fait car ça fait un mois de décembre à 19 jours
si @Victor21 passe par là il me diras ;)
 

Victor21

XLDnaute Barbatruc
[...]même si je ne sais pas en quelle année le nouveau calendrier grégorien fut adopté en Suisse[...]
@Etoto :
D'après mes sources -incomplètes :
Suisse1584du 12 du 21 novembreCantons de Lucerne, Uri, Schwitz, Zug et Fribourg
Suisse1724Cantons d'Unterwald et Appenzel, après avoir adopté une l" fois la réforme en 1584 et 1590 et être retournés au calendrier julien par la suite
Suisse1622Canton du Valais
Suisse1701du 1er au 11 janvierVilles (et cantons) de Zurich, Berne, Schaffhouse, Genève, Bienne, Neuchâtel, etc.
Suisse1724en janvierVilles (et cantons) de Saint
Suisse1784Canton des Grisons, pour partie, certaines régions ayant basculé en 1798, voire en 1811
 

Etoto

XLDnaute Barbatruc
@Etoto :
D'après mes sources -incomplètes :
Suisse1584du 12 du 21 novembreCantons de Lucerne, Uri, Schwitz, Zug et Fribourg
Suisse1724Cantons d'Unterwald et Appenzel, après avoir adopté une l" fois la réforme en 1584 et 1590 et être retournés au calendrier julien par la suite
Suisse1622Canton du Valais
Suisse1701du 1er au 11 janvierVilles (et cantons) de Zurich, Berne, Schaffhouse, Genève, Bienne, Neuchâtel, etc.
Suisse1724en janvierVilles (et cantons) de Saint
Suisse1784Canton des Grisons, pour partie, certaines régions ayant basculé en 1798, voire en 1811
Re,

Merci des infos @Victor21 👍 👍 .
 

eriiic

XLDnaute Barbatruc
Bonjour,

il y a une erreur dans le traitement qui induit des mauvais résultats.
"c'est une année divisible par 4 ou 400 je la décale en 2020"
Non. Déjà un nombre divisible par 400 sera toujours divisible par 4, ce test serait inutile en théorie.
Mais 1900 par exemple est divisible par 4 et n'est pas bissextile.

Il faut distinguer si tu as affaire à un siècle (divisible par 100) auquel cas c'est bissextile si divisible par 400.
Pour les autres années c'est bissextile si divisible par 4.
Si tu considères ta fonction valide pour les années >= 1584 tu peux simplifier en ajoutant 800 ans d'office aux date si dat1<=1901 (pour ôter le bug de 1900 bissextile pour excel)

Par ailleurs ta fonction annonce 3 jours (?) pour 28/02/1900 au 01/03/1900.
En vrai c'est 1, avec ton erreur ça devrait être 2 mais 3...
Je pense que c'est dû au fait que les n° de série diffèrent de 1 entre excel (bogué) et vba pour les dates inférieures au 01/03/1900.
Par exemple 1 c'est 01/01/1900 pour excel mais 31/12/1899 pour vba
Pour bien faire, il faudrait pour ces dates traiter différemment si la date vient d'une feuille ou de vba.
A voir si la correction corrigera aussi ce cas

1660429669874.png

eric
 

Discussions similaires

Réponses
19
Affichages
2 K
Réponses
32
Affichages
4 K