public static function create($duration): self
    {
        if ($duration instanceof Period) {
            $duration = $duration->getDateInterval();
        }

        if ($duration instanceof DateInterval) {
            $new = new self('PT0S');
            foreach ($duration as $name => $value) {
                if (property_exists($new, $name)) {
                    $new->$name = $value;
                }
            }

            return $new;
        }

        if (false !== ($second = filter_var($duration, FILTER_VALIDATE_INT))) {
            return new self('PT'.$second.'S');
        }

        if (!is_string($duration) && !method_exists($duration, '__toString')) {
            throw new TypeError(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, gettype($duration)));
        }

        $duration = (string) $duration;
        if (1 !== preg_match(self::REGEXP_CHRONO_FORMAT, $duration, $matches)) {
            $new = self::createFromDateString($duration);
            if ($new !== false) {
                return $new;
            }

            throw new Exception(sprintf('Unknown or bad format (%s)', $duration));
        }

        $matches['fraction'] = str_pad($matches['fraction'] ?? '0000000', 6, '0');
        $expression = $matches['hour'].' hours '.
            $matches['minute'].' minutes '.
            $matches['second'].' seconds '.$matches['fraction'].' microseconds';

        $instance = self::createFromDateString($expression);
        if (false === $instance) {
            throw new Exception(sprintf('Unknown or bad format (%s)', $expression));
        }

        if ('-' === $matches['sign']) {
            $instance->invert = 1;
        }

        return $instance;
    }