parseInsightsStartAndEndTime parses the start and end time query parameters and returns the parsed values. The client provided timezone must be preserved when parsing the time. Verification is performed so that the start and end time are not zero and that the end time is not before the start time. T
(ctx context.Context, rw http.ResponseWriter, now time.Time, startTimeString, endTimeString string)
| 656 | // clock must be set to 00:00:00, except for "today", where end time is allowed |
| 657 | // to provide the hour of the day (e.g. 14:00:00). |
| 658 | func parseInsightsStartAndEndTime(ctx context.Context, rw http.ResponseWriter, now time.Time, startTimeString, endTimeString string) (startTime, endTime time.Time, ok bool) { |
| 659 | for _, qp := range []struct { |
| 660 | name, value string |
| 661 | dest *time.Time |
| 662 | }{ |
| 663 | {"start_time", startTimeString, &startTime}, |
| 664 | {"end_time", endTimeString, &endTime}, |
| 665 | } { |
| 666 | t, err := time.Parse(insightsTimeLayout, qp.value) |
| 667 | if err != nil { |
| 668 | httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 669 | Message: "Query parameter has invalid value.", |
| 670 | Validations: []codersdk.ValidationError{ |
| 671 | { |
| 672 | Field: qp.name, |
| 673 | Detail: fmt.Sprintf("Query param %q must be a valid date format (%s): %s", qp.name, insightsTimeLayout, err.Error()), |
| 674 | }, |
| 675 | }, |
| 676 | }) |
| 677 | return time.Time{}, time.Time{}, false |
| 678 | } |
| 679 | |
| 680 | // Change now to the same timezone as the parsed time. |
| 681 | now := now.In(t.Location()) |
| 682 | |
| 683 | if t.IsZero() { |
| 684 | httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 685 | Message: "Query parameter has invalid value.", |
| 686 | Validations: []codersdk.ValidationError{ |
| 687 | { |
| 688 | Field: qp.name, |
| 689 | Detail: fmt.Sprintf("Query param %q must not be zero", qp.name), |
| 690 | }, |
| 691 | }, |
| 692 | }) |
| 693 | return time.Time{}, time.Time{}, false |
| 694 | } |
| 695 | |
| 696 | // Round upwards one hour to ensure we can fetch the latest data. |
| 697 | if t.After(now.Truncate(time.Hour).Add(time.Hour)) { |
| 698 | httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 699 | Message: "Query parameter has invalid value.", |
| 700 | Validations: []codersdk.ValidationError{ |
| 701 | { |
| 702 | Field: qp.name, |
| 703 | Detail: fmt.Sprintf("Query param %q must not be in the future", qp.name), |
| 704 | }, |
| 705 | }, |
| 706 | }) |
| 707 | return time.Time{}, time.Time{}, false |
| 708 | } |
| 709 | |
| 710 | ensureZeroHour := true |
| 711 | if qp.name == "end_time" { |
| 712 | ey, em, ed := t.Date() |
| 713 | ty, tm, td := now.Date() |
| 714 | |
| 715 | ensureZeroHour = ey != ty || em != tm || ed != td |