วิธีการแปลงเวลาเป็นวันที่ใน Bash?


270

ฉันต้องการคำสั่งเชลล์หรือสคริปต์ที่แปลงเวลา Unix เป็นวันที่ อินพุตสามารถมาจากพารามิเตอร์แรกหรือจาก stdin ซึ่งอนุญาตให้ใช้รูปแบบการใช้งานต่อไปนี้:

ts2date 1267619929

และ

echo 1267619929 | ts2date

ทั้งสองคำสั่งควรส่งออก "พุธ 3 มีนาคม 13:38:49 2010"

คำตอบ:


531

ในการแจกแจง Linux ทั่วไปรุ่นต่อมาคุณสามารถใช้:

date -d @1267619929

5
สายการบินdate -d @$(date -u +%s)
Mike Atlas

26
มีไว้@เพื่ออะไร? ฉันไม่เห็นในหน้า GNU เลย
Mark E. Haase

13
@mehaase - man page บันทึกว่าสตริงวันที่ซับซ้อนเกินกว่าที่จะจัดทำเป็นเอกสารใน manpage ดังนั้นจึงมีการอธิบายในข้อมูล: info '(coreutils) การเรียกใช้วันที่'
MByD

10
brew install coreutils; gdate -d @1267619929
Mark Fox

2
info 'Date input formats' ทำให้คุณตรงไปที่dateโหนดข้อมูลการจัดรูปแบบด้วยคำพูดที่เกี่ยวข้องของ Robert Grudin จากนั้นก็เป็นเมนูของตัวระบุรูปแบบ
ไมค์

165
date -r <number>

ใช้ได้กับฉันใน Mac OS X


5
ใช่ แต่มันไม่ได้จัดการกับเศษเสี้ยวของวินาที
mgold

1
และมันก็สับสนเพราะมันไม่ได้ทำงานในระบบ Linux ส่วนใหญ่เพราะ: freddy @ hades ~% date --help | grep - -r -r, --reference = FILE แสดงเวลาแก้ไขล่าสุดของ FILE
frank42

1
ในขณะที่ความคิดเห็นเกี่ยวกับคำตอบนี้เป็นความจริง แต่สิ่งเหล่านี้ไม่ใช่ความผิดของราฟาและพวกเขาจะไม่ลดคำตอบลง
ไมค์

29

รุ่นนี้จะคล้ายกับchiborg ของคำตอบ แต่มันไม่จำเป็นต้องสำหรับภายนอกและtty catมันใช้แต่สามารถได้อย่างง่ายดายเพียงใช้date gawkคุณสามารถเปลี่ยน shebang และแทนที่วงเล็บเหลี่ยมสองอันด้วยอันเดียวและสิ่งนี้จะทำงานshด้วย

#!/bin/bash
LANG=C
if [[ -z "$1" ]]
then
    if [[ -p /dev/stdin ]]    # input from a pipe
    then
        read -r p
    else
        echo "No timestamp given." >&2
        exit
    fi
else
    p=$1
fi
date -d "@$p" +%c

+1: คำตอบที่สมบูรณ์มากและฉันคิดว่าเดทเร็วกว่าเพ่งพิศ
Bruno Brant

@Bruno คุณทราบได้อย่างไรว่าวันที่นั้นเร็วกว่า gawk?
ghostdog74

3
@Bruno @ ghostdog74: ในระบบของฉันgawkคือ (มากประมาณ) 15% เร็วกว่าdateในเวลาที่กำหนดforวงประกอบเพียงgawk 'BEGIN { print strftime("%c", 1256571985); }'หรือกับการส่งออกเปลี่ยนเส้นทางไปยังdate -d '@1256571985' +%c /dev/null
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

1
วันที่เล็กน้อย (5%) เร็วกว่า gawk สำหรับฉัน (mac osx 10.9.2, วันที่ 8.23, gawk 4.1.1) แต่ข้อดีที่แท้จริงของ (g) awk คือการยอมรับท่อของคอลัมน์ของการประทับเวลาหลายแห่ง (ดู คำตอบของฉันด้านล่าง) ซึ่งทำให้สคริปต์เช่น 250x เร็วเป็น 1000 timestamps
webb

