如何在Go中表示RFC-3339`-00:00`偏移量?

如何在Go中表示RFC-3339`-00:00`偏移量?,go,time,Go,Time,RFC-3339第4.3节()将-00:00偏移定义为以下内容,这与Z或+00:00不同 4.3. Unknown Local Offset Convention If the time in UTC is known, but the offset to local time is unknown, this can be represented with an offset of "-00:00". This differs semantically from an o

RFC-3339第4.3节()将
-00:00
偏移定义为以下内容,这与
Z
+00:00
不同

4.3. Unknown Local Offset Convention

   If the time in UTC is known, but the offset to local time is unknown,
   this can be represented with an offset of "-00:00".  This differs
   semantically from an offset of "Z" or "+00:00", which imply that UTC
   is the preferred reference point for the specified time.  RFC2822
   [IMAIL-UPDATE] describes a similar convention for email.
但是,我不确定如何在Go中表示这一点。当我用
-00:00
解析一个时间并格式化它时,我得到一个
Z
偏移量。例如:

  • 输入:
    2018-01-01T00:00:00-00:00
  • 输出:
    2018-01-01T00:00:00Z
下面是一些示例代码():

RFC3339、RFC822、RFC822Z、RFC1123和RFC1123Z可用于 格式;当与时间一起使用时。解析它们并不总是接受 RFC允许的格式


Go不接受RFCs允许的所有时间格式

Go
time.time
类型使用整数,与浮点不同,整数没有正负零的概念。分析
-00:00
+00:00
偏移量的结果是相同的

比如说,

package main

import (
    "fmt"
    "time"
)

func main() {
    var err error
    var minus, plus time.Time
    t := "2018-01-01T00:00:00-00:00"
    minus, err = time.Parse(time.RFC3339, t)
    if err != nil {
        fmt.Println(err)
    }
    t = "2018-01-01T00:00:00+00:00"
    plus, err = time.Parse(time.RFC3339, t)
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println(minus, plus, minus.Equal(plus), minus == plus)
}
游乐场:

输出:

2018-01-01 00:00:00 +0000 UTC 2018-01-01 00:00:00 +0000 UTC true true

彼得索的回答是完美的。如果您需要根据偏移量未知的信息采取不同的行动,那么这可能会对您有所帮助

您可以构建自己的时间数据类型:

type MyTime struct {
    // based on time.Time so we can do all normal time.Time stuff
    time.Time

    offsetUnknown bool
}

func ParseRFC3339(s string) (MyTime, error) {
    time, err := time.Parse(time.RFC3339, s)
    if err != nil {
        return MyTime{}, err
    }

    return MyTime{
        Time: time,
        // maybe this condition needs improvement in case of false positives
        offsetUnknown: strings.Contains(s, "-00:00"),
    }, nil
}
根据
offsetUnknown
需要以不同方式执行的任何函数,都可以在
MyTime
结构上重写。这里有一个例子:

func (s MyTime) Format(layout string) string {
    out := s.Time.Format(layout)
    // again this is probably not the best solution
    if layout == time.RFC3339 && s.offsetUnknown {
        out = strings.Replace(out, "+00:00", "-00:00", -1)
    }
    return out
}

我不认为Go的
时间
包有一个未知偏移量的概念;这没有什么特别的用处。如果偏移量确实未知,则时间本身就有点无用,因为任何解释都可能不准确+/-12小时-足以使偶数日期可能偏离+/-1天。使用
-00:00
时,时间是准确的,因为RFC表示“UTC时间已知”。只是偏移量未知,因此,例如,如果我们有一个时间
2018-01-01T12:00:00-00:00
,我们知道确切的时间,但不知道偏移量,例如,时间是
2018-01-01T11:00:00-01:00
还是
2018-01-01T13:00:00+01:00
。在这种情况下,其区域设置是UTC。除了及时识别实例之外,时间没有义务提供任何信息。表示“在UTC中午,但我不知道它实际发生在什么地方”的时间是指与
time.time
无关的“it”。关于“他们不接受RFCs允许的所有时间格式”,接受
-00:00
偏移量,因为它解析时没有错误。但是,转换可能有损。@Grokify:
time.Parse
不接受正零和负零偏移格式之间的区别。@Grokify:我建议您查看实际的偏移格式。解析负偏移量时,唯一要做的事情是反转计算出的正偏移量。正如这里所说的,一个整数-0等于+0,只要把它倒过来,它的信息就会丢失。我同意。“关于它的信息丢失了”就是为什么我说转换是有损的。
type MyTime struct {
    // based on time.Time so we can do all normal time.Time stuff
    time.Time

    offsetUnknown bool
}

func ParseRFC3339(s string) (MyTime, error) {
    time, err := time.Parse(time.RFC3339, s)
    if err != nil {
        return MyTime{}, err
    }

    return MyTime{
        Time: time,
        // maybe this condition needs improvement in case of false positives
        offsetUnknown: strings.Contains(s, "-00:00"),
    }, nil
}
func (s MyTime) Format(layout string) string {
    out := s.Time.Format(layout)
    // again this is probably not the best solution
    if layout == time.RFC3339 && s.offsetUnknown {
        out = strings.Replace(out, "+00:00", "-00:00", -1)
    }
    return out
}