Mude o formato da data de MM / DD / AAAA HH: MM: SS am / pm para AAAA-MM-DD HH: MM: SS em um arquivo CSV

2

Estou tentando converter o formato de data para esse arquivo csv que recebi do fornecedor para que eu possa fazer o upload dos dados para o meu Google Bigquery. Estou usando uma VM do Google Cloud Console.

Os dados parecem com algo assim:

Name ,Phone ,SalesDate ,Venue ,NoOfUnits ,ModifiedDatae

Victor ,5555555 ,12/6/2013 10:26:32 AM , Colosseum ,1 ,12/8/2013 1:05:45 PM

Estou tentando fazer isso no formato de:

Name ,Phone ,SalesDate ,Venue ,NoOfUnits ,ModifiedDatae

Victor ,5555555 ,2013-12-6 10:26:32 ,Colosseum,1 ,2013-12-8 13:05:45

Eu sei que posso usar sed ou awk.

    
por TDBS 29.05.2018 / 20:22

5 respostas

0

Eu escrevi um script Python e um script Bash que deve fazer o que você quiser.

Solução Python

Aqui está um script Python que converte todos os campos de tempo de um formato para outro, conforme especificado na pergunta:

#!/usr/bin/env python3
# -*- coding: ascii -*-
"""reformat_time.py

Change date format from:

    MM/DD/YYYY HH:MM:SS am/pm

to:

    YYYY-MM-DD HH:MM:SS

in a CSV file
"""

import csv
from datetime import date
from datetime import datetime
import sys

# Open the file (taken as a command-line argument)
with open(sys.argv[1], 'r') as csvfile:

    # Parse the CSV data
    csvreader = csv.reader(csvfile, delimiter=',', quotechar='"')

    # Iterate over the rows
    for row in csvreader:

        # Iterate over the columns of each row
        for index, col in enumerate(row):

            # Try to parse and convert each column
            try:
                _datetime = datetime.strptime(col, "%m/%d/%Y %H:%M:%S %p")
                newcol = _datetime.strftime("%Y-%m-%d %H:%M:%S")

            # If parsing fails, leave the column unchanged
            except ValueError:
                newcol = col

            # Update the column value
            row[index] = newcol

        # Output the updated row
        print(','.join(row))

Suponha que seu arquivo CSV seja chamado de data.csv e contenha a seguinte linha (tirada de sua postagem):

Victor,5555555,12/6/2013 10:26:32 AM,Colosseum,1,12/8/2013 1:05:45 PM

Então você pode executar o script assim:

python reformat_time.py data.csv

Isso produziria a seguinte saída:

Victor,5555555,2013-12-06 10:26:32,Colosseum,1,2013-12-08 01:05:45

Solução de bash

E aqui está um script Bash usando o utilitário GNU date que tem (quase) o mesmo efeito:

#!/bin/bash
# reformat_time.sh

# Loop over the lines of the file
while read -r line; do

    # Extract the field values for each row
    Name="$(echo ${line} | cut -d, -f1)";
    Phone="$(echo ${line} | cut -d, -f2)";
    SalesDate="$(echo ${line} | cut -d, -f3)";
    Venue="$(echo ${line} | cut -d, -f4)";
    NoOfUnits="$(echo ${line} | cut -d, -f5)";
    ModifiedDate="$(echo ${line} | cut -d, -f6)";

    # Convert the time-fields from the old format to the new format
    NewSalesDate="$(date -d "${SalesDate}" "+%Y-%m-%d %H:%M:%S")";
    NewModifiedDate="$(date -d "${ModifiedDate}" "+%Y-%m-%d %H:%M:%S")";

    # Output the updated row
    echo "${Name},${Phone},${NewSalesDate},${Venue},${NoOfUnits},${NewModifiedDate}";

done < "$1"

Você pode executá-lo assim:

bash reformat_time.sh data.csv

E produziria a seguinte saída:

Victor ,5555555 ,2013-12-06 10:26:32, Colosseum ,1 ,2013-12-08 13:05:45

Observe que o script do Bash é muito mais frágil. Ele não faz nenhum tratamento de erros e afeta apenas os campos 3 e 6. Ele também preserva o espaço em branco em torno do separador de campo, o qual o script Python acima não faz.

    
por 29.05.2018 / 20:37
0

I am new to Linux and I being trying to covert the date format

Tente utilizar date com a opção -d :

       -d, --date=STRING
              display time described by STRING, not 'now'

E formate a saída da maneira que você quiser.

Exemplo:

date -d "12/6/2013 10:26:32 AM" "+%F %H:%M:%S"
2013-12-06 10:26:32

Para obter explicações sobre formatação, consulte man date (a seção FORMAT ).

    
por 29.05.2018 / 20:34
0

Você pode tentar com este awk

awk -F, '
function cvtdate( dat,  array) {
    split(dat,array,"/| |:")
    array[4]=array[7]=="PM"?(array[4]+12):array[4]
    return array[3]"-"array[1]"-"array[2]" "array[4]":"array[5]":"array[6]
}
{
    $3=cvtdate($3)
    $6=cvtdate($6)
}1' OFS=',' infile
    
por 29.05.2018 / 22:14
0

Não há necessidade real de chamar date . Como as únicas alterações são a ordem e adicionar 12 (horas) a um campo, o awk poderia fazer tudo:

awk -F, 'BEGIN{ f[1]=3; f[2]=6; regex="[^/: ]+" }
         NR>1{
                 for (i in f){
                 patsplit($f[i], a, regex)
                 b="%s-%s-%s %s:%s:%s"
                 c=(a[4]+((a[7]=="PM")?12:0))
                 $f[i]=sprintf(b,a[3],a[2],a[1],c,a[5],a[6])
             }
     } 1' OFS=, infile
    
por 30.05.2018 / 08:09
0

Outro possível onkiner:

awk -F, '{ a[3];a[6] ; for (i in a) "date -d \""$i"\" \"+%Y-%m-%d %H:%M:%S\"" |& getline $i }1' OFS=, filename
    
por 30.05.2018 / 04:54

Tags