英文:
Parsing Date in Go
问题
我正在使用Go编写一个服务,该服务接受作为HTTP请求参数传递的时间戳并进行解析。
一个示例调用是 GET /values?from=2015-02-11T15:01:00+00:00
。
传递给函数的值的示例是 2015-02-11T15:01:00+00:00
。
我尝试这样解析它:
dateTime := request.URL.Query.Get("from")
layout := "2006-01-02T15:04:05Z07:00"
formattedTime, _ := time.Parse(layout, dateTime)
(我使用Go的布局数字来完成这个操作-更多信息请参见:https://golang.org/pkg/time/#pkg-constants)
然而,这个输出是 0001-01-01 00:00:00 +0000 UTC
。
我还应该指出,当我执行 fmt.Println(dateTime)
时,我得到的是 2015-02-11T15:01:00 00:00
(而不是我期望的 2015-02-11T15:01:00+00:00
)。
此外,当我在函数中硬编码一个日期时间并使用 time.Parse(layout, dateTime)
进行解析时,它成功解析并给出输出 2015-02-11 15:01:00 +000 GMT
。
有人知道这里可能发生了什么吗?
谢谢,
Sean
英文:
I am writing a service in Go that takes a timetstamp passed in as a HTTP request parameter and parses it.
A sample call is GET /values?from=2015-02-11T15:01:00+00:00
An example of he value that is being passed into the function is 2015-02-11T15:01:00+00:00
.
I am trying to parse it thus:
dateTime := request.URL.Query.Get("from")
layout := "2006-01-02T15:04:05Z07:00"
formattedTime, _ := time.Parse(layout, dateTime)
(I am using Go's layout numbers to to do this - more information here: https://golang.org/pkg/time/#pkg-constants)
However, the output from this is 0001-01-01 00:00:00 +0000 UTC
.
I should also point out that when I do a fmt.Println(dateTime)
, I get 2015-02-11T15:01:00 00:00
(not 2015-02-11T15:01:00+00:00
as I might expect).
Also, when I hardcode a datetime into the function and parse it using time.Parse(layout, dateTime), it is parsed successfully and gives the output 2015-02-11 15:01:00 +000 GMT
.
Does anyone know what might be happening here?
Thanks,
Sean
答案1
得分: 1
你应该检查返回的错误。time.Parse()
返回一个错误:
formattedTime, err := time.Parse(layout, dateTime)
if err != nil {
fmt.Println(err)
}
你的错误可能出现在 URL 查询中的 +
字符上。URL 查询使用 URL 编码,其中 +
符号是特殊的:它用于编码空格字符。所以当你这样做时:
dateTime := request.URL.Query.Get("from")
你的 dateTime
将包含解码后的值,其中 +
将被替换为空格。可以像这样检查它:
fmt.Printf("%q\n", dateTime)
输出:
"2015-02-11T15:01:00 00:00"
当然,这不是你指定的布局的有效格式,这将导致以下错误:
将时间 "2015-02-11T15:01:00 00:00" 解析为 "2006-01-02T15:04:05Z07:00" 格式时出错:无法将 "" 解析为 "Z07:00"
你必须在 URL 查询中使用 %2B
,它是 +
符号的编码,并且还必须包含你在布局中使用的 Z
字符:
GET /values?from=2015-02-11T15:01:00Z%2B00:00
还要注意,布局必须包含 -07:00
的参考时区,而不是 07:00
:
layout := "2006-01-02T15:04:05Z-07:00"
然后输出 (formattedTime
):
2015-02-11 15:01:00 +0000 UTC
在 Go Playground 上尝试一下:
如果你必须在查询中使用 +
...
如果你必须在查询中使用 +
(如你在评论中所说),那么使用未转义的值将会很棘手,因为如果查询中的时区是 +
,它会被替换为空格,但如果时区是 -
,则不会被替换!
一种方法是使用原始查询而不是解码后的查询。这在 URL.RawQuery
中可用。
这是一个解决方案,假设只有一个请求参数:"from="
。如果有其他参数,它会失败,请注意这一点:
param := "from="
layout := "2006-01-02T15:04:05-07:00"
length := len(param) + len(layout)
if s := request.URL.RawQuery; len(s) < length || !strings.HasPrefix(s, param) {
// 非预期的查询
}
dateTime := request.URL.RawQuery[len(param):length]
formattedTime, err := time.Parse(layout, dateTime)
if err != nil {
// 处理错误
}
英文:
You should check returned errors. time.Parse()
returns an error:
formattedTime, err := time.Parse(layout, dateTime)
if err != nil {
fmt.Println(err)
}
Your error will lie in the '+'
character in the URL query. The URL query uses URL encoding where the +
sign is special: it is used to encode the space character. So when you do this:
dateTime := request.URL.Query.Get("from")
Your dateTime
will contain the decoded value where +
will be replaced by a space. Check it like:
fmt.Printf("%q\n", dateTime)
Output:
"2015-02-11T15:01:00 00:00"
And of course this is not a valid format for the layout you specified, which will give you the following error:
> parsing time "2015-02-11T15:01:00 00:00" as "2006-01-02T15:04:05Z07:00": cannot parse "" as "Z07:00"
You have to use %2B
in the URL query which is the code for the +
sign, and you also have to include the Z
char which you used in your layout:
GET /values?from=2015-02-11T15:01:00Z%2B00:00
And also note that the layout has to contain the -07:00
reference time zone and not 07:00
:
layout := "2006-01-02T15:04:05Z-07:00"
Then the output (formattedTime
):
2015-02-11 15:01:00 +0000 UTC
Try it on the Go Playground:
If you must use +
in the query...
If you must use the +
query (as you claim in the comment), then working with the unescaped value would be tricky, as if time zone in query is +
, it is replaced with space, but if the time zone is -
, it is not!
One way is to work with the Raw query and not the decoded one. This is available in URL.RawQuery
.
Here's a solution which assumes there is only 1 request parameter: "from="
. It fails if there are other, please take that into account:
param := "from="
layout := "2006-01-02T15:04:05-07:00"
length := len(param) + len(layout)
if s := request.URL.RawQuery; len(s) < length || !strings.HasPrefix(s, param) {
// unexpected query
}
dateTime := request.URL.RawQuery[len(param):length]
formattedTime, err := time.Parse(layout, dateTime)
if err != nil {
// handle error
}
答案2
得分: -1
你需要在时区偏移之前使用减号,所以布局应该是:"2006-01-02T15:04:05-07:00"
https://golang.org/pkg/time/#pkg-constants:
数值型的时区偏移格式如下:
-0700 ±hhmm
-07:00 ±hh:mm
-07 ±hh
示例:http://play.golang.org/p/ZG979Meuxz
当你打印它时,它使用的是默认格式,而不是你用来解析它的格式,因为它调用了String方法:https://golang.org/pkg/time/#Time.String
要使用自定义格式进行格式化,请使用Format:https://golang.org/pkg/time/#Time.Format
英文:
You need to use a minus before the time zone offset, so the layout should be: "2006-01-02T15:04:05-07:00"
https://golang.org/pkg/time/#pkg-constants:
Numeric time zone offsets format as follows:
-0700 ±hhmm
-07:00 ±hh:mm
-07 ±hh
example: http://play.golang.org/p/ZG979Meuxz
When you print it out, it uses the default format, not the one you used to parse it, because it calls the String method: https://golang.org/pkg/time/#Time.String
To format it using a custom format, use Format: https://golang.org/pkg/time/#Time.Format
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论