Date et heure ConvertSeconds

Magic_Doctor

XLDnaute Barbatruc
J'en avais besoin, donc je l'ai fait. Mais je pense que l'on peut faire plus simple.
VB:
Function ConvertSeconds(sec#) As String
'Converti des desondes en années | jours | heures | minutes | secondes
'Magic_Doctor

    Dim a#, j#, h As Byte, mn As Byte, s As Byte, suf1$, suf2$
    
    j = Int(sec / 86400)
    a = Int(j / 365)
    h = Int((sec - j * 86400) / 3600)
    mn = Int(((sec - j * 86400) / 3600 - h) * 60)
    s = Int((((sec - j * 86400) / 3600 - h) * 60 - mn) * 60)
    j = j - a * 365
    suf1 = IIf(a = 0, "", IIf(a = 1, " an", " ans"))
    suf2 = IIf(j = 0, "", IIf(j = 1, " jour", " jours"))
    
    ConvertSeconds = IIf(a = 0, "", a & suf1 & " ") & IIf(j = 0, "", j & suf2 & " ") & IIf(h < 10, "0", "") & h & ":" & IIf(mn < 10, "0", "") & mn & ":" & IIf(s < 10, "0", "") & s
End Function
 

patricktoulon

XLDnaute Barbatruc
Bonjour @Marcel32
même erreur;)

dites moi pour quelle raison farfelue?????:oops::oops::oops:
la partie timevalue
du résultat de sec/86400 devrait changer en fonction du choix 1,2,3

choix 1
1654408634570.png


choix 2
1654408549458.png


choix 3
1654408707751.png
 

TooFatBoy

XLDnaute Barbatruc
dites moi pour quelle raison farfelue?????:oops::oops::oops:
la partie timevalue
du résultat de sec/86400 devrait changer en fonction du choix 1,2,3
Oui je sais, ça paraît bizarre, mais c'est comme ça.
C'est normal : ça vient du calcul qui utilise des durées moyennes pour l'année ou le mois. ;)

Comme l'a très bien expliqué le Doc, le résultat est une durée correspondant parfaitement à la durée initiale , uniquement quand on reste en jours, heures, minutes et secondes.
Quand on passe au mois ou à l'année, on utilise des durées moyennes, donc le résultat n'est plus une durée correspondant exactement à la durée initiale, mais une durée de type calendaire, donc approximative.

Le sujet a été abordé de nombreuses fois ici et ailleurs. ;)


[edit]
Quand on utilise des valeurs simples, c'est encore plus évident à comprendre :
Capture_du_2022-06-05_a_08-33-51.png

[/edit]
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
re
perso je préfère les valeurs exactes
et le code en est que plus simple
VB:
Function convertsecondP(Sec#, Optional choix% = 1)
res = Format(CDate(Sec / 86400) + 2, "dd/mm/yyyy hh:nn:ss")
y = Year(res) - 1900
m = Month(res): If m = 1 Then m = 0
j = Day(res) - 1

Debug.Print Sec & " de secondes  la date ca donne :" & res & " donc "; y & " an(s) révolu(s) et " & m & " mois révolu(s) " & j & " jour(s) révolu(s) et " & TimeValue(res)
End Function

Sub test()
convertsecondP 6 '6 secondes
convertsecondP 60 '60 secondes (1 minute)
convertsecondP 3600 ' 1 heure
convertsecondP 86400 ' 1 journée
convertsecondP 864000 ' 10 jours
convertsecondP 1000000000
convertsecondP 31557600
End Sub
1654416219110.png

après je veux bien admettre le calcul approximatif mais en aucun cas le timevalue doit être différent
1 secondes c'est 100 centièmes de secondes
1 minute c'est 60 secondes
1 journée c'est 24 h 00:00 révolues

et pour les puristes décaler la date a 1904
;)
 

TooFatBoy

XLDnaute Barbatruc
perso je préfère les valeurs exactes
Moi aussi. ;)
Mais comme c'est impossible ici de calculer une valeur exacte, la meilleure méthode me semble être d'utiliser des valeurs moyennes pour l'année et le mois.

