* Input consists of mandatory and optional fields. * Mandatory fields are year, month and day. * Optional fields are time, displacement and zone. * Format is [ hours:minutes:seconds][.millis][ displacement|zone] */
| 701 | * Format is <year-month-day>[ hours:minutes:seconds][.millis][ displacement|zone] |
| 702 | */ |
| 703 | gdv_timestamp castTIMESTAMP_utf8(int64_t context, const char* input, gdv_int32 length) { |
| 704 | using arrow_vendored::date::day; |
| 705 | using arrow_vendored::date::month; |
| 706 | using arrow_vendored::date::sys_days; |
| 707 | using arrow_vendored::date::year; |
| 708 | using arrow_vendored::date::year_month_day; |
| 709 | using gandiva::TimeFields; |
| 710 | using std::chrono::hours; |
| 711 | using std::chrono::milliseconds; |
| 712 | using std::chrono::minutes; |
| 713 | using std::chrono::seconds; |
| 714 | |
| 715 | int ts_fields[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; |
| 716 | gdv_boolean add_displacement = true; |
| 717 | gdv_boolean encountered_zone = false; |
| 718 | int year_str_len = 0, sub_seconds_len = 0; |
| 719 | int ts_field_index = TimeFields::kYear, index = 0, value = 0; |
| 720 | while (ts_field_index < TimeFields::kMax && index < length) { |
| 721 | if (isdigit(input[index])) { |
| 722 | value = (value * 10) + (input[index] - '0'); |
| 723 | if (ts_field_index == TimeFields::kYear) { |
| 724 | year_str_len++; |
| 725 | } |
| 726 | if (ts_field_index == TimeFields::kSubSeconds) { |
| 727 | sub_seconds_len++; |
| 728 | } |
| 729 | } else { |
| 730 | ts_fields[ts_field_index] = value; |
| 731 | value = 0; |
| 732 | |
| 733 | switch (input[index]) { |
| 734 | case '.': |
| 735 | case ':': |
| 736 | case ' ': |
| 737 | ts_field_index++; |
| 738 | break; |
| 739 | case '+': |
| 740 | // +08:00, means time zone is 8 hours ahead. Need to subtract. |
| 741 | add_displacement = false; |
| 742 | ts_field_index = TimeFields::kDisplacementHours; |
| 743 | break; |
| 744 | case '-': |
| 745 | // Overloaded as date separator and negative displacement. |
| 746 | ts_field_index = (ts_field_index < 3) ? (ts_field_index + 1) |
| 747 | : TimeFields::kDisplacementHours; |
| 748 | break; |
| 749 | default: |
| 750 | encountered_zone = true; |
| 751 | break; |
| 752 | } |
| 753 | } |
| 754 | if (encountered_zone) { |
| 755 | break; |
| 756 | } |
| 757 | index++; |
| 758 | } |
| 759 | |
| 760 | // Store the last value |