英文:
How do I subtract milliseconds from time in this format: "2020-01-06 11:27:12.280" in shell script
问题
我有时间格式2020-01-06 11:27:12.280
,其中.280
表示毫秒。
想要从这个时间中减去500
毫秒,并再次以相同的时间格式获得结果。
我尝试过使用以下命令将日期时间转换为纪元时间:
date +%s -d "2020-01-06 11:27:12.280"
但它不考虑毫秒。
英文:
I have time format 2020-01-06 11:27:12.280
where .280
is milliseconds.
Want to subtract 500
milliseconds from this time and get result in same time format again.
I have tried to convert date time in epoch time using this command:
date +%s -d"2020-01-06 11:27:12.280
but is does not consider milliseconds.
答案1
得分: 3
GNU: 使用GNU date,可以直接在date命令内部进行减法运算。这在Léa Gris的评论中有演示:
$ date -d "2020-01-06 11:27:12.280 - 0.5 sec" '+%F %T.%3N'
2020-01-06 11:27:11.780
这在这里有效,因为GNU date有使用-d
标志查询任何日期字符串的可能性,并且具有纳秒的知识。
BSD/MacOS: BSD date的行为不同。在这里需要更多的工作:
$ d="2020-01-06 11:27:12.280"
$ d=$(( $(date -j -f "%F %T" "${d%.*}" "+%s")${d#*.} - 500 ))
$ date -r "${d%${d: -3}}" "+%F %T.${d: -3}"
2020-01-06 11:27:11.780
POSIX: 如果要遵循POSIX标准,情况就不同了。根据POSIX标准,不能使用date
命令,因为无法使用-d
标志设置自己的日期时间,也没有指定毫秒或纳秒的格式。因此,需要使用不同的工具。有很多可能的方法,但我们将在这里使用POSIX awk的一个版本:
awk -v d='2020-01-06 11:27:12.280' '
BEGIN{ gsub(/[-:]/," ",d); strftime_posix(mktime_posix(d)-0.5) }
# 从"天文算法"中的算法J.Meeus
function mktime_posix(datestring, a,t) {
split(datestring,a," ")
if (a[1] < 1970) return -1
if (a[2] <= 2) { a[1]--; a[2]+=12 }
t=int(a[1]/100); t=2-t+int(t/4)
t=int(365.25*a[1]) + int(30.6001*(a[2]+1)) + a[3] + t - 719593
return t*86400 + a[4]*3600 + a[5]*60 + a[6]
}
function strftime_posix(epoch, JD,yyyy,mm,dd,HH,MM,SS,A,B,C,D,E ) {
if (epoch < 0 ) return "0000 00 00 00 00 00.000000"
JD=epoch; SS=JD%60; JD-=SS; JD/=60; MM=JD%60;
JD-=MM; JD/=60; HH=JD%24; JD-=HH; JD/=24;
JD+=2440588
A=int((JD - 1867216.25)/(36524.25))
A=JD+1+A-int(A/4)
B=A+1524; C=int((B-122.1)/365.25); D=int(365.25*C); E=int((B-D)/30.6001)
dd=B-D-int(30.6001*E)
mm = E < 14 ? E-1 : E - 13
yyyy=mm>2?C-4716:C-4715
return sprintf("%0.4d-%0.2d-%0.2d %0.2d:%0.2d:%06.3f",yyyy,mm,dd,HH,MM,SS)
}
'
英文:
GNU: Using GNU date, it is possible to do the subtraction directly within the date-command. This is demonstrated in the comment of Léa Gris:
$ date -d "2020-01-06 11:27:12.280 - 0.5 sec" '+%F %T.%3N'
2020-01-06 11:27:11.780
This works here because GNU date has the possibility to query any date-string using the -d
flag and has knowledge of nanoseconds.
BSD/MacOS: BSD date is behaving differently. You need a bit more work here:
$ d="2020-01-06 11:27:12.280"
$ d=$(( $(date -j -f "%F %T" "${d%.*}" "+%s")${d#*.} - 500 ))
$ date -r "${d%${d: -3}}" "+%F %T.${d: -3}"
2020-01-06 11:27:11.780
POSIX: If you want to be POSIX compliant, it is a different story. According to the POSIX standard, the date
command cannot be used here as you cannot set your own date-time with the -d
flag, and neither is there a format that specifies mili or nanoseconds. Hence, one is required to use different tools. There are many possible ways, but we will use here a version of POSIX awk:
awk -v d='2020-01-06 11:27:12.280' '
BEGIN{ gsub(/[-:]/," ",d); strftime_posix(mktime_posix(d)-0.5) }
# Algorithm from "Astronomical Algorithms" By J.Meeus
function mktime_posix(datestring, a,t) {
split(datestring,a," ")
if (a[1] < 1970) return -1
if (a[2] <= 2) { a[1]--; a[2]+=12 }
t=int(a[1]/100); t=2-t+int(t/4)
t=int(365.25*a[1]) + int(30.6001*(a[2]+1)) + a[3] + t - 719593
return t*86400 + a[4]*3600 + a[5]*60 + a[6]
}
function strftime_posix(epoch, JD,yyyy,mm,dd,HH,MM,SS,A,B,C,D,E ) {
if (epoch < 0 ) return "0000 00 00 00 00 00.000000"
JD=epoch; SS=JD%60; JD-=SS; JD/=60; MM=JD%60;
JD-=MM; JD/=60; HH=JD%24; JD-=HH; JD/=24;
JD+=2440588
A=int((JD - 1867216.25)/(36524.25))
A=JD+1+A-int(A/4)
B=A+1524; C=int((B-122.1)/365.25); D=int(365.25*C); E=int((B-D)/30.6001)
dd=B-D-int(30.6001*E)
mm = E < 14 ? E-1 : E - 13
yyyy=mm>2?C-4716:C-4715
return sprintf("%0.4d-%0.2d-%0.2d %0.2d:%0.2d:%06.3f",yyyy,mm,dd,HH,MM,SS)
}
'
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论