Converter string de data e hora em época no Bash

92

A sequência de data e hora está no seguinte formato: 06/12/2012 07:21:22. Como posso convertê-lo em carimbo de data / hora ou época UNIX?

Edward D.
fonte

Respostas:

94

O que você está procurando é date --date='06/12/2012 07:21:22' +"%s". Tenha em mente que isso assume que você está usando GNU coreutils, já que ambos --datee a %sstring de formato são extensões GNU. POSIX não especifica nenhum desses, portanto, não há maneira portátil de fazer essa conversão, mesmo em sistemas compatíveis com POSIX.

Consulte a página de manual apropriada para outras versões do date.

Nota: bash --datee -doption esperam a data no formato US ou ISO8601, mm/dd/yyyyou seja yyyy-mm-dd, não no Reino Unido, UE ou qualquer outro formato.

Daniel Kamil Kozar
fonte
9
Recebo 'data: opção ilegal -' quando executo no Mac OSX 10.8.2
Ben Clayton
6
Para iniciantes como eu +"%s"significa formato de saída e %sé o formato de tempo em segundos desde 1970
razz
2
Nota: se você deseja especificar o horário em outro fuso horário (como UTC), adicione -HHMM ou + HHMM ao final. Então date --date='06/12/2012 07:21:22 -0000' +"%s"converte a data UTC em carimbo de hora unix
Greg Bray,
Para a data GNU, se você deseja usar UTC, observe que o formato é, yyyy-mm-dd hh:mm:ssdê uma olhada em gnu.org/software/coreutils/manual/html_node/… :gdate --date='2019-06-18 00:02:00 +0000' +%s
Ashutosh Jindal
não funciona em um Mac ... Gostaria de saber se existe uma maneira de trabalhar em um Mac e Linux
polaridade
47

Para Linux, execute este comando

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

Para mac OSX execute este comando

date -j -u -f "%a %b %d %T %Z %Y" "Tue Sep 28 19:35:15 EDT 2010" "+%s"
Abdul Rehman Janjua
fonte
1
No OSX, o timestamp aumenta de alguma forma com a hora atual. No momento não tenho uma explicação para isso ...
polym
3
Update: Isso foi porque ele ajusta o carimbo de data / hora para meu horário local, eu acho ... Adicionar um -usinalizador deve corrigir isso.
polym de
@AbdulRehmanJanjua O -usinalizador deve vir antes do -fsinalizador, ou então o shell o interpretará como a string de formato. Portanto, deve ser:date -j -u -f "%a..."
4
Colar exatamente isso em um terminal do macOS falha.
zneak
6
date -jf "%Y-%m-%d %H:%M:%S" "2018-01-08 14:45:00" +%s
daviestar
10

Muitas dessas respostas são excessivamente complicadas e também não sabem como usar variáveis. É assim que você faria isso de forma mais simples no sistema Linux padrão (como mencionado anteriormente, o comando de data teria que ser ajustado para usuários de Mac):

Script de amostra:

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

Resulta em :

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

Ou como uma função:

# -- 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
fonte
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
fonte
5
Bem-vindo ao Stack Overflow. Considere adicionar uma explicação além de seu código.
Olivier De Meulder
2

Solução eficiente usando datecomo processo dedicado em segundo plano

Para tornar esse tipo de tradução muito mais rápido ...

Introdução

Nesta postagem, você encontrará

  • uma demonstração rápida , seguindo esta,
  • algumas explicações ,
  • uma função útil para muitas Un * x ferramentas ( bc, rot13, sed...).

Demonstração 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

Isso deve gerar UNIXTIME atual . A partir daí, você pode 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

e:

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

De mais de 6 segundos a menos de meio segundo !! (no meu host).

Você pode verificar echo $ans, substitua "now"por "2019-25-12 20:10:00"e assim por diante ...

Opcionalmente, você poderia, uma vez que o requisito do subprocesso de data terminou:

exec 5>&- ; exec 6<&-

Postagem original (explicação detalhada)

Em vez de executar 1 bifurcação por data para converter, execute dateapenas 1 vez e faça todas as conversões com o mesmo processo (isso pode se tornar muito mais 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

Amostra:

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" )

Então agora dê uma olhada:

declare -p start1 start2 dirchg userdate

(pode responder algo como:

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

Isso foi feito em uma execução!

Usando subprocesso de longa duração

Só precisamos de um fifo :

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

(Observação: como o processo está em execução e todos os descritores são abertos, podemos remover com segurança a entrada do sistema de arquivos fifo.)

Então agora:

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

Poderíamos construir uma pequena função:

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

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

Ou use minha newConnector função

Com funções para conectar MySQL/MariaDB , PostgreSQLe SQLite...

Você pode encontrá-los em versões diferentes no GitHub ou no meu site: download ou show .

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: No GitHub , funções e teste são arquivos separados. No meu site, os testes são executados simplesmente se este script não for originado .

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

Apenas certifique-se de qual fuso horário você deseja usar.

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

O uso mais popular leva o fuso horário da máquina.

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

Mas no caso de você querer passar a data e hora UTC intencionalmente e quiser um fuso horário adequado, você precisa adicionar um -usinalizador. Caso contrário, você o converte de seu fuso horário local.

date -u -d "$datetime" +"%s" #general output = "1339485682"
Tajni
fonte
E se meu formato de data for "AAAAmmdd"? ex. 20200827
Mayur Gite
Você também pode usar. dateformata adequadamente esta entrada.
Tajni