Bash - 将时间间隔字符串转换为nr。几秒钟

时间:2016-11-07 08:27:07

标签: bash time timestamp

我正在尝试将描述时间间隔的字符串转换为相应的秒数。

经过一些实验,我发现我可以像这样使用 private void ChangeMessage(ref Message reply) { Message newMessage = null; MessageBuffer msgbuf = reply.CreateBufferedCopy(int.MaxValue); Message tmpMessage = msgbuf.CreateMessage(); XmlDictionaryReader xdr = tmpMessage.GetReaderAtBodyContents(); XElement bodyEl = XElement.Load(xdr.ReadSubtree()); var someElement= bodyEl.Descendants().FirstOrDefault(b => b.Name.LocalName == "somename"); XElement newElement = getNewSomeElement();//private method someElement.ReplaceWith(newElement);//replacing node into body MemoryStream ms = new MemoryStream(); XmlWriter xw = XmlWriter.Create(ms); bodyEl.Save(xw); xw.Flush(); xw.Close(); ms.Position = 0; XmlReader xr = XmlReader.Create(ms); //create new message from modified XML document newMessage = Message.CreateMessage(reply.Version, null, xr); newMessage.Headers.CopyHeadersFrom(reply); newMessage.Properties.CopyProperties(reply.Properties); reply = newMessage; }

date

但我认为应该有一种更简单的方法将“5分10秒”之类的字符串转换为相应的秒数,在本例中为310. 有没有办法在一个命令中执行此操作?

注意:虽然可移植性很有用,但这不是我的首要任务。

5 个答案:

答案 0 :(得分:7)

你可以从纪元开始

date -d"1970-01-01 00:00:00 UTC 5 minutes 10 seconds" "+%s"
310

你也可以很容易地分时

Time="1 day"
date -d"1970-01-01 00:00:00 UTC $Time" "+%s"
86400

答案 1 :(得分:1)

有一种方法可以在纯date中使用bash命令(为了便携性)

假设您只有一个输入字符串,可以在bash变量中转换“5分10秒”并带有:限制器,如下所示。

$ convertString="00:05:10"
$ IFS=: read -r hour minute second <<< "$convertString"
$ secondsValue=$(((hour * 60 + minute) * 60 + second))
$ printf "%s\n" "$secondsValue"
310

您可以直接在命令行上运行上述命令而不使用$标记。

答案 2 :(得分:1)

这样做(添加纪元19700101):

$ date -ud '19700101 5 minutes 10 seconds' +%s
310

添加-u以避免本地时间(和DST)效果非常重要。

$ TZ=America/Los_Angeles date -d '19700101 5 minutes 10 seconds' +%s
29110

请注意,日期可以做一些数学运算:

$ date -ud '19700101 +5 minutes 10 seconds -47 seconds -1 min' +%s
203

答案 3 :(得分:0)

修改:是的。我在评论后为OP开发了,并在Mac OS X,CentOS和Ubuntu上进行了检查。一个内衬,POSIX兼容命令,用于转换&#34; X分钟Y秒&#34;格式为秒。 那就是问题

echo $(($(echo "5 minutes 10 seconds" | cut -c1-2)*60  + $(echo "5 minutes 10 seconds" | cut -c1-12 | awk '{print substr($0,11)}')))
OP通过评论告诉我,他想要&#34; X分钟Y秒&#34;格式不适用于HH:MM:SS格式。 date"+%s"的命令会在(我的)Mac上抛出错误。 OP希望从&#34; X分钟Y秒和#34;中获取数值。格式并将其转换为秒。首先,我用数字提取分钟(将其作为等式A):

echo "5 minutes 10 seconds" | cut -c1-2)

然后我提取了秒部分(将其作为等式B):

echo "5 minutes 10 seconds" | cut -c1-12 | awk '{print substr($0,11)}'

现在将分钟乘以60然后再加上另一个:

echo $((equation A)*60) + (equation B))

