package config import ( "fmt" "time" "gopkg.in/yaml.v3" ) // Duration — time.Duration, который в YAML выглядит как "90s" или "6h", а не // как число наносекунд: конфиг правят руками. type Duration time.Duration // Duration возвращает значение в виде time.Duration. func (d Duration) Duration() time.Duration { return time.Duration(d) } // Seconds возвращает длительность в секундах — удобно для JSON-ответов API. func (d Duration) Seconds() int64 { return int64(time.Duration(d).Seconds()) } // String печатает длительность в том же виде, в каком она пишется в конфиге. func (d Duration) String() string { return time.Duration(d).String() } // MarshalYAML пишет длительность строкой. func (d Duration) MarshalYAML() (any, error) { return time.Duration(d).String(), nil } // UnmarshalYAML принимает и строку ("90s"), и число — число трактуется как // секунды, потому что так его естественнее всего написать руками. func (d *Duration) UnmarshalYAML(node *yaml.Node) error { var asString string if err := node.Decode(&asString); err == nil { parsed, err := time.ParseDuration(asString) if err != nil { return fmt.Errorf("не разобрана длительность %q: %w", asString, err) } *d = Duration(parsed) return nil } var asSeconds int64 if err := node.Decode(&asSeconds); err != nil { return fmt.Errorf("длительность должна быть строкой вида 90s или числом секунд") } *d = Duration(time.Duration(asSeconds) * time.Second) return nil }