Problème de formatage de date avec awk strftime

Bonjour,

Je travail avec la version 20 de Mint.

Voici ma ligne de commande :
awk -F"," '{ print strftime("%Y-%m-%d %H:%M:00 ",$1),$2,$3 }' TestDate.txt

où
$1
correspond à :
 '01-Jun-18 12:00:00 AM EDT'
.

Le résultat de la commande donne :
1969-12-31 19:00:00
pour tous les enregistrements de mon fichier. Si j'utilise
systime()
à la place de
$1
ça marche.

Pourtant avec la commande date le système reconnaît cette date :
01-Jun-18 12:00:00 AM EDT
, et je peux passer au format 24h. Ce qui est mon objectif car windows 10 avec Excel ne reconnait pas ce format de date
01-Jun-18 12:00:00 AM EDT
.

Avez-vous une idée pour résoudre ce problème.

Merci

10 réponses

  1. Jusqu'à présent je suis arrivé à traiter un fichier de 32000 lignes.

    J'ai essayé différents éditeurs, et le plus complet pour moi est bpython, qui tourne dans un terminal (vérification de syntaxe, autocomplétion).
    0
    1. Modérateur
      Attention il ne faut pas confondre interpréteur et éditeur.
      • Un interpréteur permet de taper et d'exécuter des commandes python. Lesdites commandes ne sont pas écrites dans un fichier, elles sont juste en mémoire. Parmi eux, on peut citer les plus classiques :
        • python3
          (resp.
          python
          pour Python2) est l'interpréteur standard en mode texte, utilisé pour exécuter un programme ;
        • ipython3
          (resp.
          ipython
          pour Python2) qui est proche de
          bpython
          plus évolué ;
        • .
          jupyter-notebook
          et son successeur
          jupyterlab
          sont deux interpréteurs, tout deux construits au dessus de
          ipython3
          qui s'utilisent dans un navigateur web après avoir lancé le serveur correspondant.
      • Un éditeur permet de créer et modifier un ou des fichiers textes (en particulier Python). Sous linux la plupart des éditeurs sont bien plus évolués que le bloc note de windows et fournissent des fonctionnalités proches de notepad++ : coloration syntaxique, indentation intelligente, etc.
        • les éditeurs génériques en mode texte sont
          nano
          ,
          vim
          ,
          emacs
          . Ces deux derniers sont suffisamment évolué pour offrir une auto-complétion sémantique ;
        • les éditeurs génériques graphiques sont
          gedit
          ,
          kwrite
          ;
        • .l'environnement graphique de développement (IDE) traditionnellement utilisé en python est
          pycharm
          mais ne prend son intérêt que pour un projet python impliquant plusieurs fichiers (sinon un éditeur moins évolué fait amplement l'affaire).


      Bonne chance
      0
  2. Dabord merci,

    Quel éditeur utilisez-vous avec Python ?

    De plus, je suis impressionné par votre disponibilté, c'est presqu'un cours privé.

    Pour ma part, j'ai terminé mon scrit
    gawk
    le voici.

    awk -F, '

    {gsub(/-Jan-/, "-01-"); gsub(/-Feb-/, "-02-"); gsub(/-Mar-/, "-03-"); gsub(/-Apr-/, "-04-"); gsub(/-May-/, "-05-"); gsub(/-Jun-/, "-06-"); gsub(/-Jul-/, "-07-"); gsub(/-Aug-/, "-08-"); gsub(/-Sep-/, "-09-"); gsub(/-Oct-/, "-10-"); gsub(/-Nov-/, "-11-"); gsub(/-Dec-/, "-12-")}
    {
    split($1,a,/[-: ]/);
    ts = sprintf("%4d %02d %02d %2d %2d %2d", a[3]~ /[0-9][0-9]/ ? a[3]+2000: a[3], a[2], a[1], a[7] ~ /^[Pp]/ ? a[4]+12 : a[4], a[5], a[6]);
    MaDate = strftime("%Y-%m-%d %H:%M:%S", mktime(ts))
    }
    {print MaDate ,$2,$3}' HighWall2020.csv | gawk ' { gsub(/\s12:/, " 25:"); gsub(/\s00/, " 12") ;gsub(/\s25:/, " 00:") } { print $1,$2"\t"$3"\t"$4}' | tee Nom.txt
    0
    1. Modérateur
      Quel éditeur utilisez-vous avec Python ?

      Celui que tu veux, un script python n'est qu'un fichier texte (comme n'importe quel fichier texte), dont l'extension est par convention
      .py
      .

      De plus, je suis impressionné par votre disponibilté, c'est presqu'un cours privé.

      Ho, c'est juste que là je dépile mes messages et que tu tombes à la bonne heure, mais oui j'essaye de regarder régulièrement ce qui se passe sur le forum.

      Pour ma part, j'ai terminé mon scrit gawk le voici.

      Merci de l'avoir partagé :-)
      0
  3. Savez-vous s'il y a une limite de taille de fichier (ex: 96000 lignes) avec gawk ?
    0
    1. Modérateur
      Non je ne sais pas. Teste et tu verras bien :-)
      0
  4. Pourquoi deux fois datetime.datetime. dans le code Python?
    0
    1. Modérateur
      Parce que c'est la classe datetime importée depuis le module datetime. Il se trouve que le nom du module et de la classe sont les mêmes.

      Note qu'il serait aussi possible d'écrire :

      from datetime import datetime
      
      def translate_date(s_in):
          format_in = "%d-%b-%y %I:%M:%S %p EDT"
          format_out = "%Y-%m-%d %H:%M:%S"
          return datetime.strptime(s_in, format_in).strftime(format_out)


      Et donc ici
      strptime
      est une méthode statique de l'objet
      datetime
      (importé depuis le module
      datetime
      )
      0
  5. J'ai ça comme résultat avec
    gawk
    :

    gawk -F, '
    {
    split($1,a,/[-: ]/);
    ts = sprintf("%4d %02d %02d %2d %2d %2d", a[3], a[2], a[1], a[7] ~ /^[Pp]/ ? a[4]+12 : a[4], a[5], a[6]);
    MaDate = strftime("%Y-%m-%d %H:%M:%S", mktime(ts))
    }
    {print MaDate ,$2,$3}' TestDate.txt


    Mais il y a un problème avec
     ~ /^[Pp]/ ? a[4]+12
    parce que le résultat me donne 12 heure pour minuit et 00 pour midi. Je vais avoir besoin d'une exception.

    comme ceci :
    2018-06-01 11:30:00 20.8 54.8
    2018-06-01 11:45:00 20.9 55.5
    2018-06-02 00:00:00 21 56
    2018-06-02 00:15:00 21 55.8
    2018-06-02 00:30:00 20.9 55.5
    2018-06-02 00:45:00 20.9 55.5
    2018-06-01 13:00:00 20.8 55.4
    2018-06-01 13:15:00 20.8 55.3

    Donc j'ai ma date avec l'heure, la température et l'humidité.

    Je suis très comptant de voir votre script. Je vais l'étudier très attentivement.

    Un gros merci pour votre disponibilité. Si vous avez le temps de regarder ma commande gawk cela me ferais grand plaisir.
    0
    1. Modérateur
      Mais il y a un problème avec ~ /^[Pp]/ ? a[4]+12 parce que le résultat me donne 12 heures pour minuit et 00 pour midi. Je vais avoir besoin d'une exception.

      Oui donc dans l'idée tu regardes s'il est écrit quelque chose qui commence par P ou p (comme pm) pour décider si tu dois ajouter douze heures. Ce n'est pas parfaitement rigoureux mais c'est sans doute suffisant dans ton cas. Par contre il faut effectivement ne faire cet ajout que si a[4] ne vaut pas 0 ou 12. J'imagine qu'il faudrait donc raffiner ton test comme suit :

          ~ /^[Pp][Mm]/ && a[4] != 0 && a[4] != 12 ? a[4]+12 : a[4]


      ... mais bon tu l'auras compris, pour moi ça donne un code sensiblement plus compliqué à lire que l'exemple python que je te t'ai donné. La méthode
      split
      est intéressante : elle est un peu moins rigoureuse qu'une expression rationnelle mais est plus facile à mettre en œuvre, donc pourquoi pas...

      Bonne chance
      0
  6. Modérateur
    Bonjour

    Script minimal

    toto.py

    #!/usr/bin/env python3
    
    import datetime
    
    s_in = "01-Jun-18 11:22:33 PM EDT"
    format_in = "%d-%b-%y %I:%M:%S %p EDT"
    format_out = "%Y-%m-%d %H:%M:%S"
    s_out = datetime.datetime.strptime(s_in, format_in).strftime(format_out)
    print(s_out)


    Note que dans
    format_in
    , l'heure est chargée avec
    %I
    et
    %p
    (format AM/PM). Il est important d'utiliser
    %I
    et non
    %H
    considérerait que l'heure va de
    0
    à
    23
    . Pour
    format_out
    c'est le contraire, on veut une heure qui va de
    0
    à
    23
    et donc on utilise bien
    %H
    .

    Exécution :

    python3 toto.py


    Résultat :

    2018-06-01 23:22:33


    Script avec un fichier

    toto.py

    #!/usr/bin/env python3
    
    import datetime, sys
    
    def translate_date(s_in):
        format_in = "%d-%b-%y %I:%M:%S %p EDT"
        format_out = "%Y-%m-%d %H:%M:%S"
        return datetime.datetime.strptime(s_in, format_in).strftime(format_out)
    
    with open(sys.argv[1]) as f:
        for line in f.readlines():
            try:
                print(translate_date(line.strip()))
            except Exception as e:
                print(e, file=sys.stderr)


    toto.txt

    01-Jun-18 11:22:33 PM EDT
    02-Feb-19 11:33:55 AM EDT
    29-Deb-20 9:17:47 PM EDT


    Exécution

    python3 toto.py toto.txt


    Résultat

    2018-06-01 23:22:33
    2019-02-02 11:33:55
    2020-12-29 21:17:47


    Bonne chance
    0
    1. J'aimerais bien voir le code Python que je connais peu.
      Comme je suis au Québec, il se peut qu'il y ai des délais entre les questions et réponses.
      Le véritable format de mes date c'est '01-Jun-19 12:00:00 AM EDT' ou EST.

      Merci.
      0
      1. Modérateur
        Bonjour,

        Est-ce qu'une solution écrite python pourrait te convenir ? Parce qu'en
        awk
        ça se fait mais il faut passer par une expression rationnelle, extraire les bons bouts, faire un
        mktime
        puis un
        strftime
        ce qui est un peu rébarbatif...

        Bonne chance
        0
        1. Merci pour votre réponse.

          Il faut que je vous dise qu'en fait j'utilise gawk qui je pense gère strftime. Comme je suis qu'un dédutant, ça va me prendre un peu de temps pour faire mes test.

          Merci encore.
          0
          1. Modérateur
            Bonjour,

            Je pense que tu confonds :
            • strftime
              (qui convertit un timestamp en une chaîne de caractère)
            • strptime
              (qui existe en
              python
              mais qui ne semble pas exister en
              awk
              ), qui fait l'opération contraire (ce qui signifie que ce que tu cherches à faire est bien plus simple à réaliser en
              python
              qu'en
              awk
              ).


            Dans le code que tu as reporté $1 n'est pas un timestamp conforme au format utilisé par
            systime()
            et attendu par
            strftime
            , ce qui explique pourquoi ce dernier ne retrouve pas ses billes.

            Il faut donc procéder en deux temps, comme expliqué dans ce lien : d'abord extraire les éléments de la date afin de construire un timestamp bien formé avec
            mktime
            , puis utiliser ce timestamp avec
            strftime
            .

            Bonne chance
            0