Autres Durée calendaire

jmfmarques

XLDnaute Accro
Bonjour
Deux discussions ont été ouvertes (et sont en cours) au sujet du calcul de la durée calendaire.
Je ne souhaite vraiment pas que celle-ci, de discussion, dévie à son tour de la finalité.
il ne s'agit en aucun cas de déterminer si est logique ou non la notion même de durée calendaire (qu'il s'agisse d'un âge, ou d'une ancienneté, etc ...), mais tout simplement d'en permettre le calcul sur la base des conventions de définition d'une durée calendaire.
Le calcul d'une durée calendaire est enseigné en cours élémentaire et est effectué sur ces bases :
- Détermination de la partie "principale" de la durée calendaire : elle est composée des entiers suivants, entre deux date/heure:
- nombres d'années calendaires entières (donc de date/heure à date/heure)
- nombre de mois calendaires entiers (donc de date/heure à date/heure)
Une fois cette partie principale déterminée (au bout du compte : une espèce d'âge anniversaire), elle est complétée par tous les "résidus", qui, eux, sont temporels et ne peuvent qu'être exprimés en jours, heures, minutes et secondes au delà de l' " anniversaire"

Ainsi et par exemple :
- si Pierre a atteint l'âge de 10 ans le 27 février 2020 (à supposément 0h:0m:0s), il a 10 ans , 3 jours et 2 heures le 01/03/2020 à 2 heures du mat , hein ...
- il n'aurait eu que 10 ans et 2 jours le 01/03/2019 à 2 heures du mat s'il était né le 27/02/2019
Partons maintenant de l'idée selon laquelle cette convention de calcul n'échappe à personne (y compris -puisque tel n'est pas le propos - à ceux qui en contesteraient l'utilité :), la raison d'être, etc ... etc ... qui relèvent de toute autre chose que du calcul à faire sur les bases de cette convention, sans en discuter ce qui n'est par définition même pas à discuter ....) :

