英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论