【问题标题】:Ruby (with Rails) convert a string of time into seconds?Ruby(使用Rails)将一串时间转换为秒?
【发布时间】:2011-06-05 03:55:40
【问题描述】:

所以,我有一串时间......类似于

'4 hours'
'48 hours'
'3 days'
'15 minutes'

我想将这些都转换为秒。对于'4 hours',这工作正常

Time.parse('4 hours').to_i - Time.parse('0 hours').to_i
=> 14400 # 4 hours in seconds, yay

但是,这在 48 小时内不起作用(超出范围错误)。 3天也不行(无信息错误)等

有没有简单的方法可以将这些字符串转换成秒数?


【问题讨论】:

    标签: ruby-on-rails ruby datetime date time


    【解决方案1】:

    我相信你会从chronic gem 中得到一些好的结果。

    另外,这里有一些good to know info about dates/times in ruby

    【讨论】:

      【解决方案2】:

      您要求 Ruby 使用 Time.parse 来确定一天中的某个时间。那不是你想要的。我能想到的所有库在这方面都是相似的:它们对绝对时间感兴趣,而不是时间长度。

      要将您的字符串转换为我们可以使用的时间格式,我建议使用 Chronic (gem install chronic)。要转换为秒,我们可以做所有与当前时间相关的事情,然后根据需要减去该时间以获得绝对秒数。

      def seconds_in(time)
          now = Time.now
          Chronic.parse("#{time} from now", :now => now) - now
      end
      
      seconds_in '48 hours'   # => 172,800.0
      seconds_in '15 minutes' # => 900.0
      seconds_in 'a lifetime' # NoMethodError, not 42 ;)
      

      几个小笔记:

      • from now 是需要 Chronic 的原因 - 它处理自然语言输入。
      • 我们指定now 是为了避免出现 Time.now 从 Chronic 执行它的魔法到我们从结果中减去它的时间发生变化的情况。它可能永远不会发生,但我认为这里比抱歉更安全。

      【讨论】:

      【解决方案3】:
      4.hours => 14400 seconds
      4.hours.to_i 14400
      4.hours - 0.hours => 14400 seconds 
      
      def string_to_seconds string
        string.split(' ')[0].to_i.send(string.split(' ')[1]).to_i
      end
      

      只有在时间格式为 number[space]hour(s)/minute(s)/second(s) 时,此辅助方法才有效

      【讨论】:

      • 你是从一个 Fixnum 开始的,但我认为他是从用户输入的字符串开始的。
      • 是的,老实说,我只是注意到了这一点,并且之前略读过。话虽如此,在我看来,如果时间字符串始终采用所描述的一致格式,那么为什么不解析字符串并使用 rails datetime helpers。
      【解决方案4】:
      '48 hours'.match(/^(\d+) (minutes|hours|days)$/) ? $1.to_i.send($2) : 'Unknown'
       => 172800 seconds
      

      【讨论】:

      • 这将在以下情况下失败:“一天”、“一天”、“1 周”、“1 个月”、“48 小时”等。这是 def solve_complex_problem; return 'answer'; end 的升级版。
      • 是的,但是通过了问题中的示例。第二句没看懂。
      • 曾经参加过一门编程课程,书中告诉您需要编写一个以某种方式响应的应用程序?关键是,与其编写它以逐字地响应示例,不如推断它应该执行什么功能并这样编写它。
      • 这更有意义。即使您知道这些功能不会被使用,您会在您的第一条评论中添加这些功能吗?假设问题是关于用户输入的只是猜测。
      【解决方案5】:
      >> strings = ['4 hours', '48 hours', '3 days', '15 minutes', '2 months', '5 years', '2 decades']
      => ["4 hours", "48 hours", "3 days", "15 minutes", "2 months", "5 years", "2 decades"]
      >> ints = strings.collect{|s| eval "#{s.gsub(/\s+/,".")}.to_i" rescue "Error"}
      => [14400, 172800, 259200, 900, 5184000, 157788000, "Error"]
      

      【讨论】:

      • 这很棘手,但在用户输入中使用eval 非常危险。如果您使用正则表达式来验证输入是否只是您所期望的(例如/\d+\s+(?:minutes|hours|days|...)/),那么这不会太糟糕。也许更好地解析它并使用.to_i.send(duration_string)
      • 我明白你在说什么,它很容易受到注入攻击,最好事先进行正则表达式检查。
      【解决方案6】:

      Chronic 会起作用,但 Chronic Duration 更合适。 它可以解析一个字符串并给你几秒钟的时间。

      require "chronic_duration"
      ChronicDuration::parse('15 minutes')
      # or 
      ChronicDuration::parse('4 hours') 
      

      http://everydayrails.com/2010/08/11/ruby-date-time-parsing-chronic.html

      【讨论】:

        猜你喜欢
        • 2011-04-27
        • 2011-04-18
        • 2018-03-15
        • 2011-07-04
        • 1970-01-01
        • 1970-01-01
        • 2017-09-08
        • 2013-02-17
        • 2011-08-28
        相关资源
        最近更新 更多