英文:
pq: date/time field value out of range: "22/02/2022"
问题
我有这个查询:
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;
我有一个 HTML 日期选择器,用于格式为 dd/mm/yyyy 的 transaction_time。
每当我选择一个日期范围,第一个数字大于12时(例如 22/02/2022),我就会得到上述错误。我怀疑格式化是问题所在。
我在文档中找到了如何将 PostgreSQL 的日期样式设置为 DMY。在这样做之后,我仍然得到相同的错误。
然而,当我在 Postgres cli 中运行相同的查询,如下所示:
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;
我得到了预期的结果。我不知道我做错了什么。
我想知道如何让数据库将日期选择器中的日期视为 dd/mm/yyyy 而不是 mm/dd/yyyy。我正在使用 Google CloudSQL Postgres。
这是从日期选择器获取数据的处理程序的代码:
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{})
}
英文:
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{})
}
答案1
得分: 5
根据评论,虽然可以更改DateStyle
,但存在一些问题:
SET datestyle
命令只会更改当前会话的样式,而SQL
包使用连接池,因此其作用有限。- 你可以尝试在postgresql.conf配置文件中使用DateStyle参数,或者在服务器上使用PGDATESTYLE环境变量,但在Postgres作为托管服务提供时可能无法使用。请注意,更改这个设置也意味着如果参数未设置(在切换到新服务器时很容易发生),你的软件将会失败。
一个相对简单的解决方案是编辑查询以使用TO_DATE
,例如:
BETWEEN TO_DATE($3,'DD/MM/YYYY') AND TO_DATE($4,'DD/MM/YYYY')
然而,尽管这样可以工作,但它使得你的数据库代码依赖于发送到API的数据格式。这意味着引入一个新的日期选择器,例如,可能会以一种很容易被忽视的方式破坏你的代码(在月初进行测试都可以正常工作)。
一个更好的解决方案可能是在API中使用标准日期格式(例如ISO 8601),和/或将日期作为time.Time
传递给数据库函数。然而,由于时区、夏令时等问题,这需要小心处理。
英文:
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 theSQL
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论