3
โปรดทราบว่าคำตอบของฉันตรงตามข้อกำหนดของ OP ตามที่ระบุไว้ในคำถาม แต่คำตอบที่ยอมรับตอนนี้ไม่ได้
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

17

คุณสามารถใช้วันที่ของ GNU ได้เช่น

$ sec=1267619929
$ date -d "UTC 1970-01-01 $sec secs"

หรือ

$ date -ud @1267619929

10

คุณสามารถใช้สคริปต์ awk ง่าย ๆ นี้:

#!/bin/gawk -f   
{ print strftime("%c", $0); }

ตัวอย่างการใช้งาน:

$ echo '1098181096' | ./a.awk 
Tue 19 Oct 2004 03:18:16 AM PDT
$

สิ่งนี้ไม่พอดีกับการใช้งานครั้งแรก - บางครั้งฉันไม่ต้องการสะท้อน TS และใช้พารามิเตอร์แทน
chiborg

ในรุ่นเก่า busybox บางอันใช้งานdate -s @ไม่ได้และawkยังใช้งานได้! ตัวอย่างที่ไม่มี stdin ก็มีประโยชน์เช่นกัน
Victor Sergienko

8

ตั้งแต่ทุบตี 4.2 คุณสามารถใช้printfเป็น%(datefmt)Tรูปแบบ:

$ printf '%(%c)T\n' 1267619929
Wed 03 Mar 2010 01:38:49 PM CET

มันเยี่ยมมากเพราะมันเป็นตัวเชลล์ รูปแบบสำหรับdatefmtเป็นสตริงที่ยอมรับโดยstrftime(3)(ดูman 3 strftime) นี่%cคือ:

%c การแสดงวันที่และเวลาที่ต้องการสำหรับสถานที่ปัจจุบัน


ตอนนี้ถ้าคุณต้องการสคริปต์ที่ยอมรับการโต้แย้งและถ้าไม่มีให้อ่าน stdin คุณสามารถดำเนินการดังนี้:

#!/bin/bash

