Konvertieren Sie Datums- und Uhrzeitzeichenfolge in Epoche in Bash

90

Die Datums- / Uhrzeitzeichenfolge hat das folgende Format: 06/12/2012 07:21:22. Wie kann ich es in einen UNIX-Zeitstempel oder eine Epoche konvertieren?

Edward D.
quelle

Antworten:

92

Was Sie suchen, ist date --date='06/12/2012 07:21:22' +"%s". Beachten Sie, dass dies voraussetzt, dass Sie GNU-Coreutils verwenden, da beide --dateund die %sFormatzeichenfolge GNU-Erweiterungen sind. POSIX gibt keines von beiden an, daher gibt es auch auf POSIX-kompatiblen Systemen keine tragbare Möglichkeit, eine solche Konvertierung durchzuführen.

Weitere Versionen von finden Sie auf der entsprechenden Handbuchseite date.

Hinweis: Bash --dateund -dOption erwarten das Datum im US- oder ISO8601-Format, dh mm/dd/yyyyoder yyyy-mm-ddnicht in Großbritannien, der EU oder einem anderen Format.

Daniel Kamil Kozar
quelle
8
Ich erhalte 'Datum: illegale Option -', wenn ich unter Mac OSX 10.8.2
Ben Clayton
6
Für Noobs wie mich +"%s"steht für Ausgabeformat und %sist das Format der Zeit in Sekunden seit 1970
Razz
2
Hinweis: Wenn Sie die Zeit in einer anderen Zeitzone (wie UTC) angeben möchten, fügen Sie am Ende -HHMM oder + HHMM hinzu. Also date --date='06/12/2012 07:21:22 -0000' +"%s"konvertiert UTC Datum in Unix Zeitstempel
Greg Bray
Für GNU Datum möchten , wenn Sie UTC Notiz verwenden , dass das Format yyyy-mm-dd hh:mm:sseinen Blick auf haben gnu.org/software/coreutils/manual/html_node/... :gdate --date='2019-06-18 00:02:00 +0000' +%s
Ashutosh Jindal
funktioniert nicht auf einem Mac ... Ich frage mich, ob es eine Möglichkeit gibt, sowohl auf einem Mac als auch unter Linux zu arbeiten
Unpolarität
47

Für Linux Führen Sie diesen Befehl aus

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

Führen Sie diesen Befehl unter Mac OSX aus

date -j -u -f "%a %b %d %T %Z %Y" "Tue Sep 28 19:35:15 EDT 2010" "+%s"
Abdul Rehman Janjua
quelle
1
Unter OSX erhöht sich der Zeitstempel irgendwie mit der aktuellen Zeit. Ich habe derzeit keine Erklärung dafür ...
Polym
3
Update: Das lag daran, dass der Zeitstempel für meine Ortszeit angepasst wird, denke ich ... Das Hinzufügen eines -uFlags sollte das beheben.
Polym
@AbdulRehmanJanjua Das -uFlag sollte vor dem -fFlag stehen, sonst interpretiert die Shell es als Formatzeichenfolge . Also sollte es sein:date -j -u -f "%a..."
4
Das Einfügen genau in ein macOS-Terminal schlägt fehl.
Zneak
6
date -jf "%Y-%m-%d %H:%M:%S" "2018-01-08 14:45:00" +%s
Daviestar
10

Viele dieser Antworten sind zu kompliziert und es fehlt auch die Verwendung von Variablen. So würden Sie es auf einem Standard-Linux-System einfacher machen (wie bereits erwähnt, müsste der Datumsbefehl für Mac-Benutzer angepasst werden):

Beispielskript:

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

Ergebnisse in:

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

Oder als Funktion:

# -- 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.
quelle
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
quelle
5
Willkommen bei Stack Overflow. Erwägen Sie, zusätzlich zu Ihrem Code eine Erklärung hinzuzufügen.
Olivier De Meulder
2

Effiziente Lösung dateals Hintergrundprozess

Um diese Art der Übersetzung viel schneller zu machen ...

Intro

In diesem Beitrag finden Sie

  • eine kurze Demo , die folgt,
  • einige Erklärungen ,
  • eine Funktion nutzbar für viele Un * x - Tools ( bc, rot13, sed...).

Schnelle Demo

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

Dies muss die aktuelle UNIXTIME ausgeben . Von dort konnte man vergleichen

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

und:

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

Von mehr als 6 Sekunden bis weniger als einer halben Sekunde !! (auf meinem Gastgeber).

Sie könnten überprüfen echo $ans, ersetzen "now"durch"2019-25-12 20:10:00" und so weiter ...

Optional können Sie nach Beendigung der Anforderung des Datumsunterprozesses Folgendes tun:

exec 5>&- ; exec 6<&-

Originalbeitrag (ausführliche Erklärung)

Anstatt 1 Gabel nach Datum zum Konvertieren auszuführen, führen Sie datenur 1 Mal aus und führen Sie alle Konvertierungen mit demselben Prozess durch (dies könnte viel schneller werden)!:

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

Stichprobe:

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

Dann schauen Sie jetzt:

declare -p start1 start2 dirchg userdate

(kann etwas beantworten wie:

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

Dies geschah in einer Ausführung!

Verwenden eines lang laufenden Unterprozesses

Wir brauchen nur ein Fifo :

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

(Hinweis: Während der Prozess ausgeführt wird und alle Deskriptoren geöffnet sind, können wir den Dateisystemeintrag von fifo sicher entfernen.)

Dann jetzt:

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

Wir könnten eine kleine Funktion kaufen:

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

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

Oder benutze meine newConnector Funktion

Mit Funktionen für Anschluss MySQL/MariaDB , PostgreSQLundSQLite ...

Sie können sie in einer anderen Version auf GitHub oder auf meiner Website finden: herunterladen oder anzeigen .

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

Hinweis: Auf GitHub sind Funktionen und Test getrennte Dateien. Auf meiner Website Test werden läuft einfach , wenn dieses Skript ist nicht bezogen .

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

Stellen Sie einfach sicher, welche Zeitzone Sie verwenden möchten.

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

Die beliebteste Verwendung ist die Zeitzone der Maschine.

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

Wenn Sie jedoch absichtlich die UTC-Uhrzeit übergeben möchten und die richtige Zeitzone wünschen, müssen Sie ein -uFlag hinzufügen . Andernfalls konvertieren Sie es aus Ihrer lokalen Zeitzone.

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