前言
如果你使用过GO语言,那么你一定会注意到,他的时间格式化跟别的语言有所不同,在与其他语言通过api交互的过程中,还可能会报错。
时间格式化
将时间格式化为字符串
t1 := time.Now()
fmt.Println(t1.Format("2006-01-02 15:04:05"))
将字符串格式化为时间
t2, err := time.Parse("2006-01-02 15:04:05", "2023-02-15 14:30:00")
// 2023-02-15 14:30:00 +0000 UTC
loc, err := time.LoadLocation("Asia/Shanghai")
if err != nil {
fmt.Println("LoadLocation error:", err)
return
}
t3, err := time.ParseInLocation("2006-01-02 15:04:05", "2023-02-15 14:30:00", loc)
// 2023-02-15 14:30:00 +0800 CST
常用时间格式
yyyy-MM-ddTHH:mm:ss.SSSZ
T使用用来分割日期和时间的;Z表示UTC统一时间,代表着时区为UTC+0,如果需要修改时差的话,把Z换成时差,比如+08:00;
SSS表示毫秒数,通常用不到;
UTC表示世界协调时间(Coordinated Universal Time),UTC时间与北京时间相差8小时 (世界协调时间 UTC +00:00 相当于北京 UTC +8:00),以下是一些不同时区的具体时间表示
2019-10-12T07:20:50.52Z (UTC+0)
2019-10-12T07:20:50.52+00:00 (UTC+0)
2019-10-12T14:20:50.52+08:00 (UTC+8)
2019-10-12T03:20:50.52-04:00 (UTC-4)
除了UTC,还有其他的时间标准,比如GMT、AST、CST等,都可与UTC进行转换
GO中时间格式化标准格式 2006-01-02 15:04:05
如何快速记忆:01 02 03 04 05,24小时制的话03就用15代替;老外常用的格式是
Mon Jan 2 15:04:05 2006 -0700 MST 对应着0 1 2 3 4 5 6 7
接收JavaScript的日期时间
正常情况下,传递给后端 yyyy-MM-dd HH:mm:ss 这种格式,会报错,因为在序列化的时候默认用的是RFC3339Nano标准格式,在time.go和format.go中有如下定义
// time.go
// 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]")
}
b := make([]byte, 0, len(RFC3339Nano)+2)
b = append(b, '"')
b = t.AppendFormat(b, RFC3339Nano)
b = append(b, '"')
return b, nil
}
// format.go
const (
// ...
RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
)
要怎么解决呢
方式一,前端直接通过系统函数,将时间格式化为ISO 8601(RFC 3339)格式的时间,然后传递给后端
datetime.toISOString() // "2023-02-15T23:59:59.386Z"
方式二,前端传递"yyyy-MM-dd HH:mm:ss"格式的时间字符串,后端按字符串来接收,然后再转换为time.Time类型使用
import moment from 'moment';
const date = new Date();
const formattedDate = moment(date).format('YYYY-MM-DD HH:mm:ss');
console.log(formattedDate); // 2023-02-15 16:45:30
在上面的代码中,我们使用了第三方库momentjs,当然也可以用date-fns.org或者dayjs;还可以直接通过时间对象的函数,获取年、月、日,然后拼接起来
function formatDate(date) {
const year = date.getFullYear().toString().padStart(4, '0');
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
const hours = date.getHours().toString().padStart(2, '0');
const minutes = date.getMinutes().toString().padStart(2, '0');
const seconds = date.getSeconds().toString().padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
const date = new Date();
const formattedDate = formatDate(date);
console.log(formattedDate); // 2023-02-15 16:45:30
关于ISO 8601 和 RFC 3339
对于时间的表示格式,ISO对其进行了标准化,就是现在常见的ISO 8601标准。 在使用的过程中,你大可不必细究其中的区别。你需要知道是,RFC3339是从ISO 8601派生的一组标准,有着一些细小的区别。比如 RFC 3339可以不用带"T",具体可以查看