IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Algorithmes et structures de données Discussion :

Calcul de durée entre deux dates en années, mois, jours, heures, minutes, secondes et reste


Sujet :

Algorithmes et structures de données

  1. #1
    Invité
    Invité(e)
    Par défaut Calcul de durée entre deux dates en années, mois, jours, heures, minutes, secondes et reste
    Bonjour,
    J'essaie de mettre au point une fonction ou procédure pour calculer la durée entre deux date.

    J'espère que le code est admis ici parce que je serais incapable de produire autre chose.

    Ma procédure écrite avec le langage Ada prend 9 paramètre dont deux sont les dates à comparer, la date de début doit être inférieur à la date de fin.
    Celle- ci, doit retourner le nombre d'années, de mois de jour, et les heures avec les minutes les secondes et le reste (les millisecondes).

    Pour le moment, je souhaite faire expertiser pour avoir votre avis une version qui ne calcule que les années les mois et les jours.

    Avec les calculs sur les année bissextiles j'arrive à des truc rigolo comme 1 an 11 mois et 33 jours C'est pourquoi j'ai un doute.

    J'aimerais avoir votre avis.

    Voici mon code.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    with Ada.Integer_Text_Io;
    with Ada.Text_Io;
    with Ada.Calendar;
    use Ada.Calendar;
    with Ada.Calendar.Time_Zones;
    with Ada.Calendar.Formatting;
    with Ada.Calendar.Arithmetic;
    use Ada.Calendar.Arithmetic;
    use Ada;
    procedure Test_Elapsed is
     
       function Is_Leap_Year (Year : Integer) return Boolean is
       begin
          return (Year rem 4 = 0) and ((Year rem 100 /= 0) or (Year rem 16 = 0));
       end Is_Leap_Year;
     
       pragma Inline (Is_Leap_Year);
     
       Days_Months_Count : constant array (Month_Number) of Day_Number := (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
     
       procedure Difference_In_Years(Top_Date : in Time;
                                     Bot_Date : in Time;
                                     Years    : out Natural;
                                     Months   : out Natural;
                                     Days     : out Natural;
                                     Houres    : out Natural;
                                     Minutes  : out Natural;
                                     Second : out Natural;
                                     Rest     : out Natural) is      
     
     
          Top_Days_Total    : Day_Count := 0;
          Top_Seconds_Total : Duration := 0.0;
          Top_Leap_Seconds  : Leap_Seconds_Count := 0;            
     
          Bot_Days_Total    : Day_Count := 0;
          Bot_Seconds_Total : Duration := 0.0;
          Bot_Leap_Seconds  : Leap_Seconds_Count := 0;            
     
          Top_Seconds : Day_Duration := Seconds(Top_Date);
          Bot_Seconds : Day_Duration := Seconds(Bot_Date);
          Top_Day     : Day_Number := Day(Top_Date);
          Bot_Day     : Day_Number := Day(Bot_Date);
          Top_Year    : Year_Number := Year(Top_Date);
          Bot_Year    : Year_Number := Year(Bot_Date);
          Top_Month   : Month_Number := Month(Top_Date);
          Bot_Month   : Month_Number := Month(Bot_Date);
     
     
       begin
     
          if Top_Date > Bot_Date then
             raise Constraint_Error;
          end if;
     
          Years    := 0;
          Months   := 0;
          Days     := 0;
          Houres   := 0;
          Minutes  := 0;
          Second   := 0;
          Rest     := 0;
     
          if Top_Year < Bot_Year then                           
             Years := (Bot_Year - 1) - (Top_Year);                  
             if Bot_Month - 1 >= Top_Month then
     
                Months := 12 - ((Bot_Month) - (Top_Month));
             else
     
                Months := 12 - ((Top_Month) - (Bot_Month - 1));
             end if;
          else         
     
             Months := (Bot_Month - Top_Month);
          end if;      
     
          if Bot_Day - 1 > Top_Day then         
             if Top_Month > 1 then            
                Days := (Days_Months_Count(Top_Month-1) - Top_Day) + Bot_Day;
     
             else
                Days := (Days_Months_Count(Days_Months_Count'last) - Top_Day) + Bot_Day;
     
             end if;         
          elsif Bot_Day - 1 < Top_Day then
             if Top_Month < 12 then
     
                Days := (Days_Months_Count(Top_Month) - Top_Day) + (Bot_Day - 1);
                if Days = Days_Months_Count(Top_Month + 1) then
                   Text_Io.Put_Line("3.1");
                   Days := 0;
                end if;
             else
     
                Days := (Days_Months_Count(Days_Months_Count'first) - Top_Day) + (Bot_Day - 1);
                if Days = Days_Months_Count(1) then
     
                   Days := 0;
                end if;
             end if;         
          else
     
             if Is_Leap_Year(Bot_Year) then            
                if Bot_Month = 2 then               
                   if Bot_Day > Days_Months_Count(2) then
     
                      Days := 1;               
                   end if;
                else
                   if Top_Month > 1 then            
                      Days := (Days_Months_Count(Top_Month-1) - Top_Day) + Bot_Day - 1;
     
                   else
                      Days := (Days_Months_Count(Days_Months_Count'last) - Top_Day) + Bot_Day - 1;
     
                   end if;
                end if;
             end if;
          end if;      
     
       end Difference_In_Years;
     
     
     
       Top_Date : Time := Time_Of(2010, 01, 27, 18000.0);
       Bot_Date : Time := Time_Of(2012, 02, 29, 18000.0);
       Years    : Natural := 0;
       Months   : Natural := 0;
       Days     : Natural := 0;
       Houres    : Natural := 0;
       Minutes  : Natural := 0;
       Second : Natural := 0;
       Rest     : Natural := 0;
     
     
    begin
       Difference_In_Years(Top_Date,
                           Bot_Date,
                           Years,
                           Months,
                           Days,
                           Houres,
                           Minutes,
                           Second,
                           Rest);
       Text_Io.Put(Natural'Image(Years)(2..Natural'Image(Years)'Last));
       Text_Io.Put("y, ");
       Text_Io.Put(Natural'Image(Months)(2..Natural'Image(Months)'last));
       Text_Io.Put("m, ");
       Text_Io.Put(Natural'Image(Days)(2..Natural'Image(Days)'last));
       Text_Io.Put("d, ");
       Text_Io.Put(Natural'Image(Houres)(2..Natural'Image(Houres)'last));
       Text_Io.Put(':');
       Text_Io.Put(Natural'Image(minutes)(2..Natural'Image(Minutes)'last));
       Text_Io.Put(':');
       Text_Io.Put(Natural'Image(Second)(2..Natural'Image(Second)'last));
       Text_Io.Put('.');
       Text_Io.Put(Natural'Image(Rest)(2..Natural'Image(Rest)'last));
       Text_Io.Put('s' & Character'Val(10));  
    end Test_Elapsed;
    Ca programme affiche :

    1y, 11m, 33d, 0:0:0.0s

    Merci pour vos réponses.
    Dernière modification par Invité ; 01/02/2015 à 18h28. Motif: il manquait les données d'initialisation dans le code.

  2. #2
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 053
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 053
    Points : 9 392
    Points
    9 392
    Par défaut
    J'utilise le langage Windev... mais tu devrais pourvoir traduire facilement ce code :

    Fonction principale :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    d1, d2  est une Date
    d1 = "20110127"
    d2 = "20120229"
     
    nb_a, nb_m, nb_j est un entier
    (nb_a, nb_m, nb_j) = fdiff(d1,d2)
    ch est une chaîne
    ch = " %1 années %2 mois %3 jours"
    ch = ChaîneConstruit(ch, nb_a, nb_m, nb_j)
    Info(ch)
    fonction de calcul du nombre d'années / mois / jours :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     
    PROCEDURE fdiff(d1,d2)
    na, nm, nj est un entier
     
    a1, m1, j1, a2, m2, j2 est un entier
    a1 = d1..Année
    m1 = d1..Mois
    j1 = d1..Jour
    a2 = d2..Année
    m2 = d2..Mois
    j2 = d2..Jour
     
    na = ( a2-a1-1)
    SI m2 > m1 _OU_ ( m2= m1 _ET_ j2>= j1) ALORS 
    	na++
    SINON
    	m2 += 12
    FIN
    nm = m2-m1-1
    SI j2>= j1 ALORS 
    	nm++
    	nj = j2-j1
    SINON
    	nj = dernjour_moisprecedent( a2, m2, j2 ) - j1
    	SI nj < 0 ALORS nj = 0
    	nj += j2
    FIN
    RENVOYER ( na, nm, nj )
    Et enfin la procédure pour calculer le nombre de jours du mois précédent, en prenant en compte les années bissextiles :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    PROCEDURE dernjour_moisprecedent(a2,m2,j2)
     
    t est un tableau de 12 entiers
    t[1] = 31 ; t[2]  =  28 ; t[3]= 31 ; t[4] = 30 ; t[5] = 31 ; t[6] = 30 ; t[7] = 31 ; t[8] = 31 ; t[9] = 30 ; t[10] = 31 ; t[11] = 30 ; t[12] = 31
    SI m2 = 1 RENVOYER 31     //  si janvier, le mois précédent est décembre.
    SI m2<>3 ALORS RENVOYER t[m2-1]  // Si différent de mars, pas de problème. 
     
    // Année bissextile ?
    SI modulo(a2,4) <> 0 ALORS RENVOYER 28 
    SI modulo(a2,100) = 0 _ET_ modulo(a2, 400) <> 0 ALORS RENVOYER 28 
    RENVOYER 29
    N'oubliez pas le bouton Résolu si vous avez obtenu une réponse à votre question.

  3. #3
    Invité
    Invité(e)
    Par défaut
    Merci pour le code.

  4. #4
    Invité
    Invité(e)
    Par défaut
    Bonjour, (je suis réveillé).

    Donc, j'ai translaté le code, mais j'ai un problème.

    A la ligne 125, je me trouve avec un nombre mois négatif dès le premier test qui est un test entre deux date identique mais même en chageant l'année de début c'est la même erreur me semble t- il.

    Voici mon code complet (normalement compilable) :

    Code Ada : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
     
    with Ada.Integer_Text_Io;
    with Ada.Text_Io;
    with Ada.Calendar;
    use Ada.Calendar;
    with Ada.Calendar.Time_Zones;
    use Ada.Calendar.Time_Zones;
    with Ada.Calendar.Formatting;
    use Ada.Calendar;
    with Ada.Calendar.Arithmetic;
    use Ada.Calendar.Arithmetic;
    use Ada;
    procedure Elapsed_Years is
     
       procedure Print_Elapsed(Top_Date : in Time;
                               Bot_Date : in Time;
                               Years    : in Natural;
                               Months   : in Natural;
                               Days     : in Natural;
                               Houres   : in Natural;
                               Minutes  : in Natural;
                               Second   : in Natural;
                               Rest     : in Natural) is
       begin
          Text_Io.Put("Pour l'interval entre le " &
                        Formatting.Image(Top_Date, False, UTC_Time_Offset(Top_Date)) & " et le " &
                        Formatting.Image(Bot_Date, False, UTC_Time_Offset(Bot_Date)) & " le temps à écoulé ");
          Text_Io.Put(Natural'Image(Years)(2..Natural'Image(Years)'Last));
          Text_Io.Put("y, ");
          Text_Io.Put(Natural'Image(Months)(2..Natural'Image(Months)'last));
          Text_Io.Put("m, ");
          Text_Io.Put(Natural'Image(Days)(2..Natural'Image(Days)'last));
          Text_Io.Put("d");
       end Print_Elapsed;
     
     
     
       function Is_Leap_Year (Year : Integer) return Boolean is
       begin
          return (Year rem 4 = 0) and ((Year rem 100 /= 0) or (Year rem 16 = 0));
       end Is_Leap_Year;
     
       pragma Inline (Is_Leap_Year);
     
       Days_Months_Count : constant array (Month_Number) of Day_Number := (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
     
       procedure Difference_In_Years(Top_Date : in Time;
                                     Bot_Date : in Time;
                                     Years    : out Natural;
                                     Months   : out Natural;
                                     Days     : out Natural;
                                     Houres   : out Natural;
                                     Minutes  : out Natural;
                                     Second   : out Natural;
                                     Rest     : out Natural) is
     
     
     
          function Last_Days(Years , Months, Days : in Natural) return Natural is
          begin
     
             if Months = 1 then
                return Days_Months_Count(12);
             end if;
     
             if Months /= 3 then
                return Days_Months_Count(Months-1);
             end if;
     
             if Is_Leap_Year(Years) then
                return Days_Months_Count(2) + 1;
             else
                return Days_Months_Count(2);
             end if;
          end Last_Days;
     
     
          Top_Days_Total    : Day_Count := 0;
          Top_Seconds_Total : Duration := 0.0;
          Top_Leap_Seconds  : Leap_Seconds_Count := 0;
     
          Bot_Days_Total    : Day_Count := 0;
          Bot_Seconds_Total : Duration := 0.0;
          Bot_Leap_Seconds  : Leap_Seconds_Count := 0;
          Top_Seconds : Day_Duration := Seconds(Top_Date);
          Bot_Seconds : Day_Duration := Seconds(Bot_Date);
          Top_Day     : Day_Number := Day(Top_Date);
          Bot_Day     : Day_Number := Day(Bot_Date);
          Top_Year    : Year_Number := Year(Top_Date);
          Bot_Year    : Year_Number := Year(Bot_Date);
          Top_Month   : Month_Number := Month(Top_Date);
          Bot_Month   : Month_Number := Month(Bot_Date);
     
          Years_Number  : Integer := 0;
          Months_Number : Integer := 0;
          Days_Number   : Integer := 0;
     
       begin
     
          if Top_Date > Bot_Date then
             raise Constraint_Error;
          end if;
     
          Years    := 0;
          Months   := 0;
          Days     := 0;
          Houres   := 0;
          Minutes  := 0;
          Second   := 0;
          Rest     := 0;
     
          Years_Number := (Bot_Year - Top_Year - 1);
     
     
          if (Bot_Month > Top_Month) or ((Bot_Month = Top_Month) and (Bot_Day >= Top_Day)) then
     
             Years := Years_Number + 1;
     
          else
     
             Months_Number := Bot_Month + 12;
     
             Years := Years_Number;
          end if;
     
          Months_Number := Months_Number - Top_Month - 1;
     
          if Bot_Day >= Top_Day then
     
             Months := Months_Number + 1;
     
             Days := Bot_Day - Top_Day;
          else
     
             Days_Number := Last_Days (Bot_Year, Months_Number, Bot_Day) - Top_Day;
     
             if Days_Number < 0 then
               Days := Days_Number + Bot_Day;
     
             end if;
     
             Months := Months_Number;
          end if;
       end Difference_In_Years;
     
     
       Top_Date : Time := Time_Of(2009, 03, 28, 18000.0);
       Bot_Date : Time := Time_Of(2011, 05, 30, 18000.0);
       Years    : Natural := 0;
       Months   : Natural := 0;
       Days     : Natural := 0;
       Houres    : Natural := 0;
       Minutes  : Natural := 0;
       Second : Natural := 0;
       Rest     : Natural := 0;
     
     
       type Elapsed_Type is
          record
             Top_Date : Time;
             Bot_Date : Time;
          end record;
     
       Test_Set : array (1..14) of Elapsed_Type:=
         ((Time_Of(2009, 05, 15, 0.0), Time_Of(2009, 05, 15, 0.0)),
          (Time_Of(2009, 04, 15, 0.0), Time_Of(2011, 05, 1, 0.0)),
          (Time_Of(2009, 05, 15, 0.0), Time_Of(2011, 04, 1, 0.0)),
          (Time_Of(2009, 04, 1, 0.0), Time_Of(2011, 05, 15, 0.0)),
          (Time_Of(2012, 02, 1, 0.0), Time_Of(2015, 03, 1, 0.0)),
          (Time_Of(2012, 02, 1, 0.0), Time_Of(2015, 01, 31, 0.0)),
          (Time_Of(2012, 02, 29, 0.0), Time_Of(2015, 01, 31, 0.0)),
          (Time_Of(2012, 03, 1, 0.0), Time_Of(2015, 02, 28, 0.0)),
          (Time_Of(2012, 03, 1, 0.0), Time_Of(2016, 02, 29, 0.0)),
          (Time_Of(2012, 02, 28, 0.0), Time_Of(2014, 12, 31, 0.0)),
          (Time_Of(2012, 02, 29, 0.0), Time_Of(2015, 1, 1, 0.0)),
          (Time_Of(2012, 02, 28, 0.0), Time_Of(2012, 02, 29, 0.0)),
          (Time_Of(2013, 02, 28, 0.0), Time_Of(2015, 3, 1, 0.0)),
          (Time_Of(2012, 02, 2, 0.0), Time_Of(2015, 3, 1, 0.0)));
     
    begin
       for Elapsed in Test_Set'Range loop
          Difference_In_Years(Test_Set(Elapsed).Top_Date,
                              Test_Set(Elapsed).Bot_Date,
                              Years,
                              Months,
                              Days,
                              Houres,
                              Minutes,
                              Second,
                              Rest);
          Print_Elapsed(Test_Set(Elapsed).Top_Date,
                        Test_Set(Elapsed).Bot_Date,
                        Years,
                        Months,
                        Days,
                        Houres,
                        Minutes,
                        Second,
                       Rest);
          Text_Io.New_Line;
       end loop;
     
    end Elapsed_Years;


    Il y a un petit jeu supplémentaire entre les entier et les naturel parce que ma procédure retourne des naturel alors que j'ai bien compris qu'on pouvais obtenir des jours négatifs avec cet algo, mais pas les mois, ou j'ai pas compris, en tout cas j'ai un problème.

    Merci pour votre aide.

  5. #5
    Invité
    Invité(e)
    Par défaut
    Yep !


    J'ai trouvé deux choses.

    La première c'est qu'il manque l'affectation de Bot_Month dans le premier "if" à Monts_Number.

    La seconde est dans la fonction derniers_jour du mois précédant, le second if devrait me semble t- il faire l'objet d'en elsif. En tout cas avec Ada.

    Je vais analyser les résultat maintenant que ça passe et je reviens éventuellement.

    En tout cas merci encore pour le code. j'étais en galère pas possible.

    Merci.

    Et même une troisième, j'ai oublié entre parenthèse le Top_Month - 1 :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Months_Number := Months_Number - (Top_Month - 1);

  6. #6
    Invité
    Invité(e)
    Par défaut
    J'espère avoir ici apporté des corrections plutôt que des erreurs.

    J'ai cherché, euh une vingtaine de minutes heure peut-être, voici le corps de la procédure, avec les corrections des corrections.

    Code Ada : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
     
       begin
     
          if Top_Date > Bot_Date then
             raise Constraint_Error;
          end if;
     
          Years    := 0;
          Months   := 0;
          Days     := 0;
          Houres   := 0;
          Minutes  := 0;
          Second   := 0;
          Rest     := 0;
     
          Years_Number := (Bot_Year - Top_Year - 1);
     
          if (Bot_Month > Top_Month) or ((Bot_Month = Top_Month) and (Bot_Day >= Top_Day)) then         
     
             Years_Number := Years_Number + 1;
             Months_Number := Bot_Month;
          else         
             Months_Number := Bot_Month + 12;
          end if;
     
     
          Months_Number := (Months_Number - Top_Month - 1);
     
          if Bot_Day >= Top_Day then
     
             Months_Number := Months_Number + 1;
             Days_Number := Bot_Day - Top_Day;
          else
             Days_Number := Last_Days (Bot_Year, Months_Number + 1) - Top_Day;                           
             if Days_Number < 0 then
                Days_Number := Days_Number + Bot_Day;
             end if;                  
          end if;
          Days := Days_Number;
          Months := Months_Number;
          Years := Years_Number;
       end Difference_In_Years;

    Alors je ne sais pas ou tu en est avec votre procédure Windev, mais c'est sensiblement différent.
    Est- ce du au priorités des opérateur ?

    Voici le résultat, si vous trouvez une erreur merci de me le faire savoir.

    Pour l'interval entre le 2009-05-15 et le 2009-05-15 le temps à écoulé 0y, 0m, 0d,
    Pour l'interval entre le 2009-04-15 et le 2011-05-01 le temps à écoulé 2y, 0m, 16d,
    Pour l'interval entre le 2009-05-15 et le 2011-04-01 le temps à écoulé 1y, 10m, 16d,
    Pour l'interval entre le 2009-04-01 et le 2011-05-15 le temps à écoulé 2y, 1m, 14d,
    Pour l'interval entre le 2012-02-01 et le 2015-03-01 le temps à écoulé 3y, 1m, 0d,
    Pour l'interval entre le 2012-02-01 et le 2015-01-31 le temps à écoulé 2y, 11m, 30d,
    Pour l'interval entre le 2012-02-29 et le 2015-01-31 le temps à écoulé 2y, 11m, 2d,
    Pour l'interval entre le 2012-03-01 et le 2015-02-28 le temps à écoulé 2y, 11m, 27d,
    Pour l'interval entre le 2012-03-01 et le 2016-02-29 le temps à écoulé 3y, 11m, 28d,
    Pour l'interval entre le 2012-02-28 et le 2014-12-31 le temps à écoulé 2y, 10m, 3d,
    Pour l'interval entre le 2012-02-29 et le 2015-01-01 le temps à écoulé 2y, 10m, 2d,
    Pour l'interval entre le 2012-02-28 et le 2012-02-29 le temps à écoulé 0y, 0m, 1d,
    Pour l'interval entre le 2013-02-28 et le 2015-03-01 le temps à écoulé 2y, 0m, 3d,
    Pour l'interval entre le 2012-02-02 et le 2015-03-01 le temps à écoulé 3y, 0m, 29d,

  7. #7
    Invité
    Invité(e)
    Par défaut Une petite erreur de ma par qui régularise le code de tbc92
    Re- bonjour,

    Me revoilà avec mes excuses, j'ai fait une petite erreur à l'appel de Last_Days, avec Months_Number + 1, qui est normalement Bot_Months. Et ça change le résultat qui était erroné.

    Merci tbc92. Merci beaucoup même.

  8. #8
    Invité
    Invité(e)
    Par défaut Fin et solution
    Pour ceux que ça intéresserait avec Ada il suffis d'ajouter les lignes suivantes pour avoir l'heure.

    Code ada : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    --
          if Bot_Seconds >= Top_seconds then
             Total_Duration := (Bot_Seconds - Top_Seconds);
          else
             Total_Duration := (86400.0 - Top_Seconds) + Bot_Seconds;
             Days := Days - 1;
          end if;
          Formatting.Split(Total_Duration, Houres, Minutes, Second, Rest);

    Voilà pour moi c'est terminé.

  9. #9
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 243
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 243
    Points : 13 458
    Points
    13 458
    Par défaut
    Bonjour,

    et donc? Combien y a-t-il d'heures entre le 24 octobre 2015 à 16h32 et le 25 octobre 2015 à 16h32 ?
    Il y a 1 jour et 0 heure entre le 24 octobre 2015 à 16h32 et le 25 octobre 2015 à 16h32.
    Il y a 1 jour et 0 heure entre le 23 octobre 2015 à 16h32 et le 24 octobre 2015 à 16h32.

    En conclus-tu que les durées sont égales ?
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  10. #10
    Modérateur
    Avatar de kolodz
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2008
    Messages
    2 211
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 211
    Points : 8 316
    Points
    8 316
    Billets dans le blog
    52
    Par défaut
    Si tu prends cet exemple, c'est n'est pas pour rien. C'est le changement d'heure (été/hiver).
    Il y a donc 25H dans l'un des cas et 24 dans l'autre cas.

    Il y a d'autre cas tordus, genre le 29 févier, la seconde intercalaire.

    De manière général, il est préférable de se basé sur une librairie qui a déjà été tester et approuver. En particulier quand tu cherche à avoir des écarts avec quelque chose autre que des secondes (où l'utilisation des timestamp fonctionne.)

    Si ce n'est pas possible (car n'existe pas dans ton langage), il y a deux possibilités :
    • Reprendre mot à mot un librairie qui fait ça proprement.
    • Se passer de cette fonctionnalité.

    Si tu compte reprendre quelque chose qui le fait déjà bien. Il y a par exemple JodaTime en Java (Maintenant intégré au standard Java en grande partie).

    Cordialement,
    Patrick Kolodziejczyk.

    Source :
    http://fr.wikipedia.org/wiki/Heure_d%27%C3%A9t%C3%A9
    http://fr.wikipedia.org/wiki/29_f%C3%A9vrier
    http://fr.wikipedia.org/wiki/Seconde_intercalaire
    Si une réponse vous a été utile pensez à
    Si vous avez eu la réponse à votre question, marquez votre discussion
    Pensez aux FAQs et aux tutoriels et cours.

  11. #11
    Invité
    Invité(e)
    Par défaut
    Je comprends, a priori je n'ai pas besoin de ces nuances.

  12. #12
    Invité
    Invité(e)
    Par défaut
    Code ada : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
     
      procedure Difference_In_Years(Top_Date : in Time;
                                     Bot_Date : in Time;
                                     Years    : out Natural;
                                     Months   : out Natural;
                                     Days     : out Natural;
                                     Houres   : out Natural;
                                     Minutes  : out Natural;
                                     Second   : out Natural;
                                     Rest     : out Duration) is      
     
          function Is_Leap_Year (Year : Integer) return Boolean is
          begin
             return (Year rem 4 = 0) and ((Year rem 100 /= 0) or (Year rem 16 = 0));
          end Is_Leap_Year;
     
          pragma Inline (Is_Leap_Year);
     
          Days_Months_Count : constant array (Month_Number) of Day_Number := (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
     
     
          function Last_Days(Years , Months : in Natural) return Natural is         
          begin         
             if Months = 1 then
                return Days_Months_Count(12);
             elsif Months /= 3 then
                return Days_Months_Count(Months-1);
             end if;
     
             if Is_Leap_Year(Years) then
                return Days_Months_Count(2) + 1;
             else
                return Days_Months_Count(2);
             end if;
          end Last_Days;
     
     
          Top_Seconds : constant Day_Duration := Seconds(Top_Date);
          Bot_Seconds : constant Day_Duration := Seconds(Bot_Date);
          Top_Day     : constant Day_Number := Day(Top_Date);
          Bot_Day     : constant Day_Number := Day(Bot_Date);
          Top_Year    : constant Year_Number := Year(Top_Date);
          Bot_Year    : constant Year_Number := Year(Bot_Date);
          Top_Month   : constant Month_Number := Month(Top_Date);
          Bot_Month   : constant Month_Number := Month(Bot_Date);
     
          Years_Number  : Integer := 0;
          Months_Number : Integer := 0;
          Days_Number   : Integer := 0;            
     
          Total_Duration : Duration := Bot_Seconds - Top_Seconds;
       begin
     
          if Top_Date > Bot_Date then
             raise Constraint_Error;
          end if;
     
          Years    := 0;
          Months   := 0;
          Days     := 0;
          Houres   := 0;
          Minutes  := 0;
          Second   := 0;
          Rest     := 0.0;
     
          Years_Number := (Bot_Year - Top_Year - 1);
     
          Months_Number := Bot_Month;
     
          if (Bot_Month > Top_Month) or ((Bot_Month = Top_Month) and (Bot_Day >= Top_Day)) then         
     
             Years_Number := Years_Number + 1;
     
          else         
             Months_Number := Bot_Month + 12;
          end if;
     
          Months_Number := (Months_Number - Top_Month - 1);
     
          if Bot_Day >= Top_Day then
     
             Months_Number := Months_Number + 1;
             Days_Number := Bot_Day - Top_Day;
          else
             Days_Number := Last_Days (Bot_Year, Bot_Month) - Top_Day;
             if Days_Number < 0 then
                Days_Number := Days_Number + Bot_Day;
             end if;                  
          end if;
          Days := Days_Number;
          Months := Months_Number;
          Years := Years_Number;
     
          if Bot_Seconds >= Top_seconds then
             Total_Duration := (Bot_Seconds + Top_Seconds) - 86400.0;
    	 Days := Days + 1;
          else
             Total_Duration := (86400.0 - Top_Seconds) + (Bot_Seconds);
          end if;
          Formatting.Split(Total_Duration, Houres, Minutes, Second, Rest);         
       end Difference_In_Years;


    Some corrections.

  13. #13
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Comme nous somme un premier jour de mois, je me suis dis, tiens je vais tester mon alarme et par la tester la fonction Difference_in_year.

    Du coup ça marchait pas alors j'ai entrepris quelque correction, ou modification.
    Voici mon nouveau code avec Ada :
    Code ada : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    procedure Difference_In_Years(Top_Date : in Time;
                                     Bot_Date : in Time;
                                     Years    : out Natural;
                                     Months   : out Natural;
                                     Days     : out Natural;
                                     Houres   : out Natural;
                                     Minutes  : out Natural;
                                     Second   : out Natural;
                                     Rest     : out Duration) is      
     
          function Is_Leap_Year (Year : Integer) return Boolean is
          begin
             return (Year rem 4 = 0) and ((Year rem 100 /= 0) or (Year rem 16 = 0));
          end Is_Leap_Year;
     
          pragma Inline (Is_Leap_Year);
     
          Days_Months_Count : constant array (Month_Number) of Day_Number := (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
     
     
          function Last_Days(Years , Months : in Natural) return Natural is         
          begin         
             if Months = 1 then
                return Days_Months_Count(12);
             elsif Months /= 3 then
                return Days_Months_Count(Months-1);
             end if;
     
             if Is_Leap_Year(Years) then
                return Days_Months_Count(2) + 1;
             else
                return Days_Months_Count(2);
             end if;
          end Last_Days;
     
     
          Top_Seconds : constant Day_Duration := Seconds(Top_Date);
          Bot_Seconds : constant Day_Duration := Seconds(Bot_Date);
          Top_Day     : constant Day_Number := Day(Top_Date);
          Bot_Day     : constant Day_Number := Day(Bot_Date);
          Top_Year    : constant Year_Number := Year(Top_Date);
          Bot_Year    : constant Year_Number := Year(Bot_Date);
          Top_Month   : constant Month_Number := Month(Top_Date);
          Bot_Month   : constant Month_Number := Month(Bot_Date);
     
          Years_Number  : Integer := 0;
          Months_Number : Integer := 0;
          Days_Number   : Integer := 0;            
        Total_Duration : Duration := Bot_Seconds - Top_Seconds;
       begin
     
          if Top_Date > Bot_Date then
             raise Constraint_Error;
          end if;
     
          Years    := 0;
          Months   := 0;
          Days     := 0;
          Houres   := 0;
          Minutes  := 0;
          Second   := 0;
          Rest     := 0.0;
     
          Years_Number := (Bot_Year - Top_Year - 1);
     
          Months_Number := Bot_Month;
     
          if (Bot_Month > Top_Month) or ((Bot_Month = Top_Month) and (Bot_Day >= Top_Day)) then         
     
             Years_Number := Years_Number + 1;
     
          else         
             Months_Number := Bot_Month + 12;
          end if;
     
          Months_Number := (Months_Number - Top_Month - 1);
     
     
          if Bot_Day > Top_Day then
     
             Months_Number := Months_Number + 1;
             Days_Number := Bot_Day - Top_Day;
     
          elsif Bot_Day < Top_Day then
     
             Days_Number := Last_Days (Bot_Year, Bot_Month) - Top_Day;
             if Days_Number < 0 then
                Days_Number := Days_Number + Bot_Day;
             end if;    
     
          else
             Months_Number := Months_Number + 1;
             Days_Number := 0;
          end if;
     
     
          Days := Days_Number;
          Months := Months_Number;
          Years := Years_Number;
     
          if Bot_Seconds > Top_seconds then
             Total_Duration := (Bot_Seconds - Top_Seconds);
          elsif Bot_Seconds < Top_Seconds then
             Total_Duration := (86400.0 - Top_Seconds) + Bot_Seconds;
     
          else
             Total_Duration := 0.0;
     
          end if;
          Formatting.Split(Total_Duration, Houres, Minutes, Second, Rest);         
       end Difference_In_Years;

    Merci encore à Tbc92.

  14. #14
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    En fait, si tu veux faire ça proprement, il faut utiliser le Calendrier Julien, et en particulier le Jour julien.

    C'est ce qui sert de base en astronomie, et ce qui est à la base des conversions par exemple local/utc dans les ordis..


    Dans le lien tu as même les algos de conversion...
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  15. #15
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    Donc !

    Je reposte juste les dernières ligne de mon code qui fonctionnais encore pas.
    Code ada : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
          if Bot_Day > Top_Day then
     
             Months_Number := Months_Number + 1;
             Days_Number := Bot_Day - Top_Day;
     
          elsif Bot_Day < Top_Day then
     
             Days_Number := Last_Days (Bot_Year, Bot_Month) - Top_Day;
             if Days_Number < 0 then
                Days_Number := Days_Number + Bot_Day;
             end if;    
     
          else
             Months_Number := Months_Number + 1;     
             Days_Number := 0;
          end if;
     
     
          Days := Days_Number;
          Months := Months_Number;
          Years := Years_Number;
     
          if Bot_Seconds > Top_seconds then
             Total_Duration := (Bot_Seconds - Top_Seconds);  
          elsif Bot_Seconds < Top_Seconds then
             Total_Duration := (86400.0 - Top_Seconds) + Bot_Seconds;                
             Days := Days - 1;
          else
             Total_Duration := 0.0;  
          end if;
          Formatting.Split(Total_Duration, Houres, Minutes, Second, Rest);         
       end Difference_In_Years;

    Voilà, normalement ça marche.

  16. #16
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 485
    Points
    5 485
    Par défaut
    Citation Envoyé par jovalise Voir le message
    Celle- ci, doit retourner le nombre d'années, de mois de jour, et les heures avec les minutes les secondes et le reste (les millisecondes).
    Citation Envoyé par jovalise Voir le message
    Je comprends, a priori je n'ai pas besoin de ces nuances.
    Tu as besoin d'une précision à la milliseconde et pourtant tu n'as pas besoin de prendre en compte les changements d'heures et les secondes intercalaires ?

    Ou bien n'as-tu au final besoin que d'une précision au jour près ? Mais même dans ce cas, est-il acceptable que ta durée puisse diminuer ? Par exemple une échéance à 2h10 du matin pourrait se produire une fois, incrémentant le nb de jours, avant de diminuer lors du changement d'heure. Plus généralement une date à 2h10 du matin désigne t-elle la première ou la seconde occurrence de cette heure-ci ?

    Tu es bien sûr de ne pas avoir besoin de ces nuances ?

  17. #17
    Invité
    Invité(e)
    Par défaut
    Bonjour, ....


    A priori oui.

    Je suis en UTC. Je ne considère donc aucun changement d'heure.

  18. #18
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 485
    Points
    5 485
    Par défaut
    Citation Envoyé par jovalise Voir le message
    Je suis en UTC. Je ne considère donc aucun changement d'heure.
    Ok. Et tu peux également te permettre d'accumuler une erreur de quelques secondes par décennie sur la durée physique du fait des secondes intercalaires ?

    Par ailleurs es-tu certain d'avoir des dates UTC correctes ? Si un utilisateur stipule le "1er décembre à 9h00", sous-entendu dans le fuseau local (non-UTC), le 1er décembre se trouvera dans une autre chronologie qu'aujourd'hui (du fait du chgt d'heure). La conversion vers UTC sera t-elle correcte ?

    Note d'ailleurs qu'il est impossible d'obtenir une conversion local -> UTC fiable pour une date future : des changements légaux peuvent intervenir. Tout comme il est impossible de prédire le nombre de secondes intercalaires entre une date UTC passée et une date UTC future.

  19. #19
    Invité
    Invité(e)
    Par défaut
    Non plus.
    C'est vraiment minimal comme besoin.
    De plus je pense qu'il faudrait, au cas ou je calcule ces secondes, les calculer également au moment de fixer le compte à reboure.

    Si il est 00:00:00.0 et que je fixe un délais de 00:00:01.0 et que pendant cette seconde j'en ajoute une, il faut que j'ajoute une seconde à mon délais pour conserver 1 seconde de delais.

    Donc non, ça m'intéresse pas plus que ça.


    Note d'ailleurs, qu je code avec Ada, et Ada défini une journée avec 86400 seconde au milième près.

    Si les jours devais diminuer au augmenter, Ada le spécifierais, et je n'ai pas à m'en préocuper mais je vois à la réflexion que j'ai un litéral qui fait référence à cette valeur, je vais corriger.

  20. #20
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 485
    Points
    5 485
    Par défaut
    Citation Envoyé par jovalise Voir le message
    De plus je pense qu'il faudrait, au cas ou je calcule ces secondes, les calculer également au moment de fixer le compte à reboure.
    Tu ne pourrais pas : les secondes intercalaires futures sont inconnues. On ne connaît que celles du passé.

    Pour un compte à rebours dont on aurait spécifié exactement la durée la façon propre (mais peut-être inutile dans ton cas) serait de stocker la date de départ et la durée requise.

    A chaque tic on calculerait la durée écoulée entre maintenant et la date de départ, en utilisant une base de données des secondes intercalaires (ou le service temporel de l'OS, qui garde déjà ces données). Puis on calculerait la différence entre le temps écoulé et la durée spécifiée.


    Note d'ailleurs, qu je code avec Ada, et Ada défini une journée avec 86400 seconde au milième près.

    Si les jours devais diminuer au augmenter, Ada le spécifierais
    Mais certains jours durent exceptionnellement 86401s. Comme le 30 juin dernier. Ce sont des secondes qui sont ajoutés au besoin pour prendre en compte les variations imprévisibles de la rotation terrestre. C'est le principe des secondes intercalaires. Et à l'avenir certains jours dureront peut-être 86402s ou 86399s, on ne peut pas savoir.

Discussions similaires

  1. Réponses: 5
    Dernier message: 24/08/2015, 16h46
  2. Réponses: 14
    Dernier message: 11/12/2013, 14h59
  3. Réponses: 1
    Dernier message: 30/04/2008, 11h00
  4. Réponses: 10
    Dernier message: 14/12/2007, 14h13

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo