pq: date/time field value out of range: "22/02/2022"

Issue

I have this query:

    l.loyaltycard_number, l.recipt_no, 
    l.totaltrans_amount, l.amount_paid, 
    l.reward_points, l.redeemed_points,
    cashier FROM loyalty l
    JOIN warehouses w
    ON l.machine_ip = w.machine_ip
    WHERE l.machine_name = $1 
    AND redeemed_points != $2
    AND trasaction_time BETWEEN $3 AND  $4
    ORDER BY trasaction_time DESC;

I have HTML datepickers for the transaction_time that is in the format dd/mm/yyyy.

anytime I select a date range that the first number is greater than 12, (22/02/2022).
I get the above error.
I suspected the formatting was the problem.

I found in the docs how to set the postgresql date style to DMY. After doing that, I get the same error.

However, when I run the same query in Postgres cli like so:

SELECT w.machine_name, l.trasaction_time,
        l.loyaltycard_number, l.recipt_no, 
        l.totaltrans_amount, l.amount_paid, 
        l.reward_points, l.redeemed_points,
        cashier FROM loyalty l
        JOIN warehouses w
        ON l.machine_ip = w.machine_ip
        WHERE l.machine_name = 'HERMSERVER'
        AND redeemed_points != 0
        AND trasaction_time BETWEEN '14/11/21' AND  '22/02/22'
        ORDER BY trasaction_time DESC;

I get the expected result. I don’t know what I am doing wrong.
I want to know how I can make the database treat the date from the datepicker as dd/mm/yyyy instead of mm/dd/yyyy. I am using google cloudsql Postgres

This is the code for the handler that gets the data from the datepicker

err := r.ParseForm()

    if err != nil {
        app.clientError(w, http.StatusBadRequest)
    }

    startDate := r.PostForm.Get("startDate")
    endDate := r.PostForm.Get("endDate")
    outlet := r.PostForm.Get("outlet")
    reportType := r.PostForm.Get("repoType")

    if reportType == "0" {
        rReport, err := app.models.Reports.GetRedeemedReport(startDate, endDate, outlet, reportType)
        if err != nil {
            app.serverError(w, err)
            return
        }

        app.render(w, r, "tranxreport.page.tmpl", &templateData{
            Reports: rReport,
        })
    } else if reportType == "1" {
        rReport, err := app.models.Reports.GetAllReport(startDate, endDate, outlet)
        if err != nil {
            app.serverError(w, err)
            return
        }

        app.render(w, r, "tranxreport.page.tmpl", &templateData{
            Reports: rReport,
        })
    } else {
        app.render(w, r, "tranxreport.page.tmpl", &templateData{})
    }

Solution

As per the comments while it should be possible to change DateStyle there are a few issues with this:

  • The SET datestyle command changes the style for the current session. As the SQL package uses connection pooling this is of limited use.
  • You may be able to use "the DateStyle parameter in the postgresql.conf configuration file, or the PGDATESTYLE environment variable on the server" but this may not be available where Postgres is offered as a managed service. Note that making this change also means your software will fail if the parameter is not set (and this is easily done when moving to a new server).

A relatively simple solution is to edit your query to use TO_DATE e.g.:

BETWEEN TO_DATE($3,'DD/MM/YYYY') AND TO_DATE($4,'DD/MM/YYYY')

However while this will work it makes your database code dependent upon the format of the data sent into your API. This means that the introduction of a new date picker, for example, could break your code in a way that is easily missed (testing at the start of the month works either way).

A better solution may be to use a standard format for the date in your API (e.g. ISO 8601) and/or pass the dates to your database functions as a time.Time. However this does require care due to time zones, daylight saving etc.

Answered By – Brits

Answer Checked By – Dawn Plyler (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.