Convertir la chaîne de date et d'heure en époque dans Bash

92

La chaîne de date et d'heure est au format suivant: 06/12/2012 07:21:22. Comment puis-je le convertir en horodatage ou en époque UNIX?

Edward D.
la source

Réponses:

95

Ce que vous recherchez, c'est date --date='06/12/2012 07:21:22' +"%s". Gardez à l'esprit que cela suppose que vous utilisez GNU coreutils, car les deux --dateet la %schaîne de format sont des extensions GNU. POSIX ne spécifie ni l'un ni l'autre, il n'y a donc pas de moyen portable de faire une telle conversion, même sur les systèmes compatibles POSIX.

Consultez la page de manuel appropriée pour les autres versions de date.

Remarque: bash --dateet -doption s'attendent à ce que la date soit au format US ou ISO8601, c'est-à-dire mm/dd/yyyyou yyyy-mm-ddnon au Royaume-Uni, dans l'UE ou dans tout autre format.

Daniel Kamil Kozar
la source
9
J'obtiens 'date: option illégale -' quand je cours sur Mac OSX 10.8.2
Ben Clayton
6
Pour noobs comme moi +"%s"représente le format de sortie et %sest le format de l'heure en secondes depuis 1970
razz
2
Remarque: si vous souhaitez spécifier l'heure dans un autre fuseau horaire (comme UTC), ajoutez -HHMM ou + HHMM à la fin. Donc date --date='06/12/2012 07:21:22 -0000' +"%s"convertit la date UTC en horodatage Unix
Greg Bray
Pour la date GNU, si vous souhaitez utiliser UTC, notez que le format est de yyyy-mm-dd hh:mm:ssjeter un œil à gnu.org/software/coreutils/manual/html_node/… :gdate --date='2019-06-18 00:02:00 +0000' +%s
Ashutosh Jindal
ne fonctionne pas sur un Mac ... Je me demande s'il existe un moyen de travailler à la fois sur Mac et Linux
nonopolarité le
47

Pour Linux, exécutez cette commande

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

Pour mac OSX, exécutez cette commande

date -j -u -f "%a %b %d %T %Z %Y" "Tue Sep 28 19:35:15 EDT 2010" "+%s"
Abdul Rehman Janjua
la source
1
Sur OSX, l'horodatage augmente d'une manière ou d'une autre avec l'heure actuelle. Je n'ai actuellement pas d'explication à cela ...
polym
3
Mise à jour: C'était parce qu'il ajuste l'horodatage de mon heure locale, je suppose ... L'ajout d'un -uindicateur devrait résoudre ce problème.
polym
@AbdulRehmanJanjua Le -udrapeau doit venir avant le -fdrapeau, sinon le shell l'interprète comme la chaîne de format. Donc, ça devrait être:date -j -u -f "%a..."
4
Coller exactement cela dans un terminal macOS échoue.
zneak
6
date -jf "%Y-%m-%d %H:%M:%S" "2018-01-08 14:45:00" +%s
daviestar
10

Beaucoup de ces réponses sont trop compliquées et manquent également de savoir comment utiliser les variables. Voici comment vous le feriez plus simplement sur un système Linux standard (comme mentionné précédemment, la commande de date devrait être ajustée pour les utilisateurs Mac):

Exemple de script:

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

Résulte en :

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

Ou en fonction:

# -- 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
la source
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
la source
5
Bienvenue dans Stack Overflow. Pensez à ajouter une explication en plus de votre code.
Olivier De Meulder
2

Solution efficace utilisant datecomme processus dédié en arrière-plan

Afin de rendre ce genre de traduction beaucoup plus rapide ...

Intro

Dans cet article, vous trouverez

  • une démo rapide , suite à ceci,
  • quelques explications ,
  • une fonction utilisable pour de nombreux Un * x outils ( bc, rot13, sed...).

Démo rapide

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

Cela doit sortir le courant UNIXTIME . À partir de là, vous pouvez comparer

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

et:

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

De plus de 6 secondes à moins d'une demi-seconde !! (sur mon hôte).

Vous pouvez vérifier echo $ans, remplacer "now"par "2019-25-12 20:10:00"et ainsi de suite ...

Facultativement, vous pouvez, une fois l'exigence de sous-processus de date terminée:

exec 5>&- ; exec 6<&-

Message original (explication détaillée)

Au lieu d'exécuter 1 fork par date pour convertir, exécutez datejuste 1 fois et effectuez toutes les conversions avec le même processus (cela pourrait devenir beaucoup plus rapide)!:

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

Échantillon:

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

Alors maintenant, jetez un œil:

declare -p start1 start2 dirchg userdate

(peut répondre à quelque chose comme:

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

Cela a été fait en une seule exécution!

Utilisation d' un sous- processus de longue durée

Nous avons juste besoin d'un fifo :

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

(Remarque: pendant que le processus est en cours d'exécution et que tous les descripteurs sont ouverts, nous pourrions supprimer en toute sécurité l'entrée du système de fichiers de fifo.)

Alors maintenant:

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

On pourrait faire une petite fonction:

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

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

Ou utilisez ma newConnector fonction

Avec des fonctions de connexion MySQL/MariaDB , PostgreSQLet SQLite...

Vous pouvez les trouver en différentes versions sur GitHub , ou sur mon site: télécharger ou afficher .

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: Sur GitHub , les fonctions et le test sont des fichiers séparés. Sur mon site, les tests sont exécutés simplement si ce script ne provient pas .

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

Assurez-vous simplement du fuseau horaire que vous souhaitez utiliser.

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

L'utilisation la plus courante prend le fuseau horaire de la machine.

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

Mais au cas où vous voudriez intentionnellement passer la date UTC et que vous voulez un fuseau horaire approprié, vous devez ajouter un -uindicateur. Sinon, vous le convertissez à partir de votre fuseau horaire local.

date -u -d "$datetime" +"%s" #general output = "1339485682"
Tajni
la source
Que faire si mon format de date est "AAAAMMJJ"? ex. 20200827
Mayur Gite
Vous pouvez également l'utiliser. dateformate correctement cette entrée.
Tajni