Go语言GORM自定义时间格式:实现yyyy-MM-dd HH:mm:ss输出

何川
何川
发布时间:2026-10-15| 5人浏览过
原创

在使用Go语言和GORM进行Web开发时,后端返回给前端的时间数据默认往往不符合人类阅读习惯(如RFC3339格式)。本文详细讲解如何定义自定义时间类型LocalTime,通过实现序列化与反序列化接口,将GORM查询结果中的时间统一格式化为"2006-01-02 15:04:05",确保API响应清晰且数据库读写正常。

问题背景

GORM默认基于Go标准库time.Time进行映射。当使用json.Marshal对包含时间的结构体进行序列化时,Go会输出标准的RFC3339Nano格式(例如:2022-12-06T17:49:06+08:00)。虽然该格式符合ISO标准,但在许多业务场景中,前端或用户更偏好简洁的yyyy-MM-dd HH:mm:ss格式。

直接修改time.Time的行为比较困难且容易引发不可预知的兼容性问题。最佳实践是创建一个类型别名,并在其上绑定自定义的方法。

解决方案:自定义LocalTime类型

我们需要定义一个新的类型LocalTime作为time.Time的别名,并实现三个关键接口:

  1. MarshalJSON():控制序列化输出的JSON字符串格式。
  2. Value():实现driver.Valuer接口,控制写入数据库时的值格式。
  3. UnmarshalJSON():控制从JSON解析到本地对象时的反序列化逻辑。

第1步:定义结构与导入依赖

首先准备必要的包,包括GORM、MySQL驱动以及标准库中的编码和时间处理模块。

package main

import (
	"database/sql/driver"
	"encoding/json"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/schema"
	"strings"
	"time"
)

第2步:实现序列化方法 MarshalJSON

该方法将内部的时间转换为指定格式的字符串,并包裹双引号以符合JSON规范。

type LocalTime time.Time

func (t LocalTime) MarshalJSON() ([]byte, error) {
	tTime := time.Time(t)
	return []byte(fmt.Sprintf("\"%v\"", tTime.Format("2006-01-02 15:04:05"))), nil
}

第3步:实现数据库写入 Value

GORM在保存数据时会调用此方法。返回字符串格式可确保存入数据库的也是格式化后的时间(前提是数据库字段类型为datetime或varchar)。

func (t LocalTime) Value() (driver.Value, error) {
	tTime := time.Time(t)
	return tTime.Format("2006-01-02 15:04:05"), nil
}

第4步:实现反序列化 UnmarshalJSON

当接收到前端传来的JSON数据需要存回结构体时,此方法负责解析。注意去除首尾的双引号后解析时间。

func (t *LocalTime) UnmarshalJSON(data []byte) error {
	if string(data) == "null" {
		return nil
	}
	var err error
	str := string(data)
	// 去除接收的str收尾多余的"
	timeStr := strings.Trim(str, "\"")
	t1, err := time.Parse("2006-01-02 15:04:05", timeStr)
	*t = LocalTime(t1)
	return err
}

完整应用示例

下面是整合上述逻辑的完整代码,包含模型定义、数据库连接及测试打印。

type Student struct {
	Id       int
	Name     string
	Age      int
	Sex      string
	CreateAt time.Time // 默认行为
}

func (Student) TableName() string {
	return "student"
}

type StudentLocal struct {
	Id       int
	Name     string
	Age      int
	Sex      string
	CreateAt LocalTime // 自定义行为
}

func (StudentLocal) TableName() string {
	return "student"
}

var db *gorm.DB
var err error

func init() {
	// dsn格式 user:pass@tcp(ip:port)/dbname?charset=utf8mb4&parseTime=True&loc=Local
	dsn := "user:pass@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
	db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
		NamingStrategy: schema.NamingStrategy{
			TablePrefix:   "",
			SingularTable: true,
		}})
	if err != nil {
		panic(err)
	}
}

func main() {
	// 1. 测试默认 Time 类型
	var student Student
	db.First(&student)
	js, _ := json.Marshal(student)
	fmt.Println("Default Time:", string(js))
	// 输出类似: {"Id":1,"Name":"张三","Age":20,"Sex":"男","CreateAt":"2022-12-06T17:49:06+08:00"}

	// 2. 测试自定义 LocalTime 类型
	var studentLocal StudentLocal
	db.First(&studentLocal)
	js, _ = json.Marshal(studentLocal)
	fmt.Println("Custom LocalTime:", string(js))
	// 输出类似: {"Id":1,"Name":"张三","Age":20,"Sex":"男","CreateAt":"2022-12-06 17:49:06"}

	// 3. 单独测试 Value 方法
	value, _ := studentLocal.CreateAt.Value()
	fmt.Println("DB Value:", value)
	// 输出: 2022-12-06 17:49:06
}

注意事项

  • DNS配置:在连接字符串中必须添加&parseTime=True&loc=Local,否则GORM可能无法正确解析本地时区的时间。
  • 时区处理:示例中使用了服务器本地时区(Local)。如果涉及跨时区业务,建议将Format参数改为time.RFC3339或使用UTC格式存储,避免前端显示误差。
  • 空值处理:在UnmarshalJSON中处理了null情况,防止前端未传时间时报错。

以上就是Go语言中GORM自定义时间格式化的详细内容,更多关于Go GORM时间格式化的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。