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.)
( style IntervalStyle, 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( |
| 499 | style IntervalStyle, s string, itm types.IntervalTypeMetadata, |
| 500 | ) (Duration, error) { |
| 501 | var d Duration |
| 502 | l := intervalLexer{str: s, offset: 0, err: nil} |
| 503 | l.consumeSpaces() |
| 504 | |
| 505 | if l.offset == len(l.str) { |
| 506 | return d, pgerror.Newf( |
| 507 | pgcode.InvalidDatetimeFormat, "interval: invalid input syntax: %q", l.str) |
| 508 | } |
| 509 | |
| 510 | // If we have strictly one negative at the beginning belonging to a |
| 511 | // in SQL Standard parsing, treat everything as negative. |
| 512 | isSQLStandardNegative := |
| 513 | style == IntervalStyle_SQL_STANDARD && |
| 514 | (l.offset+1) < len(l.str) && l.str[l.offset] == '-' && |
| 515 | !strings.ContainsAny(l.str[l.offset+1:], "+-") |
| 516 | if isSQLStandardNegative { |
| 517 | l.offset++ |
| 518 | } |
| 519 | |
| 520 | for l.offset != len(l.str) { |
| 521 | // To support -00:XX:XX we record the sign here since -0 doesn't exist |
| 522 | // as an int64. |
| 523 | sign := l.str[l.offset] == '-' |
| 524 | // Parse the next number. |
| 525 | v, hasDecimal, vp := l.consumeNum() |
| 526 | l.consumeSpaces() |
| 527 | |
| 528 | if l.offset < len(l.str) && l.str[l.offset] == ':' && !hasDecimal { |
| 529 | // Special case: HH:MM[:SS.ffff] or MM:SS.ffff |
| 530 | delta, err := l.parseShortDuration(v, sign, itm) |
| 531 | if err != nil { |
| 532 | return d, err |
| 533 | } |
| 534 | d = d.Add(delta) |
| 535 | continue |
| 536 | } |
| 537 | |
| 538 | // Parse the unit. |
| 539 | u := l.consumeUnit(' ') |
| 540 | l.consumeSpaces() |
| 541 | if unit, ok := unitMap[strings.ToLower(u)]; ok { |
| 542 | // A regular number followed by a unit, such as "9 day". |
| 543 | d = d.Add(unit.Mul(v)) |
| 544 | if hasDecimal { |
| 545 | var err error |
| 546 | d, err = addFrac(d, unit, vp) |
| 547 | if err != nil { |
| 548 | return d, err |
| 549 | } |
| 550 | } |
| 551 | continue |
| 552 | } |
| 553 | |
| 554 | if l.err != nil { |
| 555 | return d, l.err |
no test coverage detected
searching dependent graphs…