Chuyển đổi chuỗi ngày tháng thành kỷ nguyên trong Bash


90

Chuỗi ngày tháng có định dạng sau: 06/12/2012 07:21:22. Làm cách nào để chuyển đổi nó thành dấu thời gian hoặc kỷ nguyên UNIX?

Câu trả lời:


92

Những gì bạn đang tìm kiếm là date --date='06/12/2012 07:21:22' +"%s". Hãy nhớ rằng điều này giả sử bạn đang sử dụng lõi GNU, vì cả hai --date%schuỗi định dạng đều là phần mở rộng GNU. POSIX không chỉ định một trong hai điều đó, vì vậy không có cách nào di động để thực hiện chuyển đổi như vậy ngay cả trên các hệ thống tuân thủ POSIX.

Tham khảo trang hướng dẫn thích hợp cho các phiên bản khác của date.

Lưu ý: bash --date-dtùy chọn dự kiến ​​ngày ở định dạng US hoặc ISO8601, tức là mm/dd/yyyyhoặc yyyy-mm-dd, không phải ở Vương quốc Anh, EU hoặc bất kỳ định dạng nào khác.


8
Tôi nhận được 'ngày: tùy chọn bất hợp pháp -' khi tôi chạy trên Mac OSX 10.8.2
Ben Clayton

6
Đối với những người như tôi +"%s"là viết tắt của định dạng đầu ra và %slà định dạng thời gian tính bằng giây kể từ năm 1970
razz

2
Lưu ý: nếu bạn muốn chỉ định thời gian trong một múi giờ khác (như UTC), hãy thêm -HHMM hoặc + HHMM vào cuối. Vì vậy, date --date='06/12/2012 07:21:22 -0000' +"%s"chuyển đổi ngày UTC gian tem unix
Greg Bray

Đối với ngày GNU, nếu bạn muốn sử dụng tính theo giờ UTC lưu ý rằng định dạng là yyyy-mm-dd hh:mm:sscó một cái nhìn tại gnu.org/software/coreutils/manual/html_node/... :gdate --date='2019-06-18 00:02:00 +0000' +%s
Ashutosh Jindal

không hoạt động trên máy Mac ... Tôi tự hỏi liệu có cách nào để hoạt động trên cả máy Mac và Linux
nonopolarity

47

Đối với Linux Chạy lệnh này

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

Đối với mac OSX, hãy chạy lệnh này

date -j -u -f "%a %b %d %T %Z %Y" "Tue Sep 28 19:35:15 EDT 2010" "+%s"

1
Trên OSX, dấu thời gian tăng lên bằng cách nào đó với thời gian hiện tại. Tôi hiện không có lời giải thích cho điều đó ...
polym 22/09/15

3
Cập nhật: Đó là vì nó điều chỉnh dấu thời gian cho giờ địa phương của tôi, tôi đoán ... Thêm -ucờ sẽ khắc phục điều đó.
polym

@AbdulRehmanJanjua Các -ucờ nên đến trước khi những -flá cờ, hoặc người nào khác diễn giải vỏ nó là chuỗi định dạng. Vì vậy, nó phải là:date -j -u -f "%a..."

4
Không thể dán chính xác thông tin đó trong thiết bị đầu cuối macOS.
zneak

6
date -jf "%Y-%m-%d %H:%M:%S" "2018-01-08 14:45:00" +%s
daviestar

10

Rất nhiều câu trả lời quá phức tạp và cũng thiếu cách sử dụng các biến. Đây là cách bạn thực hiện đơn giản hơn trên hệ thống Linux tiêu chuẩn (như đã đề cập trước đó, lệnh ngày sẽ phải được điều chỉnh cho Người dùng Mac):

Kịch bản mẫu:

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

Kết quả trong :

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

Hoặc như một chức năng:

# -- 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
}

5
Chào mừng bạn đến với Stack Overflow. Cân nhắc thêm lời giải thích ngoài mã của bạn.
Olivier De Meulder

2

Giải pháp hiệu quả sử dụng datelàm quy trình chuyên dụng nền

Để thực hiện loại bản dịch này nhanh hơn rất nhiều ...

Giới thiệu

Trong bài đăng này, bạn sẽ tìm thấy

  • một Demo nhanh , sau đây,
  • một số giải thích ,
  • một chức năng sử dụng được cho nhiều Un * x công cụ ( bc, rot13, sed...).

Demo nhanh

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

Điều này phải xuất ra UNIXTIME hiện tại . Từ đó, bạn có thể so sánh

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

và:

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

Từ hơn 6 giây đến dưới nửa giây !! (trên máy chủ của tôi).

Bạn có thể kiểm tra echo $ans, thay thế "now"bằng "2019-25-12 20:10:00", v.v.

Tối ưu, bạn có thể, sau khi quy trình phụ yêu cầu về ngày kết thúc:

exec 5>&- ; exec 6<&-

Bài gốc (giải thích chi tiết)

Thay vì chạy 1 fork theo ngày để chuyển đổi, hãy chạy datechỉ 1 lần và thực hiện tất cả chuyển đổi với cùng một quy trình (việc này có thể trở nên nhanh hơn rất nhiều) !:

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

Mẫu vật:

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

Sau đó, bây giờ hãy xem:

declare -p start1 start2 dirchg userdate

(có thể trả lời đại loại như:

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

Điều này đã được thực hiện trong một lần thực hiện!

Sử dụng quy trình con chạy lâu dài

Chúng tôi chỉ cần một năm mươi :

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

(Lưu ý: Khi quá trình đang chạy và tất cả các bộ mô tả được mở, chúng tôi có thể xóa mục nhập hệ thống tệp của năm mươi một cách an toàn.)

Ngay sau đó:

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

Chúng tôi có thể cài đặt một chức năng nhỏ:

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

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

Hoặc sử dụng chức năng của tôi newConnector

Với chức năng cho kết nối MySQL/MariaDB , PostgreSQLSQLite...

Bạn có thể tìm thấy chúng ở phiên bản khác trên GitHub hoặc trên trang web của tôi: tải xuống hoặc hiển thị .

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

Lưu ý: Trên GitHub , các chức năng và bài kiểm tra là các tệp riêng biệt. Trong thử nghiệm trang web của tôi được chạy đơn giản nếu tập lệnh này không có nguồn gốc .

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

2

Chỉ cần chắc chắn múi giờ bạn muốn sử dụng.

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

Hầu hết việc sử dụng phổ biến đều có múi giờ của máy.

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

Nhưng trong trường hợp bạn cố tình muốn chuyển ngày giờ UTC và bạn muốn có múi giờ thích hợp, bạn cần thêm -ucờ. Nếu không, bạn chuyển đổi nó từ múi giờ địa phương của bạn.

date -u -d "$datetime" +"%s" #general output = "1339485682"
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.