Преобразование строки даты и времени в эпоху в Bash

95

Строка даты и времени имеет следующий формат: 12.06.2012 07:21:22. Как я могу преобразовать его в метку времени или эпоху UNIX?

Эдвард Д.
источник

Ответы:

96

То, что вы ищете date --date='06/12/2012 07:21:22' +"%s". Имейте в виду, что здесь предполагается, что вы используете GNU coreutils, поскольку и то, --dateи другое, и %sстрока формата являются расширениями GNU. POSIX не определяет ни то, ни другое, поэтому нет переносимого способа сделать такое преобразование даже в системах, совместимых с POSIX.

Обратитесь к соответствующей странице руководства для других версий date.

Примечание: bash --dateи -doption ожидают дату в формате США или ISO8601, т. Е. mm/dd/yyyyИли yyyy-mm-ddне в формате Великобритании, ЕС или любом другом формате.

Даниэль Камил Козар
источник
9
Я получаю «дата: незаконная опция -» при запуске в Mac OSX 10.8.2
Бен Клейтон,
6
Для таких новичков, как я, +"%s"это формат вывода и %sформат времени в секундах с 1970 года
razz
2
Примечание: если вы хотите указать время в другом часовом поясе (например, UTC), добавьте в конец -ЧЧММ или + ЧЧММ. Таким образом, date --date='06/12/2012 07:21:22 -0000' +"%s"дата UTC преобразуется в метку времени unix
Грег Брей,
Для даты GNU, если вы хотите использовать UTC, обратите внимание, что формат представлен yyyy-mm-dd hh:mm:ssна gnu.org/software/coreutils/manual/html_node/… :gdate --date='2019-06-18 00:02:00 +0000' +%s
Ашутош Джиндал
не работает на Mac ... Интересно, есть ли способ работать как на Mac, так и на Linux
неполярность
50

Для Linux Выполните эту команду

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

Для Mac OSX выполните эту команду

date -j -u -f "%a %b %d %T %Z %Y" "Tue Sep 28 19:35:15 EDT 2010" "+%s"
Абдул Рехман Джанджуа
источник
1
В OSX временная метка каким-то образом увеличивается с текущим временем. У меня в настоящее время нет объяснения этому ...
polym
3
Обновление: это потому, что он регулирует метку времени для моего местного времени, я думаю ... Добавление -uфлага должно исправить это.
polym
@AbdulRehmanJanjua -uфлаг должен прийти прежде , чем на -fфлаге или иначе толкует оболочки это формат строки. Итак, это должно быть:date -j -u -f "%a..."
5
Вставить именно это в терминал macOS не удается.
zneak
7
date -jf "%Y-%m-%d %H:%M:%S" "2018-01-08 14:45:00" +%s
daviestar 08
10

Многие из этих ответов слишком сложны, а также не имеют возможности использовать переменные. Вот как вы могли бы сделать это проще в стандартной системе Linux (как уже упоминалось ранее, команду date необходимо настроить для пользователей Mac):

Пример сценария:

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

Результаты в:

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

Или как функция:

# -- 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
}
Шгурбанов
источник
6
Добро пожаловать в Stack Overflow. Подумайте о добавлении объяснения в дополнение к вашему коду.
Olivier De Meulder
2

Эффективное решение, использующее в dateкачестве фонового выделенного процесса

Чтобы сделать такой перевод намного быстрее ...

вступление

В этом посте вы найдете

  • Quick Demo , вслед за этим,
  • некоторые объяснения ,
  • функция полезной для многих Un * х инструментов ( bc, rot13, sed...).

Быстрая демонстрация

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

Это должно выводить текущий UNIXTIME . Оттуда вы можете сравнить

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

а также:

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

От более 6 секунд до менее чем полсекунды !! (на моем хосте).

Вы можете проверить echo $ans, заменить "now"на "2019-25-12 20:10:00"и так далее ...

При желании вы могли бы, когда требование подпроцесса даты закончилось:

exec 5>&- ; exec 6<&-

Исходный пост (подробное объяснение)

Вместо того, чтобы запускать 1 форк по дате для преобразования, запустите dateтолько 1 раз и выполните все преобразования одним и тем же процессом (это может стать намного быстрее) !:

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

Образец:

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

Тогда посмотрите:

declare -p start1 start2 dirchg userdate

(может ответить примерно так:

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

Это было сделано за один раз!

Использование длительного подпроцесса

Нам просто нужен один фифо :

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

(Примечание: поскольку процесс запущен и все дескрипторы открыты, мы можем безопасно удалить запись файловой системы fifo.)

Тогда сейчас:

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

Мы могли бы построить небольшую функцию:

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

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

Или используйте мою newConnector функцию

С функциями для подключения MySQL/MariaDB , PostgreSQLи SQLite...

Вы можете найти их в другой версии на GitHub или у меня на сайте: скачать или показать .

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

Примечание: на GitHub функции и тест - это отдельные файлы. На моем сайте тесты запускаются просто, если этот скрипт не получен .

# Exit here if script is sourced
[ "$0" = "$BASH_SOURCE" ] || { true;return 0;}
Ф. Хаури
источник
2

Просто убедитесь, какой часовой пояс вы хотите использовать.

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

Чаще всего используется часовой пояс машины.

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

Но если вы намеренно хотите передать дату и время в формате UTC, и вам нужен правильный часовой пояс, вам нужно добавить -uфлаг. В противном случае вы конвертируете его из местного часового пояса.

date -u -d "$datetime" +"%s" #general output = "1339485682"
Тайни
источник
Что, если у меня формат даты «ГГГГммдд»? напр. 20200827
Маюр Гите
Вы тоже можете его использовать. dateправильно форматирует этот ввод.
Тайни