# Parse different time duration formats/units to common format

**URL:** <https://discuss.elastic.co/t/parse-different-time-duration-formats-units-to-common-format/321742>\
**Category:** Logstash\
**Created:** [December 21, 2022, 9:24am UTC](https://discuss.elastic.co/t/parse-different-time-duration-formats-units-to-common-format/321742 "2022-12-21T09:24:10Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![wespe](https://avatars.discourse-cdn.com/v4/letter/w/a6a055/32.png) [@wespe](https://discuss.elastic.co/u/wespe)\
**Post date:** [December 21, 2022, 9:24am UTC](https://discuss.elastic.co/t/parse-different-time-duration-formats-units-to-common-format/321742/1 "2022-12-21T09:24:10Z")

</div>

Hi there,

Part of my input json looks as follows:

> ```
> "phaseTimes": {
> "authorize": "28.201µs",
> "filter": "27.522068ms",
> "indexScan": "2.004642056s",
> "instantiate": "40.002µs",
> "run": "2.041368619s"
> }
> 
> ```

Note the different units, which might be seconds (s), milliseconds (ms), microseconds (µs), and, potentially, minutes (m).

How would I be able to parse these and get them into some common format, say basic milliseconds or microseconds -- without any unit.

So my expected output is something like this (here, formatted to milliseconds):

> ```
> "phaseTimes": {
> "authorize": 0.028201,
> "filter": 27.522068,
> "indexScan": 2004.642056,
> "instantiate": 0.040002,
> "run": 2041.368619
> }
> 
> ```

---

<div class="post-metadata">

**Author:** ![sai\_saran1](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/sai_saran1/32/116661_2.png) [@sai\_saran1](https://discuss.elastic.co/u/sai_saran1)\
**Post date:** [December 21, 2022, 1:02pm UTC](https://discuss.elastic.co/t/parse-different-time-duration-formats-units-to-common-format/321742/2 "2022-12-21T13:02:46Z")

</div>

You can use a ruby filter to change all values to requested format, after assigning it to a field, Try this below filter for authorize field as example

```auto
ruby {
code => "event[authorize'] = ((event['authorize][0..-2] ).to_i /1000)"
}

```

---

<div class="post-metadata">

**Author:** ![leandrojmp](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/leandrojmp/32/107231_2.png) [@leandrojmp](https://discuss.elastic.co/u/leandrojmp)\
**Post date:** [December 21, 2022, 2:07pm UTC](https://discuss.elastic.co/t/parse-different-time-duration-formats-units-to-common-format/321742/3 "2022-12-21T14:07:48Z")

</div>

The best way will be to use a ruby filter with some code to convert the data.

Those the unites can change on a document basis? For example, the `phaseTimes.authorize` will always be in micro seconds or it can be in miliseconds or seconds as well?

If so, you will need to check the unit in your ruby code to convert it correctly.

---

<div class="post-metadata">

**Author:** ![Badger](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/badger/32/25190_2.png) [@Badger](https://discuss.elastic.co/u/Badger)\
**Post date:** [December 21, 2022, 6:59pm UTC](https://discuss.elastic.co/t/parse-different-time-duration-formats-units-to-common-format/321742/4 "2022-12-21T18:59:19Z")

</div>

> [@wespe](#):
>
> How would I be able to parse these and get them into some common format, say basic milliseconds or microseconds -- without any unit.

Try

```
    ruby {
        init => '
            Factors = {
                "m" => 60000.0,
                "s" => 1000.0,
                "ms" => 1,
                "µs" => 0.001
            }
        '
        code => '
            times = event.get("phaseTimes")
            if times.is_a? Hash
                times.each { |k, v|
                    suffix = /[[:alpha:]]+$/.match(v).to_s
                    factor = Factors[suffix]
                    if factor
                        times[k] = factor * v.to_f
                    end
                }
                event.set("phaseTimes", times)
            end
        '
    }

```

which produces

```
"phaseTimes" => {
      "indexScan" => 2004.6420559999997,
            "run" => 2041.368619,
         "filter" => 27.522068,
      "authorize" => 0.028201,
    "instantiate" => 0.040002
},

```

.to\_f ignores the alpha suffix, so you do not need to split the v into digits and suffix using the regexp, although stylistically that might be better.

---

<div class="post-metadata">

**Author:** ![wespe](https://avatars.discourse-cdn.com/v4/letter/w/a6a055/32.png) [@wespe](https://discuss.elastic.co/u/wespe)\
**Post date:** [December 22, 2022, 7:49am UTC](https://discuss.elastic.co/t/parse-different-time-duration-formats-units-to-common-format/321742/5 "2022-12-22T07:49:27Z")

</div>

Wow, this is brilliant, thanks all for taking me in the right direction and for the code @Badger .

I ended up coding the following, but your solutions seems more elegant.

```auto
def str_to_ms(val)

  if val.end_with?("ms") then
    return val[0..-3].to_f
  elsif val.end_with?("µs") then
    return val[0..-3].to_f / 1000
  elsif val.end_with?("s") then
    return val[0..-2].to_f * 1000
  elsif val.end_with?("m") then
    return val[0..-2].to_f * 1000 * 60
  elsif val.end_with?("h") then
    return val[0..-2].to_f * 1000 * 60 * 60
  end

end

def filter(event)

  fields = ["authorize", "filter", "indexScan", "instantiate", "run"]
  fields.each do |key|

    val = event.get(key)

    if !val.nil? then
      event.set(key, str_to_ms(val))
    end

  end

  return [event]
end

```

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [January 19, 2023, 7:50am UTC](https://discuss.elastic.co/t/parse-different-time-duration-formats-units-to-common-format/321742/6 "2023-01-19T07:50:28Z")

</div>

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.
