How to parse days/hours/minutes/seconds in ruby?

后端 未结 5 1106
耶瑟儿~
耶瑟儿~ 2021-02-13 20:55

Is there a gem or something to parse strings like \"4h 30m\" \"1d 4h\" -- sort of like the estimates in JIRA or task planners, maybe, with internationalization?

相关标签:
5条回答
  • 2021-02-13 21:36

    Posting a 2nd answer, as chronic (which my original answer suggested) doesn't give you timespans but timestamps.

    Here's my go on a parser.

    class TimeParser
      TOKENS = {
        "m" => (60),
        "h" => (60 * 60),
        "d" => (60 * 60 * 24)
      }
    
      attr_reader :time
    
      def initialize(input)
        @input = input
        @time = 0
        parse
      end
    
      def parse
        @input.scan(/(\d+)(\w)/).each do |amount, measure|
          @time += amount.to_i * TOKENS[measure]
        end
      end
    end
    

    The strategy is fairly simple. Split "5h" into ["5", "h"], define how many seconds "h" represents (TOKENS), and add that amount to @time.

    TimeParser.new("1m").time
    # => 60
    
    TimeParser.new("1m wtf lol").time
    # => 60
    
    TimeParser.new("4h 30m").time
    # => 16200
    
    TimeParser.new("1d 4h").time
    # => 100800
    

    It shouldn't be too hard making it handle "1.5h" either, seeing the codebase is as simple as it is.

    0 讨论(0)
  • 2021-02-13 21:39

    You can use chronic. It can parse pretty much everything you trhow at it, including "yesterday", "last week" etc.

    Update: As the OP points out in the comment, Chronic is for dates, not timespans. See my other answer.

    0 讨论(0)
  • 2021-02-13 21:41

    Parse into what though?

    This will parse into a Hash:

    "4h 30m".split(/\s/).each{|i| h[i.gsub(/\d+/,"")] = i.gsub(/\w/,"")}
    

    Sorry. not familiar with JIRA....

    0 讨论(0)
  • 2021-02-13 21:44

    I wrote this method that does it pretty well

      def parse_duration(dur)
        duration = 0
    
        number_tokens = dur.gsub(/[a-z]/i,"").split
        times = dur.gsub(/[\.0-9]/,"").split
    
        if number_tokens.size != times.size
          raise "unrecognised duration!"
        else
          dur_tokens = number_tokens.zip(times)
    
          for d in dur_tokens
            number_part = d[0].to_f
            time_part = d[1]
    
            case time_part.downcase
            when "h","hour","hours"
              duration += number_part.hours
            when "m","minute","minutes","min","mins"
              duration += number_part.minutes
            when "d","day","days"
              duration += number_part.days
            when "w","week","weeks"
              duration += number_part.weeks
            when "month", "months"
              duration += number_part.months
            when "y", "year", "years"
              duration += number_part.years
            else
              raise "unrecognised duration!"
            end
    
          end
    
        end
    
        duration
      end
    
    0 讨论(0)
  • 2021-02-13 21:48

    chronic_duration does this.

    0 讨论(0)
提交回复
热议问题