OP应该要求其他人检查我的开发版本(但正在工作)命令,然后再将其用于自动重复使用,就像在生产服务器上使用cron一样。

如果我们想在日志文件中运行此操作,其值为&#34; X分钟Y秒&#34;格式,我们必须将echo "5 minutes 10 seconds"更改为cat file | ...之类的命令。 I kept a gist of it too如果我或其他人需要,我们可以将其与cat一起使用,以x minutes y seconds日志格式运行服务器日志文件。

虽然偏离主题(我的理解,问题与当前时间没什么关系),但这对于POSIX兼容的操作系统无法在几秒钟内获得当前时间:

date -d "1970-01-01 00:00:00 UTC 5 minutes 10 seconds" "+%s"

它会在MacOS X上引发错误但在大多数GNU / Linux发行版上都有效。在复杂的使用情况下,+%s部分将在符合POSIX的操作系统上抛出错误。这些命令主要适用于在POSIX上获得适用于任何类型的unix的操作时间,如OS:

awk 'BEGIN{srand(); print srand()}'
perl -le 'print time' 

如果OP需要可以通过以秒为单位生成当前时间来延长它并减去。我希望它会有所帮助。

----旧编答案之前的答案----

您可以获得没有date - echo | awk '{print systime();}'wget -qO- http://www.timeapi.org/utc/now?\\s的当前时间。将时间转换为秒的其他方法是echo "00:20:40.25" | awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }'

另一个答案中显示printf的示例近乎完美。

GNU / Linux的基本实用程序 - gnu.org/../../../../../Setting-an-Alarm.html

总是需要你想要的东西

接近方式取决于你需要多么万无一失的方式。

答案 4 :(得分:0)

先前的建议在alpine linux上无法正常工作,因此这里有一个符合POSIX的小助手功能,易于使用并且还支持计算(只是实现的副作用)。

该函数始终根据提供的参数返回整数。

$ durationToSeconds '<value>' '<fallback>'

$ durationToSeconds "1h 30m"
5400

$ durationToSeconds "$someemptyvar" 1h
3600

$ durationToSeconds "$someemptyvar" "1h 30m"
5400

# Calculations also work
$ durationToSeconds "1h * 3"
10800

$ durationToSeconds "1h - 1h"
0

# And also supports long forms for year, day, hour, minute, second
$ durationToSeconds "3 days 1 hour"
262800

# It's also case insensitive
$ durationToSeconds "3 Days"
259200
function durationToSeconds () {
  set -f
  normalize () { echo $1 | tr '[:upper:]' '[:lower:]' | tr -d "\"\\\'" | sed 's/ *y\(ear\)\{0,1\} */y /g; s/ *d\(ay\)\{0,1\} */d /g; s/ *h\(our\)\{0,1\} */h /g; s/ *m\(in\(ute\)\{0,1\}\)\{0,1\} */m /g; s/ *s\(ec\(ond\)\{0,1\}\)\{0,1\} */s /g; s/\([ydhms]\)s/\1/g'; }
  local value=$(normalize "$1")
  local fallback=$(normalize "$2")

  echo $value | grep -v '^[-+*/0-9ydhms ]\{0,30\}$' > /dev/null 2>&1
  if [ $? -eq 0 ]
  then
    >&2 echo Invalid duration pattern \"$value\"
  else
    if [ "$value" = "" ]; then
      [ "$fallback" != "" ] && durationToSeconds "$fallback"
    else
      sedtmpl () { echo "s/\([0-9]\+\)$1/(0\1 * $2)/g;"; }
      local template="$(sedtmpl '\( \|$\)' 1) $(sedtmpl y '365 * 86400') $(sedtmpl d 86400) $(sedtmpl h 3600) $(sedtmpl m 60) $(sedtmpl s 1) s/) *(/) + (/g;"
      echo $value | sed "$template" | bc
    fi
  fi
  set +f
}