【问题标题】:Golang JSON time default layout varies by platform?Golang JSON 时间默认布局因平台而异?
【发布时间】:2015-05-24 00:13:38
【问题描述】:

我遇到了一个奇怪的问题,即time.Time 的 JSON 编码字符串在我的开发环境 (OSX) 和生产环境 (Ubuntu 14.04 x64) 之间有所不同。

type Thang struct {
  CreatedAt time.Time `json:"created_at"`
}

OSX:

{
  // RFC3339 layout
  created_at: "2015-04-24T22:39:59Z",
}

Ubuntu 14.04 x64:

{
  // RFC3339Nano layout
  created_at: "2015-05-21T15:00:46.546000003Z",
}

我一直在谷歌上搜索。想不通这个以下是更多信息:

  • 这是一个简单的网络服务应用程序
  • 在我的 OSX 机器上运行 go 1.4.1
  • 我在我的 OSX 机器上交叉编译应用程序以进行如下部署:
    • GOOS=linux GOARCH=amd64 go build

希望有任何见解!

【问题讨论】:

    标签: macos ubuntu go


    【解决方案1】:

    time.TimeMarshalJSON的来源是:

    // MarshalJSON implements the json.Marshaler interface.
    // The time is a quoted string in RFC 3339 format, with sub-second precision added if present.
    func (t Time) MarshalJSON() ([]byte, error) {
            if y := t.Year(); y < 0 || y >= 10000 {
                    // RFC 3339 is clear that years are 4 digits exactly.
                    // See golang.org/issue/4556#c15 for more discussion.
                    return nil, errors.New("Time.MarshalJSON: year outside of range [0,9999]")
            }
            return []byte(t.Format(`"` + RFC3339Nano + `"`)), nil
    }
    

    [time.MarshalJSON source on GitHub]

    并且在所有平台上都是相同的。 注意:

    […] 如果存在,则添加亚秒级精度。

    还有RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"。 “9”的意思是使用最多这么多位但删除尾随零。 所以看起来你的两个例子都可以匹配这种格式。 (当解析时间时,无论格式如何,Go 总是接受并解析小数秒)。

    RFC3339 的第 5.6 节指定小数秒是可选的,可能包含也可能不包含(仅说明如果存在小数点,则它必须后跟至少一位数字)。

    由于某种原因,您在一个系统上使用的时间是否只有第二个精度或类似的精度? (例如,这是否来自某个文件系统或仅在其中一个操作系统上存储秒数的其他子系统?)。

    【讨论】:

    • 谢谢!是的,我现在意识到这不是一个真正的问题。消费这个的客户必须能够同时服用。我认为文件系统存在一些差异。
    【解决方案2】:

    RFC3339 没有说明时间的精度。似乎 Ubuntu 坚持要添加另外九位十进制数字的精度,根据 RFC3339 这很好。

    在 iOS / MacOS X 上,相同的日期格式解析器无法解析带小数点和不带小数点的秒数,因此我使用了两种格式

    "yyyy'-'MM'-'dd'T'HH':'mm':'ssX5"
    "yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSSSSSSSSX5"
    

    并尝试两者。 (实际上我有六个 S 字符,因为我认为没有理智的人会使用超过六个小数。这是错误的)。

    我认为 iOS / MacOS X 中的日期格式是由 Unicode 标准标准化的,因此这也可能适用于其他解析器。出于效率原因,我会记住哪个解析器最后一次工作并首先尝试那个 - 如果你有一个纳秒的日期,那么下一个日期也可能有纳秒。

    【讨论】:

    • 您给定的格式字符串不适用于 Go(这就是这个问题的意义所在)。在 Go 格式字符串中,如果您想要小数点后的三位数字,则使用“05.000”;如果您想要删除尾随零的最多三位数字,则使用“05.999”(当然,根据需要使用更少或更多的 0 或 9)。在 Go 中解析时,总是会接受并解析小数秒。
    • 感谢@gnasher729 的回复。您正确推断出我正在开发 iOS 应用程序。我希望 NSDateFormatter 对这些东西更聪明一点。没有 简单 方法可以将日期从 Go 标准化为整秒,所以我将尝试使用您建议的一对格式化程序
    猜你喜欢
    • 2021-07-23
    • 2016-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-04
    • 2012-05-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多