Convertir cadena de fecha y hora en época en Bash

95

La cadena de fecha y hora tiene el siguiente formato: 12/06/2012 07:21:22. ¿Cómo puedo convertirlo a marca de tiempo o época de UNIX?

Edward D.
fuente

Respuestas:

96

Lo que estás buscando es date --date='06/12/2012 07:21:22' +"%s". Tenga en cuenta que esto supone que está usando GNU coreutils, ya que tanto --datela %scadena de formato como la cadena de formato son extensiones GNU. POSIX no especifica ninguno de esos, por lo que no existe una forma portátil de realizar dicha conversión incluso en sistemas compatibles con POSIX.

Consulte la página de manual correspondiente para otras versiones de date.

Nota: bash --datey -doption esperan la fecha en formato de EE. UU. O ISO8601, es decir , mm/dd/yyyyo yyyy-mm-ddno en el Reino Unido, la UE o cualquier otro formato.

Daniel Kamil Kozar
fuente
9
Recibo 'fecha: opción ilegal -' cuando ejecuto Mac OSX 10.8.2
Ben Clayton
6
Para novatos como yo +"%s"significa formato de salida y %ses el formato de tiempo en segundos desde 1970
razz
2
Nota: si desea especificar la hora en otra zona horaria (como UTC), agregue -HHMM o + HHMM al final. Por lo tanto, date --date='06/12/2012 07:21:22 -0000' +"%s"convierte la fecha UTC en una marca de tiempo Unix
Greg Bray
Para la fecha GNU, si desea usar UTC, tenga en cuenta que el formato es yyyy-mm-dd hh:mm:sseche un vistazo a gnu.org/software/coreutils/manual/html_node/… :gdate --date='2019-06-18 00:02:00 +0000' +%s
Ashutosh Jindal
no funciona en una Mac ... Me pregunto si hay una manera de trabajar tanto en una Mac como en Linux
polaridad
50

Para Linux Ejecute este comando

date -d '06/12/2012 07:21:22' +"%s"

Para mac OSX, ejecute este comando

date -j -u -f "%a %b %d %T %Z %Y" "Tue Sep 28 19:35:15 EDT 2010" "+%s"
Abdul Rehman Janjua
fuente
1
En OSX, la marca de tiempo aumenta de alguna manera con la hora actual. Actualmente no tengo una explicación para eso ...
polym
3
Actualización: Eso fue porque ajusta la marca de tiempo para mi hora local, supongo ... Agregar una -ubandera debería arreglar eso.
polym
@AbdulRehmanJanjua La -ubandera debe ir antes de la -fbandera, o de lo contrario el shell lo interpreta como la cadena de formato. Por lo tanto, debería ser:date -j -u -f "%a..."
5
Pegar exactamente eso en un terminal macOS falla.
zneak
7
date -jf "%Y-%m-%d %H:%M:%S" "2018-01-08 14:45:00" +%s
daviestar
10

Muchas de estas respuestas son demasiado complicadas y también les falta cómo usar las variables. Así es como lo haría de manera más simple en un sistema Linux estándar (como se mencionó anteriormente, el comando de fecha debería ajustarse para los usuarios de Mac):

Ejemplo de guion:

#!/bin/bash
orig="Apr 28 07:50:01"
epoch=$(date -d "${orig}" +"%s")
epoch_to_date=$(date -d @$epoch +%Y%m%d_%H%M%S)    

echo "RESULTS:"
echo "original = $orig"
echo "epoch conv = $epoch"
echo "epoch to human readable time stamp = $epoch_to_date"

Resultados en:

RESULTS:
original = Apr 28 07:50:01
epoch conv = 1524916201 
epoch to human readable time stamp = 20180428_075001

O en función:

# -- Converts from human to epoch or epoch to human, specifically "Apr 28 07:50:01" human.
#    typeset now=$(date +"%s")
#    typeset now_human_date=$(convert_cron_time "human" "$now")

function convert_cron_time() {
    case "${1,,}" in
        epoch)
            # human to epoch (eg. "Apr 28 07:50:01" to 1524916201)
            echo $(date -d "${2}" +"%s")
            ;;
        human)
            # epoch to human (eg. 1524916201 to "Apr 28 07:50:01")
            echo $(date -d "@${2}" +"%b %d %H:%M:%S")
            ;;
    esac
}
Mike Q
fuente
3
get_curr_date () {
    # get unix time
    DATE=$(date +%s)
    echo "DATE_CURR : "$DATE
}

conv_utime_hread () {
    # convert unix time to human readable format
    DATE_HREAD=$(date -d @$DATE +%Y%m%d_%H%M%S)
    echo "DATE_HREAD          : "$DATE_HREAD
}
shgurbanov
fuente
6
Bienvenido a Stack Overflow. Considere agregar una explicación además de su código.
Olivier De Meulder
2

