Converti la stringa della data e dell'ora in epoch in Bash


92

La stringa della data e dell'ora è nel seguente formato: 06/12/2012 07:21:22. Come posso convertirlo in timestamp o epoch UNIX?

Risposte:


94

Quello che stai cercando è date --date='06/12/2012 07:21:22' +"%s". Tieni presente che ciò presuppone che tu stia utilizzando GNU coreutils, poiché sia --datee la %sstringa di formato sono estensioni GNU. POSIX non specifica nessuno di questi, quindi non esiste un modo portatile per effettuare tale conversione anche su sistemi compatibili con POSIX.

Consultare la pagina del manuale appropriata per altre versioni di date.

Nota: bash --datee -doption prevedono la data nel formato USA o ISO8601, cioè mm/dd/yyyyo yyyy-mm-dd, non nel Regno Unito, nell'UE o in qualsiasi altro formato.


9
Ottengo 'data: opzione illegale -' quando corro su Mac OSX 10.8.2
Ben Clayton,

6
Per niubbi come me +"%s"sta per formato di output ed %sè il formato del tempo in secondi dal 1970
razz

2
Nota: se vuoi specificare l'ora in un altro fuso orario (come UTC) aggiungi -HHMM o + HHMM alla fine. Quindi date --date='06/12/2012 07:21:22 -0000' +"%s"converte la data UTC in timestamp unix
Greg Bray

Per la data GNU, se desideri utilizzare UTC nota che il formato è yyyy-mm-dd hh:mm:ssdare un'occhiata a gnu.org/software/coreutils/manual/html_node/… :gdate --date='2019-06-18 00:02:00 +0000' +%s
Ashutosh Jindal

non funziona su un Mac ... mi chiedo se ci sia un modo per lavorare sia su un Mac che su Linux
nonopolarità

47

Per Linux eseguire questo comando

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

Per mac OSX eseguire questo comando

date -j -u -f "%a %b %d %T %Z %Y" "Tue Sep 28 19:35:15 EDT 2010" "+%s"

1
Su OSX il timestamp aumenta in qualche modo con l'ora corrente. Al momento non ho una spiegazione per questo ...
polimero

3
Aggiornamento: questo perché regola il timestamp per l'ora locale, immagino ... L'aggiunta di un -uflag dovrebbe risolverlo.
polym

@AbdulRehmanJanjua Il -uflag dovrebbe venire prima del -fflag, altrimenti la shell lo interpreta come stringa di formato. Quindi, dovrebbe essere:date -j -u -f "%a..."

4
Incollare esattamente quello in un terminale macOS non riesce.
Zneak

6
date -jf "%Y-%m-%d %H:%M:%S" "2018-01-08 14:45:00" +%s
daviestar

10

Molte di queste risposte sono eccessivamente complicate e mancano anche di come utilizzare le variabili. Questo è il modo in cui lo faresti più semplicemente su un sistema Linux standard (come accennato in precedenza, il comando date dovrebbe essere regolato per gli utenti Mac):

Script di esempio:

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

Risultati in:

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

O come funzione:

# -- 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
}

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
}

5
Benvenuto in Stack Overflow. Considera l'idea di aggiungere una spiegazione oltre al tuo codice.
Olivier De Meulder

2

Soluzione efficiente utilizzando datecome processo dedicato in background

Per rendere questo tipo di traduzione molto più veloce ...

Intro

In questo post troverai

  • una demo rapida , a seguito di questo,
  • alcune spiegazioni ,
  • una funzione utilizzabile per molti un * x strumenti ( bc, rot13, sed...).

Demo veloce

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

Deve restituire UNIXTIME corrente . Da lì, puoi confrontare

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

Da più di 6 secondi a meno di mezzo secondo !! (sul mio host).

Potresti controllare echo $ans, sostituire "now"entro "2019-25-12 20:10:00"e così via ...

Facoltativamente, una volta terminato il requisito del sottoprocesso della data , è possibile :

exec 5>&- ; exec 6<&-

Post originale (spiegazione dettagliata)

Invece di eseguire 1 fork per data da convertire, esegui datesolo 1 volta ed esegui tutte le conversioni con lo stesso processo (questo potrebbe diventare molto più veloce) !:

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

Campione:

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

Quindi ora dai un'occhiata:

declare -p start1 start2 dirchg userdate

(può rispondere qualcosa come:

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

Questo è stato fatto in una sola esecuzione!

Utilizzo di un sottoprocesso a esecuzione prolungata

Abbiamo solo bisogno di un fifo :

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

(Nota: poiché il processo è in esecuzione e tutti i descrittori sono aperti, è possibile rimuovere in modo sicuro la voce del filesystem di fifo.)

Quindi ora:

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

Potremmo costruire una piccola funzione:

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

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

Oppure usa la mia newConnector funzione

Con le funzioni di collegamento MySQL/MariaDB , PostgreSQLe SQLite...

Li puoi trovare in diverse versioni su GitHub o sul mio sito: scarica o mostra .

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: su GitHub , le funzioni e il test sono file separati. Sul mio sito vengono eseguiti test semplicemente se questo script non è originario .

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

2

Assicurati solo di quale fuso orario vuoi usare.

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

L'utilizzo più diffuso richiede il fuso orario della macchina.

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

Ma nel caso in cui si desideri intenzionalmente passare il datetime UTC e si desidera il fuso orario corretto, è necessario aggiungere un -uflag. Altrimenti lo converti dal tuo fuso orario locale.

date -u -d "$datetime" +"%s" #general output = "1339485682"

E se il formato della mia data è "AAAAMMGG"? ex. 20200827
Mayur Gite

Puoi usarlo anche tu. dateformatta correttamente questo input.
Tajni
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.