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)
| 496 | // format (e.g. '1 day 2 hours', '1 day 03:02:04', etc.) or golang |
| 497 | // format (e.g. '1d2h', '1d3h2m4s', etc.) |
| 498 | func parseDuration(s string, itm types.IntervalTypeMetadata) (duration.Duration, error) { |
| 499 | var d duration.Duration |
| 500 | l := intervalLexer{str: s, offset: 0, err: nil} |
| 501 | l.consumeSpaces() |
| 502 | |
| 503 | if l.offset == len(l.str) { |
| 504 | return d, pgerror.Newf( |
| 505 | pgcode.InvalidDatetimeFormat, "interval: invalid input syntax: %q", l.str) |
| 506 | } |
| 507 | for l.offset != len(l.str) { |
| 508 | // To support -00:XX:XX we record the sign here since -0 doesn't exist |
| 509 | // as an int64. |
| 510 | sign := l.str[l.offset] == '-' |
| 511 | // Parse the next number. |
| 512 | v, hasDecimal, vp := l.consumeNum() |
| 513 | l.consumeSpaces() |
| 514 | |
| 515 | if l.offset < len(l.str) && l.str[l.offset] == ':' && !hasDecimal { |
| 516 | // Special case: HH:MM[:SS.ffff] or MM:SS.ffff |
| 517 | delta, err := l.parseShortDuration(v, sign, itm) |
| 518 | if err != nil { |
| 519 | return d, err |
| 520 | } |
| 521 | d = d.Add(delta) |
| 522 | continue |
| 523 | } |
| 524 | |
| 525 | // Parse the unit. |
| 526 | u := l.consumeUnit(' ') |
| 527 | l.consumeSpaces() |
| 528 | if unit, ok := unitMap[strings.ToLower(u)]; ok { |
| 529 | // A regular number followed by a unit, such as "9 day". |
| 530 | d = d.Add(unit.Mul(v)) |
| 531 | if hasDecimal { |
| 532 | var err error |
| 533 | d, err = addFrac(d, unit, vp) |
| 534 | if err != nil { |
| 535 | return d, err |
| 536 | } |
| 537 | } |
| 538 | continue |
| 539 | } |
| 540 | |
| 541 | if u != "" { |
| 542 | return d, pgerror.Newf( |
| 543 | pgcode.InvalidDatetimeFormat, "interval: unknown unit %q in duration %q", u, s) |
| 544 | } |
| 545 | return d, pgerror.Newf( |
| 546 | pgcode.InvalidDatetimeFormat, "interval: missing unit at position %d: %q", l.offset, s) |
| 547 | } |
| 548 | return d, l.err |
| 549 | } |
| 550 | |
| 551 | func (l *intervalLexer) parseShortDuration( |
| 552 | h int64, hasSign bool, itm types.IntervalTypeMetadata, |
no test coverage detected
searching dependent graphs…