Le décor est-il maintenant clair pour tous ?
Si (et j'espère que tel est le cas) oui, je me suis efforcé de coder une fonction personnalisée totalement indépendante de l'utilisation de fonctions Excel (DATEDIF, au demeurant masquée) et VBA (datediff), dont il est rapporté qu'elles ne sont pas exemptes d'erreurs selon la version Office.
J'ai donc codé la fonction personnalisée suivante :
VB:
Public Function DUREE_CALENDAIRE(C1 As Range, C2 As Range) As String
  Dim d1 As Date, d2 As Date, T(2, 5) As Integer, z As Integer, k As Integer, X As String, n
  d1 = C1.Value: d2 = C2.Value
  T(0, 0) = Year(d2): T(0, 1) = Month(d2): T(0, 2) = Day(d2): T(0, 3) = Hour(d2): T(0, 4) = Minute(d2): T(0, 5) = Second(d2)
  T(1, 0) = Year(d1): T(1, 1) = Month(d1): T(1, 2) = Day(d1): T(1, 3) = Hour(d1): T(1, 4) = Minute(d1): T(1, 5) = Second(d1)
  For k = 5 To 0 Step -1
    If T(0, k) < T(1, k) Then
      z = 60
      Select Case k
        Case 3: z = 24
        Case 2: z = Day(DateSerial(T(0, 0), T(0, 1), 0))
        Case 1:  z = 12
      End Select
      T(0, k) = T(0, k) + z: T(0, k - 1) = T(0, k - 1) - 1
    End If
    T(2, k) = T(0, k) - T(1, k)
  Next
  n = Array("", " an", " mois", " jour", " heure", " minute", " seconde")
  For k = 0 To 5
    X = X & IIf(T(2, k) > 0, T(2, k) & n(k + 1), " ") & IIf(T(2, k) > 1 And k <> 1, "s", "") & " "
  Next
  DUREE_CALENDAIRE = WorksheetFunction.Trim(X)
End Function
- en application des méthodes de calcul enseignées dans ce domaine en cours élémentaire
- en ne faisant appel qu'à la seule fonction de VBA dont l'exactitude ne saurait être mise en cause (DateSerial)

J'ai bien évidemment fait des tests du type "avocat du diable" pour déceler d'éventuelles erreurs.
Je n'y suis pas parvenu (à déceler une faille) jusqu'à présent, mais d'autres pourraient découvrir une faille qui m'aurait échappé. ils m'intéressent.
Voilà le principe des ces tests (avec cette formule en C2 et tiée vers le bas:
Code:
=DUREE_CALENDAIRE(A2;B2)
Ma gratitude à tous ceux qui voudront bien tout mettre en oeuvre pour mettre en exergue une éventuelle faille. Ce ne sera qu'en absence de faille, que je déposerai cette fonction personnalisée.

débutfinancienneté calendaire
14/05/1941 00:00:02​
25/03/2020 00:00:00​
78 ans 10 mois 10 jours 23 heures 59 minutes 58 secondes
14/01/2019 10:00:02​
16/02/2020 00:02:01​
1 an 1 mois 1 jour 14 heures 1 minute 59 secondes
26/03/2014 10:00:02​
02/03/2018 10:01:02​
3 ans 11 mois 4 jours 1 minute
26/02/2020 10:00:02​
02/03/2020 10:00:02​
5 jours
 
Dernière édition:

Modeste geedee

XLDnaute Barbatruc
Bonsour®
Le décor est-il maintenant clair pour tous ?

Ma gratitude à tous ceux qui voudront bien tout mettre en oeuvre pour mettre en exergue une éventuelle faille. Ce ne sera qu'en absence de faille, que je déposerai cette fonction personnalisée.
:( ne t'offusques pas, nous avons tous été confronté à cela
au hasard alors :
:cool:
1585319319592.png


1585320496192.png

1585320579779.png


1585320899350.png
[/QUOTE]
 

Modeste geedee

XLDnaute Barbatruc
Bonsour®
Le décor est-il maintenant clair pour tous ?
Si (et j'espère que tel est le cas) oui, je me suis efforcé de coder une fonction personnalisée totalement indépendante de l'utilisation de fonctions Excel (DATEDIF,

J'ai bien évidemment fait des tests du type "avocat du diable" pour déceler d'éventuelles erreurs.
Je n'y suis pas parvenu (à déceler une faille) jusqu'à présent, mais d'autres pourraient découvrir une faille qui m'aurait échappé. ils m'intéressent.
en omettant la partie horaire (ENT(DATEHEURE]
c'est quasiment la copie conforme de (4 nov 2019) :

;-))
et avec les mêmes anomalies...
1585327634042.png

VB:
Function AMJ(borne1 As Date, borne2 As Date) As String
'------------------------------------------------------------------
' ' Principe :
' ' on se cale sur le jour de début
' ' chaque jour identique des mois suivants détermine X periodes mensuelles
' ' on deduit A le nombre d'années complètes (12 périodes mensuelles  => ENT (X / 12)
' ' on deduit M le reliquat périodes mensuelles ( X modulo 12)
' ' on peut alors calculer J les jours résiduels
'------------------------------------------------------------------
Dim Ddeb As Date, DFin As Date
Dim A0 As Integer, M0 As Integer, J0 As Integer, X As Integer
Dim A As Integer, M As Integer, J As Integer
'============remise en ordre éventuel des bornes
Ddeb = Application.Min(borne1, borne2)
DFin = Application.Max(borne1, borne2)
' ------------------------------------------------------------------
A0 = Year(Ddeb)
' ===========mois anniversaire debut
M0 = Month(Ddeb)
'===========jour anniversaire debut
J0 = Day(Ddeb)
'------------------------------------------------------------------
' ===========on compte toutes les periodes mensuelles par rapport au jour anniversaire debut
X = 0
While DateSerial(A0, M0 + X, J0) <= DFin
        A = Int(M / 12):        M = X Mod 12:        A = Int(X / 12)
        X = X + 1
Wend
' ===========nombre de jours par rapport au dernier jour anniversaire pris en référence
' -------------------- X-1 permet la prise en compte du nombre de jour du mois précédent l'anniversaire
J = DFin - (DateSerial(A0, M0 + X - 1, J0))
'-------------------------------------------------------------------
' ===========mise en forme string AMJ (absences et pluriels)
Select Case A
        Case 0:         AMJ = ""
        Case 1:        AMJ = A & " an "
        Case Else:        AMJ = A & " ans "
End Select

Select Case M
        Case 0:         AMJ = AMJ & ""
        Case Else:        AMJ = AMJ & M & " mois "
End Select

Select Case J
        Case 0:        'AMJ = AMJ
        Case 1:        AMJ = AMJ & J & " jour"
        Case Else:        AMJ = AMJ & J & " Jours"
        End Select
' ==========contrôle éventuel
'AMJ  & date  anniversaire mois-1
'AMJ = AMJ & " " & Format(DateSerial(A0, M0 + X - 1, J0), "dd/mm/yy")
'End
End Function
 

jmfmarques

XLDnaute Accro
Me revoilà

Je pense que mon erreur était tout simplement au niveau de la base des retenues scolaires.
Conformément à la définition conventionnelle, les résidus sont à calculer en dépassement de l' "anniversaire", et les "reports correctifs" ne sont à appliquer que si unité/fin < unité/début.
Mais attention alors : l'unité/début est à corriger (-1) si dépassement de 28 en février ou dépassement de 30 tous les autres mois, puisque seules sont considérées les unités/fin et leurs résidus.


débutfinancienneté calendaire
14/05/1941 12:00:01​
25/03/2020 00:00:02​
78 ans 10 mois 10 jours 12 heures 1 secondeBON
14/01/2019 00:04:00​
16/02/2020 10:00:03​
1 an 1 mois 2 jours 9 heures 56 minutes 3 secondesBON
26/03/2014 01:01:01​
02/03/2018 02:00:00​
3 ans 11 mois 4 jours 58 minutes 59 secondesBON
26/02/2020 10:00:02​
02/03/2020 10:00:02​
5 joursBON
29/02/1940 00:00​
07/02/1947 00:00​
6 ans 11 mois 10 joursBON
01/03/1940​
07/02/1947​
6 ans 11 mois 5 jours 23 heures 59 minutes 41 secondesBON
31/12/2000​
06/07/2014​
13 ans 6 mois 6 joursBON
01/01/2001​
06/07/2014​
13 ans 6 mois 5 joursBON

Y sommes-nous maintenant ainsi :

VB:
Public Function DUREE_CALENDAIRE(C1 As Range, C2 As Range) As String
  Dim d1 As Date, d2 As Date, T(2, 5) As Integer, z As Integer, k As Integer, X As String, n
  d1 = C1.Value: d2 = C2.Value
  T(0, 0) = Year(d2): T(0, 1) = Month(d2): T(0, 2) = Day(d2): T(0, 3) = Hour(d2): T(0, 4) = Minute(d2): T(0, 5) = Second(d2)
  T(1, 0) = Year(d1): T(1, 1) = Month(d1): T(1, 2) = Day(d1): T(1, 3) = Hour(d1): T(1, 4) = Minute(d1): T(1, 5) = Second(d1)

  If Month(d1) = 2 And Day(d1) > 28 Then T(1, 2) = 28 '---> garde-fou 1
  If Day(d1) > 30 Then T(1, 2) = 30 '---> garde-fou 2


  For k = 5 To 0 Step -1
    If T(0, k) < T(1, k) Then
      z = 60
      Select Case k
        Case 3: z = 24
        'Case 2: z = IIf(Day(d1) <> 28 And Day(d2) <> 29, Day(DateSerial(T(0, 0), T(0, 1), 0)), 0)
        Case 2: z = Day(DateSerial(T(0, 0), T(0, 1), 0))
        Case 1:  z = 12
      End Select
      'MsgBox T(0, k) & "  " & T(0, k) + z
      T(0, k) = T(0, k) + z: T(0, k - 1) = T(0, k - 1) - 1
    End If
    T(2, k) = T(0, k) - T(1, k)
  Next
  n = Array("", " an", " mois", " jour", " heure", " minute", " seconde")
  For k = 0 To 5
    X = X & IIf(T(2, k) > 0, T(2, k) & n(k + 1), " ") & IIf(T(2, k) > 1 And k <> 1, "s", "") & " "
  Next
  DUREE_CALENDAIRE = WorksheetFunction.Trim(X)
End Function

Les deux garde-fous y sont mis en exergue
 
Dernière édition:

Modeste geedee

XLDnaute Barbatruc
Je pense que mon erreur était tout simplement au niveau de la base des retenues scolaires.
Conformément à la définition conventionnelle, les résidus sont à calculer en dépassement de l' "anniversaire", et les "reports correctifs" ne sont à appliquer que si unité/fin < unité/début.
Mais attention alors : l'unité/début est à corriger (-1) si dépassement de 28 en février ou dépassement de 30 tous les autres mois, puisque seules sont considérées les unités/fin et leurs résidus.
Les deux garde-fous y sont mis en exergue

:( cela ne semble pas suffire :

1585337716928.png


1585337745384.png
 

jmfmarques

XLDnaute Accro
J'ai des difficultés à voir où ce que tu as surligné de jaune comporte une erreur .
Peux-tu nous montrer les dates/heures complètes (on ne voit que les dates dans ce que tu affiches).

EDIT je vois bien (mais rien à voir avec tes surlignements) que mon deuxième garde-fou est à corriger (ce que je vais faire demain) très légèrement pour faire face à un cas particulier.
Cette correction n'aura par contre aucune incidence sur les erreurs que semble vouloir signaler ton message, erreurs qui font que ma question demeure, puisque je n'en vois personnellement pas encore.
 
Dernière édition:

Marcel32

XLDnaute Accro
J'ai des difficultés à voir où ce que tu as surligné de jaune comporte une erreur .
Je pense que Modeste veut montrer que :
le 01/03 étant le lendemain du 28/02, il ne devrait probablement y avoir qu'un seul jour d'écart entre les deux résultats surlignés et non 3 jours ou 4 jours.

Et plus généralement, les résultats de février (me) semblent faux par rapport aux résultats réellement attendus.
Mais peut-être sont-ils en fait corrects par rapport à ce qu'on t'a enseigné au primaire.
Perso, je ne saurais dire car je ne me souviens hélas pas du tout avoir reçu un tel enseignement. :(

[edit]
Je suppose que tu te trompes sur le calcul de la fin de mois, que tu dois toujours prendre comme étant égale à 31 (ou 30), au lieu de la calculer en fonction de la date donnée.
[/edit]
 
Dernière édition:

jmfmarques

XLDnaute Accro
cela, Marcel, c'est parce-que tu as encore des difficultés à comprendre les durées calendaires (j'en ai rappelé pourtant la convention) et tu t'embrouilles les pinceaux en te raccrochant indûment à des écarts temporels.

Je sais que ce n'est pas facile à comprendre, mais tu vas y arriver

Il te suffira de faire l'opération inverse (en application de cette convention) pour comprendre.
Regarde :
28/02/1999
+ 17 ans entiers calendaires --->> 28/02/2016
+ 1 mois entier calendaire--->> 28/03/1999
+ résidus jours temporels depuis le 28/3/1999 (8 jours) --->> 05/04/2016


01/03/1999

+ 17 ans entiers calendaires --->> 01/03/2016
+ 1 mois entier calendaire--->> 01/04/2016
+ résidus jours temporels depuis le 01/04/2016 (4 jours) --->> 05/04/2016
 
Dernière édition:

Marcel32

XLDnaute Accro
cela, Marcel, c'est parce-que tu as encore des difficultés à comprendre les durées calendaires (j'en ai rappelé pourtant la convention)
Parles-tu de ça :
Le calcul d'une durée calendaire est enseigné en cours élémentaire et est effectué sur ces bases :
- Détermination de la partie "principale" de la durée calendaire : elle est composée des entiers suivants, entre deux date/heure:
- nombres d'années calendaires entières (donc de date/heure à date/heure)
- nombre de mois calendaires entiers (donc de date/heure à date/heure)
Une fois cette partie principale déterminée (au bout du compte : une espèce d'âge anniversaire), elle est complétée par tous les "résidus", qui, eux, sont temporels et ne peuvent qu'être exprimés en jours, heures, minutes et secondes au delà de l' " anniversaire"

Pour moi ce n'est pas clair du tout car ça manque un peu de précision.

Mais tes deux exemples ci-dessus sont eux parfaitement clairs : j'ai enfin compris comment tu calcules tes "durées calendaires". :cool:
 

Discussions similaires

Statistiques des forums

Discussions
291 730
Messages
1 917 541
Membres
179 713
dernier inscrit
Ranya
Haut Bas