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

Langage Delphi Discussion :

Lister les mois-année entre deux dates données


Sujet :

Langage Delphi

  1. #1
    Membre éprouvé
    Avatar de Andry
    Profil pro
    Informaticien
    Inscrit en
    Juillet 2002
    Messages
    1 164
    Détails du profil
    Informations personnelles :
    Localisation : Madagascar

    Informations professionnelles :
    Activité : Informaticien

    Informations forums :
    Inscription : Juillet 2002
    Messages : 1 164
    Points : 1 181
    Points
    1 181
    Par défaut Lister les mois-année entre deux dates données
    Salut à tous.
    J'ai un petit souci depuis hier que j'arrive pas à résoudre.
    J'ai deux date Debut et Fin et j'aimerais lister le mois-année entre ces deux date par exemple en faire un tableau de chaine.
    Par exemple
    Début : 01/11/2007
    Fin : 31/03/2008
    qui va donner
    11-2007
    12-2007
    01-2008
    02-2008
    03-2008
    Comment y arriver.

    Merci pour votre aide.

  2. #2
    Membre chevronné

    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    1 519
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 1 519
    Points : 2 153
    Points
    2 153
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    Je pense que tu peux t'en tirer avec les DecodeDate pour récupérer le mois et année des dates puis incrémenter "intelligemment" ces valeurs pour générer les différentes dates jusqu'à atteindre la date de fin.

  3. #3
    Membre éprouvé
    Avatar de Andry
    Profil pro
    Informaticien
    Inscrit en
    Juillet 2002
    Messages
    1 164
    Détails du profil
    Informations personnelles :
    Localisation : Madagascar

    Informations professionnelles :
    Activité : Informaticien

    Informations forums :
    Inscription : Juillet 2002
    Messages : 1 164
    Points : 1 181
    Points
    1 181
    Par défaut
    J'ai pensé à faire comme ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    for an = YearOf(Debut) to YearOf(Fin) do
    begin
      for ms = MonthOf(Debut) to MonthOf(Fin) do
      begin
        Ligne[i] := Format('%d-%d',[ms,an]);
      end;
    end;
    mais helas, je viens de decouvrir que ça ne marche pas dans tous les cas.
    Je vais essayer de voir avec DecodeDate.

    Correction. Ceci à l'aire de marcher
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    Var 
       DebMois,FinMois : TDateTime;
     begin
        DebMois := DateDebut;
        DebMois := StartOfTheMonth(datedebut);
        FinMois   := DateFin;
        FinMois   := EndOfTheMonth(datefin);
        While (DebMois <= FinMois) do
        begin
          Ligne[i] := Format('%d-%d',[MonthOf(DebMois,yearOf(DebMois)]);
          DebMois := IncMonth(DebMois ,1);
    A Tester
    A+

  4. #4
    Membre chevronné

    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    1 519
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 1 519
    Points : 2 153
    Points
    2 153
    Billets dans le blog
    1
    Par défaut
    C'est ce que je disais par faire un incrément "intelligent"

    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
    var
      JourDeb, JourFin, MoisDeb, MoisFin, AnDeb, AnFin: Word;
    begin
      DecodeDate( DateDebut, AnDeb, MoisDeb, JourDeb );
      DecodeDate( DateFin, AnFin, MoisFin, JourFin );
     
      while ( MoisDeb <> MoisFin ) and ( AnDeb <> AnFin )
      begin
        Ligne[i] := Format('%d-%d',[MoisDeb, AnDeb]);
        Inc( MoisDeb );
        if MoisDeb > 12 then
        begin
          Inc( AnDeb );
          MoisDeb := 1;
        end;
      end;
     
      Ligne[i] := Format('%d-%d',[MoisFin, AnFin]);
     
    end;

  5. #5
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    pour ma part je ferais une fonction un peu plus générique qui énumère les dates d'un interval spécifié en les renvoyant dans une liste.

    l'enumeration dans ce thread concerne les mois, mais bon autant étendre la fonction pour énumérer des jours, des heures....

    on défini le type servant à notre énumeration et le prototype de la fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
      TEnumType = (etMois, etJour, etHeure, etMinute); //et ainsi de suite
     
      function EnumDateTime(ADebut, AFin: TDateTime; AType: TEnumType): TList;
    maintenant on s'occupe de la fonction qui va enumérer un interval en fonction du type que l'on veut. on utilisera l'unité DateUtils, pourquoi ? parce que on manipule des dates et qu'elle est sensé être utile dans ce cas
    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
     
     
    function EnumDateTime(ADebut, AFin: TDateTime; AType: TEnumType): TList;
    var
      D: TDateTime;
      P: PDateTime;
    begin
      D := Debut;
      Result := TList.Create;
      while D < Fin do 
      begin
        New(P);
        P^ := D;
        Result.Add(P);
        case AType of
          etMois: D := IncMonth(D);
          etJour: D := IncDay(D);
          etHeure: D := IncHour(D);
          etMinute: D :=IncMinute(D);
          //... et ainsi de suite etSecond, etMillisecond
        end;
      end;
    end;
    voila c'est fini...simple non?
    comment on l'utilise? c'est trés simple aussi:

    exemple: une form, un memo et un bouton
    dans l'évenement OnClick du bouton:

    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
     
    procedure TfrmDemo.Button1Click(Sender: TObject);
    var
      L: TList;
      P: Pointer;
    begin
      L := EnumDateTime(Now, Now + 310, etMois); //énumere les mois 
      try
        for P in L do //on énumère la liste
        begin
          memo1.Lines.Add(FormatDateTime('mm-yyyy', TDateTime(P^))); //affiche la date avec le bon format
          Dispose(P); //libere proprement car on a plus besoin
        end;
      finally
        L.Free; //libere la liste
      end;
    end;
    dans le cas d'une énumeration des jours entre ces 2 dates, il suffit de remplacer etMois par etJour
    et le format d'affichage de la date en 'dd-mm-yyyy'

    voilà une bonne base pouvant être amélioré...
    une amélioration possible par exemple:
    si les dates sont négatives (cad la date de référence de Delphi), et que l'on énumère les heures, ou minute ou seconde....alors on a un problème. du coup il faut jouer avec le ReplaceTime ou un truc dans le genre.

    "Simple is beautiful"

  6. #6
    Membre éprouvé
    Avatar de Andry
    Profil pro
    Informaticien
    Inscrit en
    Juillet 2002
    Messages
    1 164
    Détails du profil
    Informations personnelles :
    Localisation : Madagascar

    Informations professionnelles :
    Activité : Informaticien

    Informations forums :
    Inscription : Juillet 2002
    Messages : 1 164
    Points : 1 181
    Points
    1 181
    Par défaut

    Très bonne démonstration Kafeine.

    Bref ça marche très bien. j'ai du juste modifier le code d'énumération de la liste car ça na pas l'aire de marché avec mon Delphi 7.

    Super . Je vais garder ce bout de code au chaud car je suis actuellement entrain de faire une appli qui manipule intensivement des dates etc.

    Encore merci.

  7. #7
    Membre expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 561
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 561
    Points : 3 955
    Points
    3 955
    Par défaut
    Hi men,

    Je pense que la solution d'Andry est la plus simple et a priori la plus facile à maintenir, ce qui est un bon point.

    La méthode de Kaféine est valable pour les compilateurs Delphi les plus récents (> Delphi 7 ; absence d'énumérateur avec for, apporté par .Net, dans les versions jusqu'à D7). En outre, je suis critique quant à la libération de mémoire distante de l'allocation initiale. C'est, je trouve, assez risqué surtout si la maintenance du code n'est pas assurée par le créateur du code. C'est une source d'oubli et de bug difficile à résoudre. J'adore les pointeurs mais de manière raisonnée, ici je pense que c'est superflu. Ceci dit c'est tout de même une solution qui peut être envisagée.

    Cdlt

  8. #8
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    Salut,

    Citation Envoyé par e-ric
    Je pense que la solution d'Andry est la plus simple et a priori la plus facile à maintenir
    j'en déduit que ma solution n'est pas la plus simple et n'est pas facile à maintenir...Du coup mon "Simple is beautiful" tombe à l'eau (snif).
    Je me rend compte que les pointeurs te font peur (Peut être un passé douloureux avec eux, je sais pas peut être une aggression ou un viol par une bande de pointeurs
    enragés :\ )

    Bon d'abord j'arrête les plaisanteries à 2 balles.

    Citation Envoyé par e-ric
    ...valable pour les compilateurs Delphi les plus récents...
    Comme l'a dit Andry, il suffit de de remplacer le "For .. In" par un simple "For I := 0 To .. Do". Et Hop Delphi <= 7 Compatible.

    Citation Envoyé par e-ric
    je trouve, assez risqué surtout si la maintenance du code n'est pas assurée par le créateur du code
    Je suis d'accord, mais normalement il y a un commentaire qui accompagne la fonction facilitant la maintenance. Et le développeur sait interpréter un commentaire et
    un prototype de fonction...au pire il va voir l'implémentation de la fonction.

    Citation Envoyé par e-ric
    J'adore les pointeurs mais de manière raisonnée...
    Ha, Finalement ils te font pas peur j'en suis ravi.

    Citation Envoyé par e-ric
    ici je pense que c'est superflu
    Complétement d'accord. Rien n'empèche d'écrire (avant D2009, sinon on utilise les génériques) un dériver un TList typé TDateTime ou que la fonction un Array de TDateTime.

    Essayons cette approche:
    D'abord la liste de TDateTime

    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
     
      TDateTimeList = class(TList)
      private
        function GetDate(Index: Integer): TDateTime;
      public
        property Dates[Index: Integer]: TDateTime read GetDate;
        function Add(ADate: TDateTime): Integer;
        procedure Clear; override;
      end;
     
    implementation
     
    { TDateTimeList }
     
    function TDateTimeList.Add(ADate: TDateTime): Integer;
    var
      P: PDateTime;
    begin
      New(P);
      P^ := ADate;
      Result := inherited Add(P);
    end;
     
    procedure TDateTimeList.Clear;
    var
      I: Integer;
    begin
      for I := 0 to Count - 1 do
        Dispose(Items[I]);
      inherited;
    end;
     
    function TDateTimeList.GetDate(Index: Integer): TDateTime;
    begin
      Result := TDateTime(inherited Get(Index)^);
    end;
    Maintenant on modifie EnumDatetime:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    function EnumDateTime(ADebut, AFin: TDateTime; AType: TEnumType): TDateTimeList;
    Bon pas la peine remettre l'implementation ici elle reste la même a part le type TList remplacé par TDateTimeList et on vire les pointeurs.
    voila on arrive à une solution acceptable je pense et compatible delphi toutes versions (ou au moins D7)
    Testons:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    var
      L: TDateTimeList;
      I: Integer;
    begin
      L := EnumDateTime(EncodeDate(2009, 1, 1), EncodeDate(2009, 1, 31), etJour);
      try
        for I := 0 to L.Count - 1 do
          memo1.Lines.Add(FormatDateTime('dd:mm:yyyy', L.Dates[I]));
      finally
        L.Free;
      end;
    Maintenant, mise en situation...(ceci est une fiction, toutes ressemblances avec des faits réèlles seraient fortuits...)

    Chef: Kaféine !!!
    Kaféine: Oui Chef !
    Chef: Je veux pouvoir énumérer des années....et ceci pour hier!
    Kaféine: ok mais j'ai pas le temps pour le moment car je dois déjà laver les moniteurs des collègues...
    Chef: m'en fous tu te démerde !! (c'est un chef vulgaire)

    faisons évoluer cette procédure EnumDateTime qui se trouve normalement dans le répertoire "Utils" du framework de l'appli, dans une unité qui doit avoir "Date" dans son nom.

    Kaféine: Bordel y'a pas de commentaire dans cette fonction...bon ca va c'est pas trop compliqué.
    J'ai juste à ajouter 1 type supplémentaire dans l'enumération et 1 case...

    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
     
    TEnumType = (etAnnee, etMois, etJour, etHeure, etMinute);
     
    function EnumDateTime(ADebut, AFin: TDateTime; AType: TEnumType): TDateTimeList;
    var
      D: TDateTime;
    begin
      Result := TDateTimeList.Create;
      D := ADebut;
      while D <= AFin do
      begin
        Result.Add(D);
        case AType of
          etAnnee: D := IncYear(D);
          etMois: D := IncMonth(D);
          etJour: D := IncDay(D);
          etHeure: D := IncHour(D);
          etMinute: D := IncMinute(D);
        end;
      end;
    end;
    Voilà...
    Un petit Défi pour finir parce que l'on peut toujours améliorer l'existant: Enumérer les trimestres ou les semestres entre 2 dates....ou bien nettoyez votre moniteur

    A+

  9. #9
    Membre expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 561
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 561
    Points : 3 955
    Points
    3 955
    Par défaut
    Hi,

    Il y a du bien fondé dans ce que tu dis. Mais bon, par rapport au problème posé par Andry, cela me paraissait trop raffiné. On peut effectivement imaginer un petit framework facilitant le travail sur les dates et heures avec un peu de facilité. C'est un réflexe naturel de développeur, je suis bien placé pour le savoir.

    En tout cas, nous pouvons remercier Kaféine pour son expérience et son contribution au débat.

    Cdlt

  10. #10
    Membre éprouvé
    Avatar de Andry
    Profil pro
    Informaticien
    Inscrit en
    Juillet 2002
    Messages
    1 164
    Détails du profil
    Informations personnelles :
    Localisation : Madagascar

    Informations professionnelles :
    Activité : Informaticien

    Informations forums :
    Inscription : Juillet 2002
    Messages : 1 164
    Points : 1 181
    Points
    1 181
    Par défaut
    Yes.

    Super code Kafeine.
    Je pense que cela mérite une place dans la section source du site.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Toutes versions] Déterminer le nombre de jours pour chaque année fiscale, entre deux dates données
    Par mikeactuaire dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 09/09/2011, 12h42
  2. Réponses: 8
    Dernier message: 05/06/2009, 17h07
  3. [MySQL] Écart années entre deux dates
    Par romeskira dans le forum PHP & Base de données
    Réponses: 4
    Dernier message: 09/10/2008, 08h25
  4. Réponses: 2
    Dernier message: 02/07/2007, 16h52
  5. selectionner une borne de dates entre deux dates données
    Par itchyjojo dans le forum Requêtes et SQL.
    Réponses: 1
    Dernier message: 18/05/2007, 07h07

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