Skip to content

YAML Time Duration Support in Go

Last time, when one of users asked me "could I set up a 100d in his yaml file for Go time.Duration", my first action is why he cannot search the documentation by himself. But then, another problem overwhelmed my mind because actually I'm not sure about it. I don't know it as well.

After seeing the source code, I got the answer. However, the important inspiration here is: "how to make knowledge cohesive", hence the blog comes. In short, you should understand several concepts here:

  • whether the time duration is a standard specification?
  • does Go implementation allow to parse a string into different type?
  • how could it parse?

By enquiring these questions progressively, you can easily recognize how yaml works in a cohesive way instead of remembering some scattered knowledge about it.

YAML Doesn't Support Time Duration

Checked with YAML overview part in specification, we will soon find YAML doesn't have a concept of time duration, although time is supported. Hence, we soon knows that allowing yaml to set up time duration is a new added feature.

Go YAML Implementation Supports it Additionally

Go YAML hasn't mentioned anything about the time.Duration, so probably we need to see the source code. Then, we can find out yaml parses string to time.Duration:
additionally.

    case string:
        if out.Type() == durationType {
            d, err := time.ParseDuration(resolved)
            if err == nil {
                out.SetInt(int64(d))
                return true
            }
        }
    }

One thing to highlight is yaml2 used to support numbers as time.Duration, but yaml3 abandons such supports because it's very unfriendly.

    case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
        // This used to work in v2, but it's very unfriendly.
        isDuration := out.Type() == durationType

How YAML Parses the Time Duration

If YAML specification marks the time span, of course YAML needs to parse the time by itself. However, when it comes to an additional support, the YAML will reuse the Go standard library to parse the string for a time duration. That's the function time.ParseDuration:

ParseDuration parses a duration string. A duration string is a possibly signed sequence of decimal numbers, each with optional fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m". Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

Conclusion: How to Make Knowledge Cohesive

In this question, actually the traces are very clear, as long as we know what the yaml specification is, and how YAML parses for the time duration. Then, you can quickly recognize the knowledge in a cohesive way. It means even though you forget the whole details in the future, it's still possible for you to quickly pick up the idea "yaml specification doesn't mark this, and I can check the go standard time library".

Logically reasoning makes the behaviors more predictable, rather than memorizing it as boring and dummy knowledge.