แปลงสตริงวันเวลาเป็นยุคใน Bash


คำตอบ:


96

date --date='06/12/2012 07:21:22' +"%s"สิ่งที่คุณกำลังมองหาอยู่ โปรดทราบว่าการดำเนินการนี้ถือว่าคุณกำลังใช้ GNU coreutils เนื่องจากทั้งสอง--dateและ%sสตริงรูปแบบเป็นส่วนขยาย GNU POSIX ไม่ได้ระบุอย่างใดอย่างหนึ่งดังนั้นจึงไม่มีวิธีแบบพกพาในการแปลงดังกล่าวแม้ในระบบที่รองรับ POSIX

ปรึกษาหน้าคู่มือที่เหมาะสมสำหรับรุ่นอื่น ๆ dateของ

หมายเหตุ: bash --dateและ-doption คาดว่าวันที่ในรูปแบบ US หรือ ISO8601 เช่นmm/dd/yyyyหรือyyyy-mm-ddไม่อยู่ใน UK, EU หรือรูปแบบอื่น ๆ


9
ฉันได้รับ 'วันที่: ตัวเลือกที่ผิดกฎหมาย -' เมื่อฉันรันบน Mac OSX 10.8.2
Ben Clayton

6
สำหรับ noobs อย่างฉัน+"%s"หมายถึงรูปแบบผลลัพธ์และ%sเป็นรูปแบบของเวลาเป็นวินาทีตั้งแต่ปี 1970
razz

2
หมายเหตุ: หากคุณต้องการระบุเวลาในเขตเวลาอื่น (เช่น UTC) ให้เพิ่ม -HHMM หรือ + HHMM ต่อท้าย ดังนั้นdate --date='06/12/2012 07:21:22 -0000' +"%s"แปลงวันที่ UTC เป็นเวลาประทับแบบ unix
Greg Bray

สำหรับวันที่ 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
Ashutosh Jindal

ไม่ทำงานบน Mac ... ฉันสงสัยว่ามีวิธีทำงานทั้งบน Mac และ Linux หรือไม่
nonopolarity

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

10

คำตอบเหล่านี้จำนวนมากซับซ้อนเกินไปและไม่มีวิธีใช้ตัวแปร นี่เป็นวิธีที่คุณจะทำได้ง่ายขึ้นบนระบบ Linux มาตรฐาน (ตามที่กล่าวไว้ก่อนหน้านี้คำสั่งวันที่จะต้องปรับเปลี่ยนสำหรับผู้ใช้ 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เป็นกระบวนการเฉพาะเบื้องหลัง

เพื่อให้การแปลแบบนี้เร็วขึ้นมาก ...

Intro

ในโพสต์นี้คุณจะพบ

  • การสาธิตอย่างรวดเร็วตามนี้
  • บางคำอธิบาย ,
  • ฟังก์ชั่นใช้ได้นานหลายUn * xเครื่องมือ ( 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 forkตามวันที่เพื่อแปลงให้รัน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"

จะเกิดอะไรขึ้นถ้ารูปแบบวันที่ของฉันเป็น "YYYYmmdd" เช่น 20200827
Mayur Gite

คุณสามารถใช้มันได้เช่นกัน dateจัดรูปแบบข้อมูลนี้ให้ถูกต้อง
Tajni
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.