无法使用包含时区偏移量的 RFC3339 将字符串解析为时间,并出现看似矛盾的错误
Cannot parse string to time with timezone offset included RFC3339 with seemingly contradictory errors
我正在使用 Golang 和 time.Time 将给定的字符串解析为时间对象。
使用 RFC3339 和 time.Parse
这是我的代码示例:
t, err := time.Parse(time.RFC3339, "2020-08-08T00:22:44Z07:00")
if err != nil {
return nil, err
}
我收到以下错误。
当我包含时区偏移时,我得到:
ERRO[0002] parsing time "2020-08-08T00:22:44Z07:00": extra text: 07:00
当我不包括我得到的时区偏移量时:
ERRO[0002] parsing time "2020-08-08T00:15:36" as "2006-01-02T15:04:05Z07:00": cannot parse "" as "Z07:00"
将时间解析为结构化对象时如何避免此问题?
在 Go time.RFC3339
常量 "2006-01-02T15:04:05Z07:00"
中字符 Z
的存在是否 not 意味着符合模式的日期是应该包括 Z
后跟时区偏移量。
事实上,带有 Z
后跟任何其他内容的日期不是有效的 RFC3339 日期。因此,您的第一个错误 extra text: 07:00
Z
代表“Zulu Time”,即UTC时区。来自 RFC3339 规范:
Z A suffix which, when applied to a time, denotes a UTC
offset of 00:00; often spoken "Zulu" from the ICAO
phonetic alphabet representation of the letter "Z".
所以Z
单独已经提供了时区信息,即UTC。
正如@Flimzy 在评论中指出的那样,2020-08-08T00:22:44Z
将是一个有效的 RFC3339 日期。
t, err := time.Parse(time.RFC3339, "2020-08-08T00:22:44Z")
if err != nil {
panic(err)
}
fmt.Println(t) // 2020-08-08 00:22:44 +0000 UTC
现在,如果您进一步阅读 RFC3339 标准,您会看到以下定义:
time-zone = "Z" / time-numoffset
time-numoffset = ("+" / "-") time-hour [[":"] time-minute]
这意味着日期的时区部分是或者一个Z
或者偏移量。显然,由于 Z
已经表示偏移量 00:00
,因此不能在同一日期字符串中再有一个 +/-HH:mm
偏移量。
但这也意味着 Z
或 +/-HH:mm
必须存在。因此,如果您同时删除它们,则会出现第二个错误:cannot parse "" as "Z07:00"
解析器正在尝试将 "2020-08-08T00:15:36"
字符串读取为 RFC3339,因此它需要 Z
或秒(或毫秒,如果有的话)之后的偏移量。
总而言之,Go time.RFC3339
模式中的 Z07:00
只是表示日期字符串应该包含时区这一事实。有效的 RFC3339 日期字符串必须包含 Z
或偏移量。
我正在使用 Golang 和 time.Time 将给定的字符串解析为时间对象。
使用 RFC3339 和 time.Parse
这是我的代码示例:
t, err := time.Parse(time.RFC3339, "2020-08-08T00:22:44Z07:00")
if err != nil {
return nil, err
}
我收到以下错误。
当我包含时区偏移时,我得到:
ERRO[0002] parsing time "2020-08-08T00:22:44Z07:00": extra text: 07:00
当我不包括我得到的时区偏移量时:
ERRO[0002] parsing time "2020-08-08T00:15:36" as "2006-01-02T15:04:05Z07:00": cannot parse "" as "Z07:00"
将时间解析为结构化对象时如何避免此问题?
在 Go time.RFC3339
常量 "2006-01-02T15:04:05Z07:00"
中字符 Z
的存在是否 not 意味着符合模式的日期是应该包括 Z
后跟时区偏移量。
事实上,带有 Z
后跟任何其他内容的日期不是有效的 RFC3339 日期。因此,您的第一个错误 extra text: 07:00
Z
代表“Zulu Time”,即UTC时区。来自 RFC3339 规范:
Z A suffix which, when applied to a time, denotes a UTC offset of 00:00; often spoken "Zulu" from the ICAO phonetic alphabet representation of the letter "Z".
所以Z
单独已经提供了时区信息,即UTC。
正如@Flimzy 在评论中指出的那样,2020-08-08T00:22:44Z
将是一个有效的 RFC3339 日期。
t, err := time.Parse(time.RFC3339, "2020-08-08T00:22:44Z")
if err != nil {
panic(err)
}
fmt.Println(t) // 2020-08-08 00:22:44 +0000 UTC
现在,如果您进一步阅读 RFC3339 标准,您会看到以下定义:
time-zone = "Z" / time-numoffset time-numoffset = ("+" / "-") time-hour [[":"] time-minute]
这意味着日期的时区部分是或者一个Z
或者偏移量。显然,由于 Z
已经表示偏移量 00:00
,因此不能在同一日期字符串中再有一个 +/-HH:mm
偏移量。
但这也意味着 Z
或 +/-HH:mm
必须存在。因此,如果您同时删除它们,则会出现第二个错误:cannot parse "" as "Z07:00"
解析器正在尝试将 "2020-08-08T00:15:36"
字符串读取为 RFC3339,因此它需要 Z
或秒(或毫秒,如果有的话)之后的偏移量。
总而言之,Go time.RFC3339
模式中的 Z07:00
只是表示日期字符串应该包含时区这一事实。有效的 RFC3339 日期字符串必须包含 Z
或偏移量。