Konwertuj ciąg daty i czasu na epokę w Bash

95

Ciąg daty i godziny ma następujący format: 12.06.2012 07:21:22. Jak mogę przekonwertować go na sygnaturę czasową lub epokę UNIX?

Edward D.
źródło

Odpowiedzi:

96

To, czego szukasz, to date --date='06/12/2012 07:21:22' +"%s". Pamiętaj, że zakłada się, że używasz coreutils GNU, ponieważ oba elementy --datei %słańcuch formatu są rozszerzeniami GNU. POSIX nie określa żadnego z nich, więc nie ma przenośnego sposobu na wykonanie takiej konwersji nawet w systemach zgodnych z POSIX.

Zapoznaj się z odpowiednią stroną podręcznika dla innych wersji date.

Uwaga: bash --datei -dopcja oczekują daty w formacie amerykańskim lub ISO8601, tj. mm/dd/yyyyLub yyyy-mm-ddnie w formacie brytyjskim, UE lub innym.

Daniel Kamil Kozar
źródło
9
Dostaję `` data: nielegalna opcja - '' kiedy uruchamiam na Mac OSX 10.8.2
Ben Clayton,
6
Dla noobów takich jak ja +"%s"oznacza format wyjściowy i %sjest to format czasu w sekundach od 1970 roku
razz
2
Uwaga: jeśli chcesz określić czas w innej strefie czasowej (np. UTC), dodaj -HHMM lub + HHMM na końcu. Więc date --date='06/12/2012 07:21:22 -0000' +"%s"konwertuje datę UTC na znacznik czasu unixa
Greg Bray
Jeśli chodzi o datę GNU, jeśli chcesz używać UTC, zwróć uwagę, że format jest zgodnyyyyy-mm-dd hh:mm:ss z gnu.org/software/coreutils/manual/html_node/ ... :gdate --date='2019-06-18 00:02:00 +0000' +%s
Ashutosh Jindal
nie działa na Macu ... Zastanawiam się, czy jest sposób na pracę zarówno na Macu, jak i Linuksie
nonopolarity
50

W systemie Linux Uruchom to polecenie

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

W systemie Mac OSX uruchom to polecenie

date -j -u -f "%a %b %d %T %Z %Y" "Tue Sep 28 19:35:15 EDT 2010" "+%s"
Abdul Rehman Janjua
źródło
1
W OSX znacznik czasu rośnie w jakiś sposób wraz z aktualnym czasem. Obecnie nie mam na to wytłumaczenia ...
polym
3
Aktualizacja: To dlatego, że dostosowuje sygnaturę czasową do mojego czasu lokalnego, jak sądzę ... Dodanie -uflagi powinno to naprawić.
polym
@AbdulRehmanJanjua -uflaga powinna przyjść wcześniej na -fflagi, albo też interpretuje powłoki to ciąg formatu. Tak więc powinno to być:date -j -u -f "%a..."
5
Wklejanie dokładnie tego w terminalu macOS kończy się niepowodzeniem.
zneak
7
date -jf "%Y-%m-%d %H:%M:%S" "2018-01-08 14:45:00" +%s
daviestar
10

Wiele z tych odpowiedzi jest zbyt skomplikowanych, a także brakuje w nich sposobu korzystania ze zmiennych. W ten sposób zrobiłbyś to prościej w standardowym systemie Linux (jak wspomniano wcześniej, polecenie date musiałoby być dostosowane do użytkowników komputerów Mac):

Przykładowy skrypt:

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

Prowadzi do :

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

Lub jako funkcja:

# -- 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
źródło
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
źródło
6
Witamy w Stack Overflow. Rozważ dodanie wyjaśnienia do kodu.
Olivier De Meulder
2

Wydajne rozwiązanie wykorzystujące datejako tło procesu przeznaczone

Aby tego rodzaju tłumaczenie było dużo szybsze ...

Intro

W tym poście znajdziesz

  • Szybkie Demo , po to,
  • kilka wyjaśnień ,
  • Funkcja użyteczna dla wielu UN * X narzędzi ( bc, rot13, sed...).

Szybkie 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

Musi to wyprowadzać prąd UNIXTIME . Stamtąd możesz porównać

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

i:

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

Od ponad 6 sekund do mniej niż pół sekundy !! (na moim hoście).

Możesz sprawdzić echo $ans, wymienić "now"na "2019-25-12 20:10:00"i tak dalej ...

Opcjonalnie możesz po zakończeniu wymagania daty podprocesu :

exec 5>&- ; exec 6<&-

Oryginalny post (szczegółowe wyjaśnienie)

Zamiast uruchamiać 1 fork według daty w celu konwersji, uruchom datetylko 1 raz i wykonaj całą konwersję w tym samym procesie (może to stać się znacznie szybsze) !:

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

Próba:

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

A teraz spójrz:

declare -p start1 start2 dirchg userdate

(może odpowiedzieć na przykład:

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

Zrobiono to w jednym wykonaniu!

Korzystanie z długotrwałego podprocesu

Potrzebujemy tylko jednej kolejki FIFO :

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

(Uwaga: ponieważ proces jest uruchomiony i wszystkie deskryptory są otwarte, możemy bezpiecznie usunąć wpis systemu plików fifo).

Więc teraz:

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

Moglibyśmy kupić małą funkcję:

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

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

Lub użyj mojej newConnector funkcji

Z funkcjami do łączenia MySQL/MariaDB , PostgreSQLi SQLite...

Możesz je znaleźć w innej wersji na GitHub lub na mojej stronie: pobierz lub pokaż .

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: Na GitHub , funkcje i testy są oddzielone plików. Na mojej stronie testy są uruchamiane po prostu, jeśli ten skrypt nie jest pochodzący .

# Exit here if script is sourced
[ "$0" = "$BASH_SOURCE" ] || { true;return 0;}
F. Hauri
źródło
2

Po prostu upewnij się, jakiej strefy czasowej chcesz używać.

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

Najpopularniejszym zastosowaniem jest strefa czasowa maszyny.

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

Ale jeśli celowo chcesz przekazać datę UTC i chcesz mieć odpowiednią strefę czasową, musisz dodać -uflagę. W przeciwnym razie przekonwertujesz go z lokalnej strefy czasowej.

date -u -d "$datetime" +"%s" #general output = "1339485682"
Tajni
źródło
Co się stanie, jeśli mój format daty to „RRRRmmdd”? dawny. 20200827
Mayur Gite
Możesz go również użyć. dateprawidłowo formatuje to wejście.
Tajni