Cambie el formato de fecha de MM/DD/AAAA HH:MM:SS am/pm a AAAA-MM-DD HH:MM:SS en un archivo CSV

Cambie el formato de fecha de MM/DD/AAAA HH:MM:SS am/pm a AAAA-MM-DD HH:MM:SS en un archivo CSV

Estoy intentando convertir el formato de fecha de este archivo csv que obtuve del proveedor para poder cargar los datos en mi Google Bigquery. Estoy usando una máquina virtual de Google Cloud Console.

Los datos se parecen a esto:

Name ,Phone ,SalesDate ,Venue ,NoOfUnits ,ModifiedDatae

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

Estoy intentando hacerlo en el formato de:

Name ,Phone ,SalesDate ,Venue ,NoOfUnits ,ModifiedDatae

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

Sé que puedo usar sed o awk.

Respuesta1

Escribí un script de Python y un script de Bash que deberían hacer lo que quieras.

Solución Python

Aquí hay una secuencia de comandos de Python que convierte todos los campos de tiempo de un formato a otro, como se especifica en la pregunta:

#!/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))

Supongamos que se llama a su archivo CSV data.csvy contiene la siguiente línea (tomada de su publicación):

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

Entonces podrías ejecutar el script así:

python reformat_time.py data.csv

Esto produciría el siguiente resultado:

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

Solución de golpe

Y aquí hay un script Bash que utiliza la dateutilidad GNU que tiene (casi) el mismo efecto:

#!/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"

Podrías ejecutarlo así:

bash reformat_time.sh data.csv

Y produciría el siguiente resultado:

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

Observe que el script Bash es mucho más frágil. No maneja errores y solo afecta al tercer y sexto campo. También conserva el espacio en blanco que rodea el separador de campo, algo que no hace el script Python anterior.

Respuesta2

Soy nuevo en Linux y estoy intentando convertir el formato de fecha.

Intente utilizar datecon el -dinterruptor:

       -d, --fecha=CADENA
              tiempo de visualización descrito por STRING, no 'ahora'

Y luego formatee la salida como desee.

Ejemplo:

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

Para obtener una explicación del formato, consulte man date(la FORMATsección).

Respuesta3

Puedes probar con 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

Respuesta4

Otro posible awk oneliner:

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

información relacionada