在Go语言中解析日期

huangapple go评论180阅读模式
英文:

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 &#39;+&#39; 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(&quot;from&quot;)

Your dateTime will contain the decoded value where + will be replaced by a space. Check it like:

fmt.Printf(&quot;%q\n&quot;, dateTime)

Output:

&quot;2015-02-11T15:01:00 00:00&quot;

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 := &quot;2006-01-02T15:04:05Z-07:00&quot;

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: &quot;from=&quot;. It fails if there are other, please take that into account:

param := &quot;from=&quot;
layout := &quot;2006-01-02T15:04:05-07:00&quot;
length := len(param) + len(layout)

if s := request.URL.RawQuery; len(s) &lt; 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  &#177;hhmm
-07:00 &#177;hh:mm
-07    &#177;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

huangapple
  • 本文由 发表于 2016年3月21日 17:28:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/36127217.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定