1 secondes c'est 100 centièmes de secondes
1 minute c'est 60 secondes
1 journée c'est 24 h 00:00
Ca me semble être une évidence, c'est pour ça que le Doc et moi utilisons ces valeurs. ;)

L'année étant officiellement égale à 365,25 jours, quand on atteint 1 an, on introduit un "décalage" de 1/4 de jour, c'est-à-dire 6 heures (ce qui est parfaitement visible dans l'image de #17).

Le mois étant 1/12 de l'année, on a un "décalage" de 1/4/12 = 1/48 jour = 1/2 heure = 30 minutes.



Cette méthode permet de lisser ce "décalage", par rapport à l'utilisation d'une date de départ arbitraire qui va introduire 1 jour de décalage selon que l'on parte d'une année bissextile ou non.



C'est mon opinion actuelle, mais moi aussi ça me chagrine de voir des heures qui changent selon l'option 1, 2, ou 3, choisie. Donc peut-être que demain j'aurais une opinion différente.
Rien n'est perdu pour un camp comme pour l'autre... 😁
 

Katido

XLDnaute Occasionnel
Le besoin initial, c'est de calculer les jours et il faut s'en tenir là. C'est facile et toujours juste, sachant qu'un jour comporte toujours 86 400 secondes.

L'année 2022 comporte 31 536 000 s alors que 2000 en comportait 31 622 400. De même un mois n'a pas toujours la même durée, tout le monde le sait. Donc une formule qui convertit des secondes en mois et années ne peut être que bâtarde, tout en fournissant une précision illusoire. Même pas la peine de faire une macro...

En revanche, on peut calculer la date précise (avec heures, minutes et secondes) de l'instant qui correspond à 1000 000 000 secondes après une date donnée. Ou encore la durée écoulée entre 2 dates.
Par exemple 1000 000 000 secondes après le 5 juin 2022 à minuit sonnant est donné par dateadd("s", 1000000000, #06/05/2022#), ce qui donne 11/02/2054 01:46:40.
Il ne faut pas confondre date et durée.
 

patricktoulon

XLDnaute Barbatruc
re
oui dateadd marche aussi
c'est ce que je dis depuis le debut
les fonctions date de vb font très bien leur boulot quand on sait s'en servir
pas la peine de faire des calculs approximatifs qui donnent 3 durées différentes selon le choix d'unité an mois jour

ce que j'ai essayé d'expliquer
en aucune facon même avec un calcul approximatif sous divers format le timecode doit être différent

je re cite notre ami le docteur
Exemple :
1.000.000.000 secondes correspondent à (suivant l'option choisie dans le paramétrage de la fonction) :
- 11574 jours 01:46:40
- 31 ans 251 jours 07:46:40
- 31 ans 8 mois 7 jours 19:46:40
dans les trois versions on a des jours révolus donc le timecode doit Etre identique

si tant est que 11574 jours ou 31 ans et 251 jours ou 31 ans 5 mois et 7 jours soit la même durée alors les heures minutes secondes doivent être les mêmes

juste une question de logique ;)


si il ne l'est pas c'est que la formule est fausse
 
Dernière édition:

TooFatBoy

XLDnaute Barbatruc
juste une question de logique ;)


si il ne l'est pas c'est que la formule est fausse
La formule n'est absolument pas fausse.

Relis à tête reposée les différentes explications données et tu comprendras que c'est juste une façon différente de calculer quelque chose qui n'est pas vraiment calculable, ou du moins qui ne peut donner qu'un résultat approximatif et non exact.

Mais je comprends ton blocage à admettre comme valable les résultats des différentes formules selon le choix effectué. ;)
 

Magic_Doctor

XLDnaute Barbatruc
Bonsoir Marcel32,

