我目前遇到了mac date command的两个问题。
我正在运行一个shell脚本,该脚本首先执行命令(ps -p $ p_id -o etime =),以使用 p_id 为我提供进程的已用时间,返回 [[dd-] hh:] mm:ss
形式的日期问题1:以下命令将日期转换为另一种格式似乎导致了奇怪的问题: (日期-j -f“%H:%M:%s”“$ processStartTime”“+%H:%M:%s”)。 说 prcoessStartTime = 12:30:33 。此命令返回的输出日期为 01:00:33 ,即使我将日期转换为相同的格式。它只能得到正确的秒数,小时和分钟是错误的。如果我使用不同的引号,如''围绕日期格式,我甚至得到更奇怪的结果!目标是将时间转换为分钟,以便我可以看到该过程运行了多少分钟。
问题2:由于处理日期可以采用以下格式 [[dd-] hh:] mm:ss 我应该如何在代码中处理不同的日期格式?我应该有3个条件来检查格式吗?还是有办法处理这个?即一些日期可能是hh:mm:ss和其他mm:ss的形式,我需要在命令中输入日期格式正确,否则会引发错误。
答案 0 :(得分:1)
sed
格式化MaxOS的日期 dst 格式。有一个强大的sed
命令来重置MacOs的日期命令的值(不是很性感,但它有效):
date -j $(
ps ho lstart= $p_id |
sed '
s/^....//;
s/Jan/01/;s/Feb/02/;s/Mar/03/;s/Apr/04/;s/May/05/;s/Jun/06/;
s/Jul/07/;s/Aug/08/;s/Sep/09/;s/Oct/10/;s/Nov/11/;s/Dec/12/;
s/^\([0-9]\{2\}\) \([0-9]\{2\}\) \([0-9]\{2\}\):\([0-9]\{2\}\):\([0-9]\{2\}\) [0-9]\{2\}\([0-9]\{2\}\)/\1\2\3\4\6.\5/;
') +%s
这将在 unixtimestamp 中呈现进程$p_id
的开始时间。
# Building translation variables for months strings
for ((i=1;i<13;i++));do
val=$(printf %02d $i)
mnt=$(date -j ${val}010101 +%b)
eval mn$mnt=$val
done
IFS=': ' read -a psdate < <(ps ho lstart= $p_id)
var=mn${psdate[1]}
printf -v fdte "%02d%02d%02d%02d%02d.%02d" ${!var} ${psdate[2]} \
${psdate[3]} ${psdate[4]} ${psdate[6]#??} ${psdate[5]}
date -j $fdte +%s
这两个命令都在MacOS上测试过。我发现第二个性感。
答案 1 :(得分:0)
你似乎在搅拌苹果和橘子。
date
命令与时间戳一起使用 - 这些是单个离散时间点的简单原子表示,因此,它们指的是绝对时间。在实现方面,time_t
传统上是UTC时间1970年1月1日午夜(在Unix上)的秒数。
相比之下,您正在处理的时间信息是 relative ,表示时间范围。
如果A是&#34;现在&#34; &B是&#34;一小时三十三秒&#34;,它是指从A-B开始到A结束的时间,还是指从A开始到A + B结束的时间?或者它与其他一些时间点相关? date
命令通常解释没有相对于前一个午夜的日期的时间;所以你(隐含地)得到一个从午夜开始并在指定时间结束的范围。
date
命令还有一个解析器,用于表示相对时间的各种人类表达,但它必然是不准确和不可预测的,因为它是人类语言的方式。
vbvntv$ date -d 'tomorrow 07:00'
Tue Nov 11 07:00:00 EET 2014
我无法访问可以对其进行测试的Mac,但通常情况下,在解析人类日期时似乎功能较差且功能较差。
在您的情况下,您不清楚自己真正想做什么。也许你想计算A-B的时间,即给定现在完成的工作量(A)并花费B时间,何时开始?
这样做的常用方法是将它们转换为绝对秒数。
vbvntv$ date -d "00:00"
Mon Nov 10 00:00:00 EET 2014
vbvntv$ date -d "00:00" +%s
1415570400
vbvntv$ date -d "01:00:33"
Mon Nov 10 01:00:33 EET 2014
vbvntv$ date -d "01:00:33" +%s
1415574033
vbvntv$ echo $((1415574033-1415570400))
3633
vbvntv$ date -d "3633 seconds ago"
Mon Nov 10 09:53:05 EET 2014
vbvntv$ # or alternatively
vbvntv$ date +%s
1415609708
vnvntv$ date -d @$((1415609708-3633))
Mon Nov 10 09:53:15 EET 2014
答案 2 :(得分:0)
解决问题没有。 1 您必须将%s
替换为%S
(正如RBH已经建议的那样):
processStartTime='12:30:33'
- date -j -f "%H:%M:%s" "$processStartTime" "+%H:%M:%s"
+ date -j -f "%H:%M:%S" "$processStartTime" "+%H:%M:%S"
结合F. Hauri引入的ps ho lstart= $pid
方法与设置LANG='C'
,可以避免问题没有。 2 ::
{
pid='1'
ps_date="$(LANG='C' ps ho lstart= $pid)"
# convert ps_date to Unix epoch time
processStartTimeEpochTime="$(LANG='C' date -j -f '%a %b %d %T %Y' "$ps_date" '+%s' 2>/dev/null)"
elapsed_secs="$(( $(date '+%s') - ${processStartTimeEpochTime} ))"
printf '%s\n' "ps_date: $ps_date" "processStartTimeEpochTime: $processStartTimeEpochTime"
printf '%s\n' "elapsed seconds: $elapsed_secs" "elapsed minutes: $(( $elapsed_secs / 60 ))" "elapsed hours: $(( $elapsed_secs / 3600 ))"
printf '%s' 'processStartTimeEpochTime reversed: '
date -r "$processStartTimeEpochTime" '+%F--%T'
}
如果您坚持使用 ps -p $pid -o etime=
,由于解析了 [[dd-]hh:]mm:ss
格式,它会变得有点笨拙。
{
pid='1'
# days, hours, minutes, seconds
# format: [[dd-]hh:]mm:ss
dhms="$(ps -p $pid -o etime=)"
days=""
h=""
m=""
s=""
get_hms() {
hms="$1"
h=${hms%%:*}
hms=${hms#*:};
m=${hms%%:*}
hms=${hms#*:};
s=${hms}
return 0
}
case "$dhms" in
??-??:??:??) days=${dhms%%-*}; hms=${dhms#*-}; get_hms "$hms";;
?-??:??:??) days=${dhms%%-*}; hms=${dhms#*-}; get_hms "$hms";;
??:??:??) days="0"; hms="$dhms"; get_hms "$hms";;
?:??:??) days="0"; hms="0${dhms}"; get_hms "$hms";;
??:??) days="0"; hms="00:${dhms}"; get_hms "$hms";;
?:??) days="0"; hms="00:0${dhms}"; get_hms "$hms";;
??) days="0"; hms="00:00:${dhms}"; get_hms "$hms";;
?) days="0"; hms="00:00:0${dhms}"; get_hms "$hms";;
*) days=""; hms="";;
esac
# strip a leading 0 if any
days="${days#0}"
h="${h#0}"
m="${m#0}"
s="${s#0}"
[ X"$days" = "X" ] && days='0'
[ X"$h" = "X" ] && h='0'
[ X"$m" = "X" ] && m='0'
[ X"$s" = "X" ] && s='0'
printf '%s\n' "d: $days" "h: $h" "m: $m" "s: $s"
days_in_secs=$(( $days * 86400 ))
hours_in_secs=$(( $h * 3600 ))
minutes_in_secs=$(( $m * 60 ))
time_span_in_secs=$(( $days_in_secs + $hours_in_secs + $minutes_in_secs + $s ))
processStartEpochTime="$(( $(date '+%s') - ${time_span_in_secs} ))"
printf '%s\n' "dhms: $dhms"
printf '%s' 'processStartEpochTime reversed: '
date -r "$processStartEpochTime" '+%F--%T'
printf '%s\n' "elapsed seconds: $time_span_in_secs" "elapsed minutes: $(( $time_span_in_secs / 60 ))" "elapsed hours: $(( $time_span_in_secs / 3600 ))"
}