【问题标题】:Bash - convert time interval string to nr. of secondsBash - 将时间间隔字符串转换为 nr。秒
【发布时间】:2016-11-07 08:27:07
【问题描述】:

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

经过一些实验,我发现我可以像这样使用date

soon=$(date -d '5 minutes 10 seconds' +%s); now=$(date +%s)
echo $(( $soon-$now ))

但我认为应该有一种更简单的方法可以将诸如“5 分 10 秒”之类的字符串转换为相应的秒数,在本例中为 310。有没有办法在一个命令中做到这一点?强>

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

【问题讨论】:

    标签: bash time timestamp


    【解决方案1】:

    你可以从纪元开始

    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
    

    【讨论】:

      【解决方案2】:

      有一种方法可以做到这一点,无需在纯bash 中使用date 命令(为了便携性)

      假设您只有一个输入字符串来转换 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
      

      您可以直接在命令行上运行上述命令,无需$ 标记。

      【讨论】:

      • 我不赞成你的回答的原因是因为这不能回答我的问题。我正在尝试以“5 分 10 秒”的形式转换一个字符串。如果我已经以“hh:mm:ss”的形式拥有它,那确实很容易
      【解决方案3】:

      这样就可以了(添加纪元 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
      

      【讨论】:

        【解决方案4】:

        之前的建议在 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/years\{0,1\}/y/g; s/months\{0,1\}/m/g; s/days\{0,1\}/d/g; s/hours\{0,1\}/h/g; s/minutes\{0,1\}/m/g; s/min/m/g; s/seconds\{0,1\}/s/g; s/sec/s/g;  s/ //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
        }
        

        【讨论】:

        • sed "$template" 在 macOS 上无法与默认的 sed 一起使用,但如果他们安装并使用 gnu-sed,它应该会很好用。
        • 我更新了 normalize 函数以使用更简单的逻辑,首先替换整个单词。现在复数形式和多个空格也可以正常工作了。
        • 不错的一个!你如何区分几个月和几分钟?
        • 执行此类计算的库/工具通常不支持月份。天数不一致:2 月为 28/29。其余时间为 30/31。因此只需使用30d
        【解决方案5】:

        编辑:是的。我为 OP 在评论后开发并在 Mac OS X、CentOS 和 Ubuntu 上进行了检查。一个衬里,POSIX 兼容命令,用于将“X 分钟 Y 秒”格式转换为秒。 这就是问题

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

        OP 通过评论告诉我,他想要“X 分钟 Y 秒”格式而不是 HH:MM:SS 格式。带有date"+%s" 的命令在(我的)Mac 上抛出错误。 OP 想从“X 分钟 Y 秒”格式中获取数值并将其转换为秒。首先,我提取了数字中的分钟(将其作为方程式 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 所做的那样。

        如果我们想在“X 分钟 Y 秒”格式的值的日志文件上运行它,我们必须将 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

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

        【讨论】:

        • 这对我没有帮助,因为我正在尝试以“5 分 10 秒”的形式转换字符串。如果我已经以“hh:mm:ss”的形式拥有它,那确实很容易
        猜你喜欢
        • 2011-07-04
        • 2013-02-17
        • 2012-05-26
        • 2011-07-11
        • 1970-01-01
        • 1970-01-01
        • 2016-08-01
        • 1970-01-01
        • 2017-10-11
        相关资源
        最近更新 更多