
本文介绍如何在go中定义结构体并解析类似java xmlgregoriancalendar生成的嵌套日期时间json数据,重点处理年月日、时分秒及偏移量转换为标准time.time类型。
本文介绍如何在go中定义结构体并解析类似java xmlgregoriancalendar生成的嵌套日期时间json数据,重点处理年月日、时分秒及偏移量转换为标准time.time类型。
在实际对接Java后端(尤其是使用JAXB或JAX-WS服务)时,常会收到形如 XMLGregorianCalendarImpl 的日期时间JSON片段——它并非标准ISO格式,而是以离散字段(year、month、day、hour、minute、second、timezone)形式存在。Go原生不支持直接反序列化为 time.Time,需手动构造并解析。
正确建模嵌套日期结构
首先,根据JSON结构层级定义Go结构体。注意使用json标签精确匹配字段名,并利用内嵌结构体简化访问:
type StartDate struct {
Class string `json:"_class"`
Year int `json:"year"`
Month int `json:"month"`
Day int `json:"day"`
Timezone string `json:"timezone"` // 注意:原始数据中 timezone 是 NumberInt(-300),需预处理为 "-0500" 格式
Hour int `json:"hour"`
Minute int `json:"minute"`
Second int `json:"second"`
}
type EffectiveDates struct {
StartDate `json:"startDate"`
}
type Payload struct {
EffectiveDates `json:"effectiveDates"`
}
⚠️ 关键提醒:MongoDB或某些Java序列化器输出的 timezone: NumberInt(-300) 并非合法JSON数值(NumberInt 是Mongo Shell扩展语法)。真实HTTP响应中应为纯数字(如 -300)或已转为字符串(如 "-0500")。若接收的是整数型时区偏移(单位:分钟),需自行转换:
func intToTimezoneStr(offsetMinutes int) string { sign := "+" if offsetMinutes
构造时间字符串并解析为 time.Time
Go的time.Parse要求输入格式与布局字符串严格一致。推荐使用 2006-01-02 15:04:05 -0700(即RFC3339基础格式)进行解析:
timeStr := fmt.Sprintf("%d-%02d-%02d %02d:%02d:%02d %s",
p.Year, p.Month, p.Day,
p.Hour, p.Minute, p.Second,
p.Timezone,
)
t, err := time.Parse("2006-01-02 15:04:05 -0700", timeStr)
if err != nil {
log.Fatal("failed to parse time:", err)
}
fmt.Println(t.Format(time.RFC3339)) // 输出:2008-10-16T09:50:13-05:00
✅ 使用 %02d 确保月份、日期、时分秒补零,避免 10-16 解析失败;时区字符串必须符合 -0700 格式(不能是 -300 或 UTC-5)。
完整可运行示例
package main
import (
"encoding/json"
"fmt"
"log"
"time"
)
type StartDate struct {
Class string `json:"_class"`
Year int `json:"year"`
Month int `json:"month"`
Day int `json:"day"`
Timezone string `json:"timezone"`
Hour int `json:"hour"`
Minute int `json:"minute"`
Second int `json:"second"`
}
type EffectiveDates struct {
StartDate `json:"startDate"`
}
type Payload struct {
EffectiveDates `json:"effectiveDates"`
}
func main() {
input := `{
"effectiveDates": {
"startDate": {
"_class": "com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl",
"year": 2008,
"month": 10,
"day": 16,
"timezone": "-0500",
"hour": 9,
"minute": 50,
"second": 13
}
}
}`
var p Payload
if err := json.Unmarshal([]byte(input), &p); err != nil {
log.Fatal("JSON unmarshal failed:", err)
}
timeStr := fmt.Sprintf("%d-%02d-%02d %02d:%02d:%02d %s",
p.Year, p.Month, p.Day,
p.Hour, p.Minute, p.Second,
p.Timezone,
)
t, err := time.Parse("2006-01-02 15:04:05 -0700", timeStr)
if err != nil {
log.Fatal("time parsing failed:", err)
}
fmt.Println("Parsed time (RFC3339):", t.Format(time.RFC3339))
// Output: Parsed time (RFC3339): 2008-10-16T09:50:13-05:00
}
? 总结:处理此类日期结构的核心在于——结构体建模要贴合JSON层级,时区需标准化为±HHMM格式,再通过time.Parse安全转换。避免直接操作时间戳或硬编码偏移,确保跨时区场景下的正确性与可维护性。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











