| 574 | } |
| 575 | |
| 576 | static int match_multi_number(timestamp_t num, char c, const char *date, |
| 577 | char *end, struct tm *tm, time_t now) |
| 578 | { |
| 579 | struct tm now_tm; |
| 580 | struct tm *refuse_future; |
| 581 | long num2, num3; |
| 582 | |
| 583 | num2 = strtol(end+1, &end, 10); |
| 584 | num3 = -1; |
| 585 | if (*end == c && isdigit(end[1])) |
| 586 | num3 = strtol(end+1, &end, 10); |
| 587 | |
| 588 | /* Time? Date? */ |
| 589 | switch (c) { |
| 590 | case ':': |
| 591 | if (num3 < 0) |
| 592 | num3 = 0; |
| 593 | if (set_time(num, num2, num3, tm) == 0) { |
| 594 | /* |
| 595 | * If %H:%M:%S was just parsed followed by: .<num4> |
| 596 | * Consider (& discard) it as fractional second |
| 597 | * if %Y%m%d is parsed before. |
| 598 | */ |
| 599 | if (*end == '.' && isdigit(end[1]) && is_date_known(tm)) |
| 600 | strtol(end + 1, &end, 10); |
| 601 | break; |
| 602 | } |
| 603 | return 0; |
| 604 | |
| 605 | case '-': |
| 606 | case '/': |
| 607 | case '.': |
| 608 | if (!now) |
| 609 | now = time(NULL); |
| 610 | refuse_future = NULL; |
| 611 | if (gmtime_r(&now, &now_tm)) |
| 612 | refuse_future = &now_tm; |
| 613 | |
| 614 | if (num > 70) { |
| 615 | /* yyyy-mm-dd? */ |
| 616 | if (set_date(num, num2, num3, NULL, now, tm) == 0) |
| 617 | break; |
| 618 | /* yyyy-dd-mm? */ |
| 619 | if (set_date(num, num3, num2, NULL, now, tm) == 0) |
| 620 | break; |
| 621 | } |
| 622 | /* Our eastern European friends say dd.mm.yy[yy] |
| 623 | * is the norm there, so giving precedence to |
| 624 | * mm/dd/yy[yy] form only when separator is not '.' |
| 625 | */ |
| 626 | if (c != '.' && |
| 627 | set_date(num3, num, num2, refuse_future, now, tm) == 0) |
| 628 | break; |
| 629 | /* European dd.mm.yy[yy] or funny US dd/mm/yy[yy] */ |
| 630 | if (set_date(num3, num2, num, refuse_future, now, tm) == 0) |
| 631 | break; |
| 632 | /* Funny European mm.dd.yy */ |
| 633 | if (c == '.' && |
no test coverage detected