Pas la peine de discuter, c'est inutile...
Le raisonnement est bon, les formules (que ce soient les tiennes ou les miennes) sont bonnes.
Depuis le début de ce fil que j'ai ouvert, je précise bien que seule la 1ère option (celle des jours) renvoie un résultat exact. Les deux autres, puisque l'on utilise des "années moyennes" et des "mois moyens", renvoient des résultats approximatifs (très proches de la réalité), un peu, ma foi, comme le carbone14. Quand on choisit des années + jours ou années + mois + jours, la fraction de jour à partir de laquelle on extraie les heures, minutes et secondes sera forcément différente de celle obtenue exactement avec uniquement les jours.
Une chose est certaine, c'est que, pour bien faire, il faut conserver, quelle que soit l'option, les mêmes heures, minutes et secondes que celle obtenues avec uniquement les jours. Pour ce faire, j'ai revu ma fonction en trichant un peu. Au fait, tous les noms des variables de la fonction sont expliqués en REM et sont (par leurs acronymes) assez explicites. Mais j'avoue que ta solution est nettement plus élégante.
Une dernière précision. En déclarant la variable A (années) comme double et non plus comme integer, la fonction gère un nombre de secondes allant très au-delà du billion, sans plantage.
VB:
Function ConvertSeconds(Nbsec#, Optional chx As Byte = 1) As String
'*******************************************************************************
'Converti des secondes en jours | heures | minutes | secondes ou
'                         années | jours | heures | minutes | secondes ou
'                         années | mois | jours | heures | minutes | secondes
'Magic_Doctor
'*******************************************************************************
'- Nbsec : un nombre de secondes
'- chx   : si 1 ou omis --> jours | heures | minutes | secondes
'          si 2         --> années | jours | heures | minutes | secondes
'          si 3         --> années | mois | jours | heures | minutes | secondes
'*******************************************************************************

    Dim tj#, A#, M As Byte, J#, H As Byte, Mn As Byte, Sec As Byte
    Dim sufAns$, sufJours$, ta#, fa#, jfa#, tm#, fm#, jfm#, fj#, sfj#, hfj#, fh#, mfh#
 
    tj = Nbsec / 86400      'nombre (décimal) total de jours (secondes converties en jours)
    J = Int(tj)             'nombre entier de jours dans Nbsec
    fj = tj - J             'fraction de jour
    sfj = fj * 86400        'nombre de secondes dans la fraction de jour
    hfj = sfj / 3600        'nombre (décimal) d'heures dans la fraction de jour
 
    '********** Dans tous les cas, véritables heures, minutes & secondes **********
    H = Int(hfj)            'nombre entier d'heures dans la fraction de jour
    fh = hfj - H            'fraction d'heure
    mfh = fh * 60           'nombre (décimal) de minutes dans la fraction d'heure
    Mn = Int(mfh)           'nombre entier de minutes dans la fraction d'heure
    Sec = (mfh - Mn) * 60   'nombre de secondes dans la fraction de minute
    '******************************************************************************
 
    ta = tj / 365.25        'nombre (décimal) total d'années (365,25 = nombre moyen de jours dans une année)
    A = Int(ta)             'nombre entier d'années
    fa = ta - A             'fraction d'année
    jfa = fa * 365.25       'nombre (décimal) de jours dans la fraction d'année
 
    If chx = 1 Then         'jours | heures | minutes | secondes
        A = 0               'on ne tient pas compte des années
    ElseIf chx = 2 Then     'années | jours | heures | minutes | secondes
        J = Int(jfa)        'nombre entier de jours dans la fraction d'année
        sufAns = IIf(A = 0, "", IIf(A = 1, " an ", " ans "))
    Else                    'années | mois | jours | heures | minutes | secondes
        tm = jfa / 30.4375  'nombre (décimal) total de mois (30,4375 = nombre moyen de mois dans une année)
        M = Int(tm)         'nombre entier de mois
        fm = tm - M         'fraction de mois
        jfm = fm * 30.4375  'nombre de jours dans la fraction de mois
        J = Int(jfm)        'nombre entier de jours dans la fraction de mois
        sufAns = IIf(A = 0, "", IIf(A = 1, " an ", " ans "))
    End If
    sufJours = IIf(J = 0, "", IIf(J = 1, " jour ", " jours "))
    ConvertSeconds = IIf(A = 0, "", A & sufAns) & IIf(M = 0, "", M & " mois ") & IIf(J = 0, "", J & sufJours) & IIf(H < 10, "0", "") & H & ":" & IIf(Mn < 10, "0", "") & Mn & ":" & IIf(Sec < 10, "0", "") & Sec
End Function
Soit, pour 10^9 secondes :
- 11574 jours 01:46:40
- 31 ans 251 jours 01:46:40
- 31 ans 8 mois 7 jours 01:46:40
 
Dernière édition:

TooFatBoy

XLDnaute Barbatruc
Une chose est certaine, c'est que, pour bien faire, il faut conserver, quelle que soit l'option, les mêmes heures, minutes et secondes que celle obtenues avec uniquement les jours.
On pourrait le faire en traitant à part la partie inférieure à 24 heures mais, perso, je n'ai pas voulu le faire car on s'éloignerait de la valeur "la plus juste" au niveau du résultat, même si instinctivement ce dernier paraîtrait au contraire "plus juste".

En tout cas, merci pour ton travail. 👍


@+
🖖
 

Magic_Doctor

XLDnaute Barbatruc
Bonsoir,

Récapitulons ce thriller cybernétique.
Deux points de vues : Magic_Doctor vs patricktoulon.
La fonction de Magic_Doctor fonctionne généralement et ne nécessite aucune date de référence. Le problème, c'est que la fonction, dépendant de valeurs moyennes pour les années et les mois, va forcément renvoyer un résultat approximatif mais, somme toute, très proche de la réalité.
La fonction de patricktoulon, elle, dépend d'une date de référence (à savoir le 01/01/1900) et renvoie logiquement un résultat exact. Le problème, avec cette solution, c'est que l'on est condamnés à avoir un résultat qui dépend toujours de cette date de référence, même plus d'un siècle après ladite date.
En conséquence, je me suis dit que la solution idéale serait de reprendre le principe de la date de référence mais en ayant la liberté de choisir cette date. Et si on omettait de la mettre en paramétrage de la fonction, alors s'imposerait tout simplement la date du jour.
VB:
Function SecondsAfterDate(Nbsec#, Optional chx As Byte = 1, Optional Date_Depart As Date) As String
'**********************************************************************************
'Converti des secondes en jours | heures | minutes | secondes ou
'                         années | jours | heures | minutes | secondes ou
'                         années | mois | jours | heures | minutes | secondes
'Renvoi la date correspondant à une date + x jours
'Magic_Doctor
'**********************************************************************************
'- Nbsec : un nombre de secondes
'- chx   : si 1 ou omis --> jours | heures | minutes | secondes
'          si 2         --> années | jours | heures | minutes | secondes
'          si 3         --> années | mois | jours | heures | minutes | secondes
'          si 4         --> Date_Depart + le nombre de jours correspondant à Nbsec
'- Date_Depart : une date de référence (>= 01/01/1900) à partir de laquelle
'                s'effectuent tous les calculs
'**********************************************************************************
  
    Dim tj#, J#, A#, M As Byte, H As Byte, Mn As Byte, Sec As Byte
    Dim fj#, sfj#, hfj#, fh#, mfh#, sufAns$, sufJours$
    Dim MaDate As Date, Date_Fin As Date, fecha As Date
 
    MaDate = IIf(Date_Depart = 0, Date, Date_Depart)  'gracias Marcel32
  
    tj = Nbsec / 86400      'nombre (décimal) total de jours (secondes converties en jours)
    J = Int(tj)             'nombre entier de jours dans Nbsec
    fj = tj - J             'fraction de jour
    sfj = fj * 86400        'nombre de secondes dans la fraction de jour
    hfj = sfj / 3600        'nombre (décimal) d'heures dans la fraction de jour

    '************* Dans tous les cas, véritables heures, minutes & secondes ************
    H = Int(hfj)            'nombre entier d'heures dans la fraction de jour
    fh = hfj - H            'fraction d'heure
    mfh = fh * 60           'nombre (décimal) de minutes dans la fraction d'heure
    Mn = Int(mfh)           'nombre entier de minutes dans la fraction d'heure
    Sec = (mfh - Mn) * 60   'nombre de secondes dans la fraction de minute
   
    If Sec = 60 Then Sec = 0: Mn = Mn + 1  'correction des sec & mn au cas où Sec = 60
    '***********************************************************************************

    Date_Fin = DateAdd("d", J, MaDate) 'date de départ + nb jours
  
    If chx = 1 Then         'jours | heures | minutes | secondes
        A = 0               'on ne tient pas compte des années
        M = 0               'on ne tient pas compte des mois
    ElseIf chx < 4 Then
        A = DateDiff("yyyy", MaDate, Date_Fin)                   'nb d'années entre les 2 dates
        A = IIf(DateAdd("yyyy", A, MaDate) > Date_Fin, A - 1, A) 'nb réel d'années entre les 2 dates
        fecha = DateAdd("yyyy", A, MaDate)                       'date de départ + nb d'années
        If chx = 2 Then                                          'années | jours | heures | minutes | secondes
            M = 0                                                'on ne tient pas compte des mois
            J = Date_Fin - fecha                                 'nb de jours
        ElseIf chx = 3 Then                                                         'années | mois | jours | heures | minutes | secondes
            M = DateDiff("m", fecha, Date_Fin)                                      'nb de mois
            fecha = DateAdd("m", M, fecha)                                          'date de départ + nb d'années + nb de mois
            fecha = IIf(Day(fecha) > Day(Date_Fin), DateAdd("m", -1, fecha), fecha) 'date de départ + nb d'années + nb de mois CORRIGÉE
            J = Date_Fin - fecha                                                    'nb de jours
        End If
    Else  'date de départ + nb jours
        SecondsAfterDate = Date_Fin: Exit Function
    End If

    sufAns = IIf(A = 0, "", IIf(A = 1, " an ", " ans "))
    sufJours = IIf(J = 0, "", IIf(J = 1, " jour ", " jours "))
  
    SecondsAfterDate = IIf(A = 0, "", A & sufAns) & IIf(M = 0, "", M & " mois ") & IIf(J = 0, "", J & sufJours) & IIf(H < 10, "0", "") & H & ":" & IIf(Mn < 10, "0", "") & Mn & ":" & IIf(Sec < 10, "0", "") & Sec
End Function
J'ai rajouté un choix fondamental, celui qui permet à la fonction de renvoyer la date correspondant à la date de référence + x secondes. Ça peut être intéressant pour rajouter, en dehors des sempiternels anniversaires mortels, l'anniversaire du milliard ou des deux milliards, voire des 3 milliards de secondes. Et hop, une fête en plus !
Par exemple, votre vieille tante Gertrude, née le 26 août 1927, fêtera ses 3 000 000 000 de secondes le 18 septembre de cette année, soit 95 ans, 1 mois & 24 jours (les heurse, minutes & secondes, là on s'en tamponnera le coquillard). Quelle fiesta en perspective !
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
re
oui c'est deja beaucoup mieux
par contre le fait que ca dépende de la date 01/01/1900 ou une autre c'est pareil
tu n'a pas compris mon raisonnement en fait

en gros je résume
il n'y a pas de calcul a faire soit math soit datediff etc....(pour an/mois/jour)
une seule ligne
VB:
Sub test()
Sec = 3 * 10 ^ 9
ladate = CDate(Sec / 86400) + 1
Debug.Print ladate
Debug.Print Format(ladate, "yy"" an(s) ""mm"" mois ""dd"" jour(s) "" et ") & TimeValue(CDate(Sec / 86400))
End Sub

donc pour résumer
une seule ligne de code est suffisante pour obtenir le résultat
voici pour les trois (chacune dans une sub )
VB:
Sub start()
test1EnAnneeMoisJour
test2EnJour
test3EnMoisJour
End Sub

Sub test1EnAnneeMoisJour()
Sec = 3 * 10 ^ 9
ladate = CDate(Sec / 86400) + 1
Debug.Print ladate
Debug.Print Format(ladate, "yy"" an(s) ""mm"" mois ""dd"" jour(s) "" et ") & TimeValue(CDate(Sec / 86400))
End Sub

Sub test2EnJour()
Sec = 3 * 10 ^ 9
ladate = CDate(Sec / 86400) + 1
Debug.Print DateDiff("d", CDate("01/01/1900"), ladate) - 1 & "jour(s) et " & TimeValue(CDate(Sec / 86400))
End Sub

Sub test3EnMoisJour()
Sec = 3 * 10 ^ 9
ladate = CDate(Sec / 86400) + 1
mois = DateDiff("m", CDate("01/01/1900"), ladate) - 1
Debug.Print mois & "  mois et " & Day(ladate) & " jour(s)  et " & TimeValue(CDate(Sec / 86400))
End Sub
1654839098113.png


et encore même si j'obtiens le même résultat que toi c'est faux (on devrait enlever 1 mois)
car le 24/01/xxxx (le mois de janvier n'est pas terminé donc pas révolu et pareil pour le jour aussi car 5heure 20 du matin le jour n'est pas fini donc au 24/01/xxxx à 5 heure 20 on a 23 jours révolus et 5heures20

après effectivement tout les chemins mènent a Rome
;)
 
Dernière édition:

Magic_Doctor

XLDnaute Barbatruc
Re,

Je reconnais que, même s'il ne sert pas à grand chose, le problème est à la fois intéressant et tordu.
Pour 3*10^9 sec :
- en partant du 01/01/1900 j'obtiens :
95 ans 1 mois 24 jours 05:20:00
- en partant de la date anniversaire de la vieille tante Gertrude, soit le 26/08/1927 :
95 ans 1 mois 23 jours 05:20:00
- en partant de la date d'aujourd'hui, soit le 10/06/2022 :
95 ans 1 mois 24 jours 05:20:00

En revanche, quelle que soit la date de départ, le nombre de jours est 34722 jours.
 

TooFatBoy

XLDnaute Barbatruc
- en partant du 01/01/1900 j'obtiens :
95 ans 1 mois 24 jours 05:20:00
- en partant de la date anniversaire de la vieille tante Gertrude, soit le 26/08/1927 :
95 ans 1 mois 23 jours 05:20:00
- en partant de la date d'aujourd'hui, soit le 10/06/2022 :
95 ans 1 mois 24 jours 05:20:00
Oui, et ça prouve ce qu'on disait précédemment : c'est une méthode de calcul qui est plus fausse que celle utilisant les durées moyennes des années et mois, puisqu'elle dépend de la date de départ (ce qui introduit donc un jour d'écart selon la date de départ), contrairement à la méthode utilisant les moyennes qui est forcément celle donnant le meilleur résultat puisqu'elle n'introduit que d'éventuels écarts plus faibles (1/4 jour ou 1/2 heure), même ce résultat peut paraître bizarre à première vue quand on n'y réfléchi pas.

Mais bon là, au pire on régresse, au mieux on tourne en rond, si on repart vers une méthode donnant un résultat moins bon...
 

patricktoulon

XLDnaute Barbatruc
re
en effet

si on part de la naissance de la vielle tente on a 34722 jours et ça tombe juste en calcul inverse aussi
si on part de la date 01/01/1900 on a 34720 jours et ça tombe juste en calcul inverse aussi

bon il faut prendre en compte les année bissextiles que l'on a dans l'intervalle bien sur
qui ne seront pas les mêmes si la date de depart n'est pas la même
pour moi la différence est trop grande pour prendre en compte l'un ou l'autre

par contre tu ne prends pas en compte le( jour et ou mois) révolu(s)
exemple
pour le le 23/01/1995 05:20:00
c'est bien 95 ans 0 mois et 22 jours et 5 heures 20
ou 1140 mois et 5 heures 20

avec ta méthode on tombe le
Code:
x=cdate("26/08/1927")+(3*10^9/86400)
resultat=18/09/2022 05:20:00
ce qui nous fait 95 ans 8 mois 17 jours et 5 h 20 et non pas 09 mois et 18 jours
 

Discussions similaires

Membres actuellement en ligne

Statistiques des forums

Discussions
314 749
Messages
2 112 461
Membres
111 553
dernier inscrit
cecilou47