if (($#)); then
    printf '%(%c)T\n' "$@"
else
    while read -r line; do
        printf '%(%c)T\n' "$line"
    done
fi

6

ฉันใช้สิ่งนี้เมื่อแปลงไฟล์บันทึกหรือตรวจสอบพวกเขา:

tail -f <log file> | gawk \
'{ printf strftime("%c", $1); for (i=2; i<NF; i++) printf $i " "; print $NF }'

สิ่งที่ฉันกำลังมองหาสามารถย่อให้สั้นลงได้awk '{ printf strftime("%c: ", $1); $1 = ""; print $0; }'
ChrisWue

5

ใน OSX หรือ BSD มี-rค่าสถานะเทียบเท่าซึ่งเห็นได้ชัดว่าใช้เวลาประทับยูนิกซ์ นี่คือตัวอย่างที่รันวันที่สี่ครั้ง: หนึ่งครั้งสำหรับวันแรกเพื่อแสดงว่ามันคืออะไร; หนึ่งสำหรับการแปลงเป็นเวลา Unix ด้วย%sและในที่สุดซึ่งหนึ่งด้วยกับ-rแปลงสิ่งที่%sให้กลับไปที่สตริง

$  date; date +%s; date -r `date +%s`
Tue Oct 24 16:27:42 CDT 2017
1508880462
Tue Oct 24 16:27:42 CDT 2017

อย่างน้อยดูเหมือนว่าจะทำงานกับเครื่องของฉัน

$ uname -a
Darwin XXX-XXXXXXXX 16.7.0 Darwin Kernel Version 16.7.0: Thu Jun 15 17:36:27 PDT 2017; root:xnu-3789.70.16~2/RELEASE_X86_64 x86_64

หากคุณมีค่าการประทับเวลาแล้วและคุณต้องการค้นหาวันที่เทียบเท่าใน OS X คุณสามารถพิมพ์ได้ที่บรรทัดคำสั่ง: date -r 1509453417
Noel Whitemore

1
นั่นเป็นเรื่องจริง ถ้าคุณดูคำตอบของฉันฉันจะแสดงให้เห็นว่า
Daniel Farrell

5

คุณสามารถรับวันที่จัดรูปแบบจากการประทับเวลาเช่นนี้

date +'%Y-%m-%d %H:%M:%S' -d "@timestamp"

วิธีอื่น ๆ : date -ud "@ 1585667718" + '% Y-% m-% d% H:% M:% S'
AndiAna

3

ฉันได้เขียนสคริปต์ที่ทำสิ่งนี้เอง:

#!/bin/bash
LANG=C
if [ -z "$1" ]; then
    if [  "$(tty)" = "not a tty" ]; then
            p=`cat`;
    else
            echo "No timestamp given."
            exit
    fi
else
    p=$1
fi
echo $p | gawk '{ print strftime("%c", $0); }'

1
แท็กคำถามของคุณรวมถึง "ทุบตี" แต่ Shebang ของคุณพูดว่า "sh"
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

3

ในคำตอบนี้ฉันคัดลอกคำตอบของ Dennis Williamson และแก้ไขเล็กน้อยเพื่อให้ความเร็วเพิ่มขึ้นอย่างมากเมื่อทำการไพพ์คอลัมน์ของการประทับเวลาจำนวนมากไปยังสคริปต์ ตัวอย่างเช่นการวางท่อ 1,000 ครั้งลงในสคริปต์ต้นฉบับที่มี xargs -n1 บนเครื่องของฉันใช้เวลา 6.929 วินาทีเมื่อเทียบกับ 0.027 วินาทีด้วยเวอร์ชันที่ปรับเปลี่ยนนี้:

#!/bin/bash
LANG=C
if [[ -z "$1" ]]
then
    if [[ -p /dev/stdin ]]    # input from a pipe
    then
        cat - | gawk '{ print strftime("%c", $1); }'
    else
        echo "No timestamp given." >&2
        exit
    fi
else
    date -d @$1 +%c
fi

2

ตัวอย่างบางส่วน:

$ วันที่
อังคาร 22 มีนาคม, 16:47:06 CST 2016

$ date -d "อังคาร 22 มี.ค. , 16:47:06 CST 2016" "+% s"
1458636426

$ date +% s
1458636453

$ date -d @ 1458636426
อังคาร 22 มีนาคม, 16:47:06 CST 2016

$ date - วันที่ = '@ 1458636426'
อังคาร 22 มีนาคม, 16:47:06 CST 2016



2

ฉันใช้หนึ่งซับข้ามแพลตฟอร์มนี้:

date -d @1267619929 2>/dev/null || date -r 1267619929

มันควรทำงานได้ทั้งใน macOS และ Linux รุ่นทั่วไป


0

ในขณะที่ไม่ใช่ทุบตีบริสุทธิ์สคริปต์ต่อไปนี้จะแปลงการประทับเวลาความยาว 13 ในสตริงเป็นวันที่เทียบเท่าในเขตเวลาท้องถิ่นของคุณโดยใช้ Perl

timestamp_to_date.sh

#!/usr/bin/env bash
IT=$(cat /dev/stdin)
re='(.*)([0-9]{13})(.*)'
while [[ $IT =~ $re ]]; do
  TIMESTAMP=${BASH_REMATCH[2]}
  AS_DATE=$(echo "$TIMESTAMP" | perl -pe 's/([\d]{10})([\d]{3})/localtime $1/eg;')
  IT="${IT/$TIMESTAMP/$AS_DATE}"    
done
echo "$IT"

อินพุต

{"timestamp":"1573121629939","level":"DEBUG","thread":"http-nio-15372-exec-3","logger":"org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor"}

เอาท์พุต

$ cat input | timestamp_to_date.sh

{"timestamp":"Thu Nov  7 06:13:49 2019","level":"DEBUG","thread":"http-nio-15372-exec-3","logger":"org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor"}

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