Solución eficiente utilizando datecomo fondo dedicado proceso de

Para hacer este tipo de traducción mucho más rápido ...

Intro

En esta publicación, encontrará

  • una demostración rápida , después de esto,
  • algunas explicaciones ,
  • una función útil para muchos Un * x herramientas ( bc, rot13, sed...).

Demo rápida

fifo=$HOME/.fifoDate-$$
mkfifo $fifo
exec 5> >(exec stdbuf -o0 date -f - +%s >$fifo 2>&1)
echo now 1>&5
exec 6< $fifo
rm $fifo
read -t 1 -u 6 now
echo $now

Debe generar la corriente UNIXTIME . A partir de ahí, podrías comparar

time for i in {1..5000};do echo >&5 "now" ; read -t 1 -u6 ans;done
real    0m0.298s
user    0m0.132s
sys     0m0.096s

y:

time for i in {1..5000};do ans=$(date +%s -d "now");done 
real    0m6.826s
user    0m0.256s
sys     0m1.364s

¡¡De más de 6 segundos a menos de medio segundo !! (en mi anfitrión).

Podrías verificar echo $ans, reemplazar "now"por"2019-25-12 20:10:00" etc.

Opcionalmente, podría, una vez finalizado el requisito de fecha del subproceso :

exec 5>&- ; exec 6<&-

Publicación original (explicación detallada)

En lugar de ejecutar 1 bifurcación por fecha para convertir, ejecute datesolo 1 vez y realice todas las conversiones con el mismo proceso (¡esto podría ser mucho más rápido) !:

date -f - +%s <<eof
Apr 17  2014
May 21  2012
Mar  8 00:07
Feb 11 00:09
eof
1397685600
1337551200
1520464020
1518304140

Muestra:

start1=$(LANG=C ps ho lstart 1)
start2=$(LANG=C ps ho lstart $$)
dirchg=$(LANG=C date -r .)
read -p "A date: " userdate
{ read start1 ; read start2 ; read dirchg ; read userdate ;} < <(
   date -f - +%s <<<"$start1"$'\n'"$start2"$'\n'"$dirchg"$'\n'"$userdate" )

Entonces ahora eche un vistazo:

declare -p start1 start2 dirchg userdate

(puede responder algo como:

declare -- start1="1518549549"
declare -- start2="1520183716"
declare -- dirchg="1520601919"
declare -- userdate="1397685600"

¡Esto se hizo en una sola ejecución!

Usando subprocesos de larga ejecución

Solo necesitamos un quince :

mkfifo /tmp/myDateFifo
exec 7> >(exec stdbuf -o0 /bin/date -f - +%s >/tmp/myDateFifo)
exec 8</tmp/myDateFifo
rm /tmp/myDateFifo

(Nota: como el proceso se está ejecutando y todos los descriptores están abiertos, podríamos eliminar de forma segura la entrada del sistema de archivos de FIFO).

Entonces ahora:

LANG=C ps ho lstart 1 $$ >&7
read -u 8 start1
read -u 8 start2
LANG=C date -r . >&7
read -u 8 dirchg

read -p "Some date: " userdate
echo >&7 $userdate
read -u 8 userdate

Podríamos construir una pequeña función:

mydate() {
    local var=$1;
    shift;
    echo >&7 $@
    read -u 8 $var
}

mydate start1 $(LANG=C ps ho lstart 1)
echo $start1

O usa mi newConnector función

Con funciones para la conexión MySQL/MariaDB , PostgreSQLySQLite ...

Puede encontrarlos en diferentes versiones en GitHub o en mi sitio: descargar o mostrar .

wget https://raw.githubusercontent.com/F-Hauri/Connector-bash/master/shell_connector.bash

. shell_connector.bash 
newConnector /bin/date '-f - +%s' @0 0

myDate "2018-1-1 12:00" test
echo $test
1514804400

Nota: En GitHub , las funciones y la prueba son archivos separados. En mi sitio, las pruebas se ejecutan simplemente si este script no se obtiene .

# Exit here if script is sourced
[ "$0" = "$BASH_SOURCE" ] || { true;return 0;}
F. Hauri
fuente
2

Solo asegúrate de qué zona horaria quieres usar.

datetime="06/12/2012 07:21:22"

El uso más popular toma la zona horaria de la máquina.

date -d "$datetime" +"%s" #depends on local timezone, my output = "1339456882"

Pero en caso de que intencionalmente desee pasar la fecha y hora UTC y desee la zona horaria adecuada, debe agregar una -ubandera. De lo contrario, lo convierte de su zona horaria local.

date -u -d "$datetime" +"%s" #general output = "1339485682"
Tajni
fuente
¿Qué pasa si mi formato de fecha es "YYYYmmdd"? ex. 20200827
Mayur Gite
Puedes usarlo también. dateformatea correctamente esta entrada.
Tajni