parseDuration parses a duration in the "traditional" Postgres format (e.g. '1 day 2 hours', '1 day 03:02:04', etc.) or golang format (e.g. '1d2h', '1d3h2m4s', etc.)
(s string, itm types.IntervalTypeMetadata)
| 519 | // format (e.g. '1 day 2 hours', '1 day 03:02:04', etc.) or golang |
| 520 | // format (e.g. '1d2h', '1d3h2m4s', etc.) |
| 521 | func parseDuration(s string, itm types.IntervalTypeMetadata) (duration.Duration, error) { |
| 522 | var d duration.Duration |
| 523 | l := intervalLexer{str: s, offset: 0, err: nil} |
| 524 | l.consumeSpaces() |
| 525 | l.consumeAts() // remove all @ characters |
| 526 | l.consumeSpaces() // remove spaces that come after @s |
| 527 | |
| 528 | if l.offset == len(l.str) { |
| 529 | return d, pgerror.Newf( |
| 530 | pgcode.InvalidDatetimeFormat, "interval: invalid input syntax: %q", l.str) |
| 531 | } |
| 532 | for l.offset != len(l.str) { |
| 533 | // To support -00:XX:XX we record the sign here since -0 doesn't exist |
| 534 | // as an int64. |
| 535 | sign := l.str[l.offset] == '-' |
| 536 | // Parse the next number. |
| 537 | v, hasDecimal, vp := l.consumeNum() |
| 538 | l.consumeSpaces() |
| 539 | |
| 540 | if l.offset < len(l.str) && l.str[l.offset] == ':' && !hasDecimal { |
| 541 | // Special case: HH:MM[:SS.ffff] or MM:SS.ffff |
| 542 | delta, err := l.parseShortDuration(v, sign, itm) |
| 543 | if err != nil { |
| 544 | return d, err |
| 545 | } |
| 546 | d = d.Add(delta) |
| 547 | continue |
| 548 | } |
| 549 | |
| 550 | // Parse the unit. |
| 551 | u := l.consumeUnit(' ') |
| 552 | l.consumeSpaces() |
| 553 | if unit, ok := unitMap[strings.ToLower(u)]; ok { |
| 554 | // A regular number followed by a unit, such as "9 day". |
| 555 | d = d.Add(unit.Mul(v)) |
| 556 | if hasDecimal { |
| 557 | d = addFrac(d, unit, vp) |
| 558 | } |
| 559 | continue |
| 560 | } |
| 561 | |
| 562 | if u != "" { |
| 563 | return d, pgerror.Newf( |
| 564 | pgcode.InvalidDatetimeFormat, "interval: unknown unit %q in duration %q", u, s) |
| 565 | } |
| 566 | return d, pgerror.Newf( |
| 567 | pgcode.InvalidDatetimeFormat, "interval: missing unit at position %d: %q", l.offset, s) |
| 568 | } |
| 569 | return d, l.err |
| 570 | } |
| 571 | |
| 572 | func (l *intervalLexer) parseShortDuration( |
| 573 | h int64, hasSign bool, itm types.IntervalTypeMetadata, |
no test coverage detected