将基于时间的字符串转换为ISO格式

时间:2015-09-14 17:00:23

标签: ruby-on-rails ruby regex html5 datetime

我有一个b1 b2 b3 b4 8 NA NA 7 对象,它有一个持续时间属性(基于字符串),以分钟和秒为单位。我想将此输出为Song标签的datetime属性(通过Rails),但需要将其转换为ISO 8601格式才能使其在语义上有效。

所以,我有持续时间<time/>。在删除两个数字之间的冒号并最后在结尾附加字母"2:30"时,需要预先设置字符'PT'

'S'

最终输出:

PT2M30S

我将如何实现这一目标?

是否有Ruby方法可以实现这一目标?是否必须写出正则表达式才能找到/替换上述字符?

3 个答案:

答案 0 :(得分:2)

如果你想以优雅的方式做到这一点,试试ruby-duration gem

示例代码

Duration.new(:weeks => 1, :days => 20).iso8601 => "P3W6DT0H0M0S"

答案 1 :(得分:2)

它没有采用正则表达式或任何想要做的事情。我只是简单地拆分冒号,并将结果传递给格式字符串:

'PT%sM%sS' % "2:30".split(':') # => "PT2M30S"
  

在这种情况下,模运算符如何工作?从来没有见过这样的事情。

它不是&#34;模运算符&#34;除非它被应用于一个数字。它是一个名为%的String方法,相当于formatsprintf。有关详细信息,请参阅String.%后跟Kernel::sprintf,但基本上是:

  s   | Argument is a string to be substituted.  If the format
      | sequence contains a precision, at most that many characters
      | will be copied.

所以:

'%s'   % 'foo' # => "foo"
'%5s'  % 'foo' # => "  foo"
'%-5s' % 'foo' # => "foo  "
'%1s'  % 'foo' # => "foo"
'%.1s' % 'foo' # => "f"

'%s = %s' % ['a', 1] # => "a = 1"

请特别注意,在插入字符串时,最后一个1会转换为"1"。这可能很有用,但它不是从对象转换为字符串的唯一方式(甚至是更好的方式)。

最后,不要假设正则表达式是解决每个需要从字符串中提取信息的问题的方法。如果您可以在不使用奇怪的解决方法的情况下执行此操作,请使用内置方法,例如split

require 'fruity'

compare do
  _split { 'PT%sM%sS' % "2:30".split(':') }
  _regex { "2:30".sub(/(.*):(.*)/, "PT\\1M\\2S") }
end

结果是:

# >> Running each test 2048 times. Test will take about 1 second.
# >> _split is faster than _regex by 19.999999999999996% ± 10.0%

正则表达式很灵活,但通常以降低速度为代价。

此外,当gsub应该被使用时,我们会发现很多误导subsub的工作量比gsub少得多;如果sub触发一次,gsub将继续循环,直到它到达字符串的末尾。这是一个可衡量的差异,即使在诸如"2:30"

之类的短字符串上也是如此
compare do
  _sub { "2:30".sub(/(.*):(.*)/, "PT\\1M\\2S") }
  _gsub { "2:30".gsub(/(.*):(.*)/, "PT\\1M\\2S") }
end

# >> Running each test 2048 times. Test will take about 1 second.
# >> _sub is faster than _gsub by 2x ± 0.1

答案 2 :(得分:1)

我会把它变成一种方法......

> "2:30".sub(/(.*):(.*)/, "PT\\1M\\2S")
=> "PT2M30S"