feat(timex): 自 go-hua/common 迁入时间日期工具并独立成包
- NT/UTC 时间戳互转、时间字符串转毫秒时间戳、指定年月天数 - 附单元测试、examples/timex 例程与包 README
This commit is contained in:
@@ -0,0 +1,23 @@
|
|||||||
|
// timex 包示例:时间日期工具(NT/UTC 时间戳互转、时间字符串转毫秒时间戳、月份天数)
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"git.zeroonesoft.cn/golib/zogo/timex"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Windows NT 时间戳与 Unix 时间戳互转
|
||||||
|
nt := timex.UtcToNt(1000000000)
|
||||||
|
fmt.Println("Unix 转 NT:", nt)
|
||||||
|
fmt.Println("NT 转 Unix:", timex.NtToUtc(nt))
|
||||||
|
|
||||||
|
// 时间字符串转毫秒时间戳
|
||||||
|
ts, err := timex.TimeStrToTimestamp("2026-08-29 12:00:00")
|
||||||
|
fmt.Println("时间字符串转毫秒时间戳:", ts, "错误:", err)
|
||||||
|
|
||||||
|
// 查询指定年月有多少天
|
||||||
|
fmt.Println("2026年2月天数:", timex.GetYearMonthToDay(2026, 2))
|
||||||
|
fmt.Println("2024年2月天数:", timex.GetYearMonthToDay(2024, 2))
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# timex
|
||||||
|
|
||||||
|
时间与日期工具:Windows NT 时间戳与 Unix 时间戳互转、时间字符串转毫秒时间戳、
|
||||||
|
查询指定年月的天数。
|
||||||
|
|
||||||
|
> 迁移自 go-hua/common(原 time.go / date.go)。
|
||||||
|
|
||||||
|
## 用法
|
||||||
|
|
||||||
|
```go
|
||||||
|
import "git.zeroonesoft.cn/golib/zogo/timex"
|
||||||
|
|
||||||
|
// Windows NT 时间戳(100 纳秒,1601 纪元)与 Unix 秒级时间戳互转
|
||||||
|
nt := timex.UtcToNt(1000000000)
|
||||||
|
unix := timex.NtToUtc(nt)
|
||||||
|
|
||||||
|
// 时间字符串 → 毫秒时间戳(本地时区,格式 2006-01-02 15:04:05)
|
||||||
|
ts, err := timex.TimeStrToTimestamp("2026-08-29 12:00:00")
|
||||||
|
|
||||||
|
// 指定年月有多少天(自动处理闰年)
|
||||||
|
timex.GetYearMonthToDay(2024, 2) // 29
|
||||||
|
```
|
||||||
|
|
||||||
|
完整可运行例程:[examples/timex/main.go](../examples/timex/main.go)
|
||||||
|
|
||||||
|
## 注意
|
||||||
|
|
||||||
|
- `NtToUtc/UtcToNt` 为秒级精度整数运算(NT 侧按 1e7 折算),无溢出保护。
|
||||||
|
- `TimeStrToTimestamp` 只接受 `2006-01-02 15:04:05` 一种格式,其他格式自行用
|
||||||
|
标准库 `time.ParseInLocation`。
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
// Package timex 时间与日期工具:Windows NT 时间戳与 Unix 时间戳互转、
|
||||||
|
// 时间字符串转毫秒时间戳、查询指定年月的天数。
|
||||||
|
package timex
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NtToUtc Windows NT timestamp to Unix UTC timestamp
|
||||||
|
func NtToUtc(ntTimestamp uint64) uint64 {
|
||||||
|
unixTimestamp := (ntTimestamp - 11644473600000000) / 1000000
|
||||||
|
return unixTimestamp
|
||||||
|
}
|
||||||
|
|
||||||
|
// UtcToNt Unix UTC timestamp to Windows NT timestamp
|
||||||
|
func UtcToNt(unixTime uint64) uint64 {
|
||||||
|
ntTimestamp := unixTime*1000000 + 11644473600000000
|
||||||
|
return ntTimestamp
|
||||||
|
}
|
||||||
|
|
||||||
|
// 时间字符串转时间戳
|
||||||
|
func TimeStrToTimestamp(timeStr string) (int64, error) {
|
||||||
|
layout := "2006-01-02 15:04:05"
|
||||||
|
t, err := time.ParseInLocation(layout, timeStr, time.Local)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
// 获取时间戳(单位是秒),并转换为毫秒
|
||||||
|
millisecondTimestamp := t.UnixMilli()
|
||||||
|
return millisecondTimestamp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetYearMonthToDay 查询指定年份指定月份有多少天
|
||||||
|
// @params year int 指定年份
|
||||||
|
// @params month int 指定月份
|
||||||
|
func GetYearMonthToDay(year int, month int) int {
|
||||||
|
// 有31天的月份
|
||||||
|
day31 := map[int]bool{
|
||||||
|
1: true,
|
||||||
|
3: true,
|
||||||
|
5: true,
|
||||||
|
7: true,
|
||||||
|
8: true,
|
||||||
|
10: true,
|
||||||
|
12: true,
|
||||||
|
}
|
||||||
|
if day31[month] {
|
||||||
|
return 31
|
||||||
|
}
|
||||||
|
// 有30天的月份
|
||||||
|
day30 := map[int]bool{
|
||||||
|
4: true,
|
||||||
|
6: true,
|
||||||
|
9: true,
|
||||||
|
11: true,
|
||||||
|
}
|
||||||
|
if day30[month] {
|
||||||
|
return 30
|
||||||
|
}
|
||||||
|
// 计算是平年还是闰年
|
||||||
|
if (year%4 == 0 && year%100 != 0) || year%400 == 0 {
|
||||||
|
// 得出2月的天数
|
||||||
|
return 29
|
||||||
|
}
|
||||||
|
// 得出2月的天数
|
||||||
|
return 28
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package timex
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestGetYearMonthToDay(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
year, month, want int
|
||||||
|
}{
|
||||||
|
{2024, 2, 29}, // 闰年
|
||||||
|
{2023, 2, 28}, // 平年
|
||||||
|
{2000, 2, 29}, // 400 整除
|
||||||
|
{1900, 2, 28}, // 100 整除非 400
|
||||||
|
{2026, 1, 31},
|
||||||
|
{2026, 4, 30},
|
||||||
|
}
|
||||||
|
for _, c := range cases {
|
||||||
|
if got := GetYearMonthToDay(c.year, c.month); got != c.want {
|
||||||
|
t.Errorf("GetYearMonthToDay(%d,%d) = %d, want %d", c.year, c.month, got, c.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNtUtcConvert(t *testing.T) {
|
||||||
|
nt := UtcToNt(1000000000)
|
||||||
|
if got := NtToUtc(nt); got != 1000000000 {
|
||||||
|
t.Errorf("NT/UTC 往返 = %d, want 1000000000", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTimeStrToTimestamp(t *testing.T) {
|
||||||
|
ts, err := TimeStrToTimestamp("2026-08-29 12:00:00")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("TimeStrToTimestamp: %v", err)
|
||||||
|
}
|
||||||
|
if ts <= 0 {
|
||||||
|
t.Errorf("时间戳应为正数: %d", ts)
|
||||||
|
}
|
||||||
|
if ts%1000 != 0 {
|
||||||
|
t.Errorf("毫秒时间戳应为整秒: %d", ts)
|
||||||
|
}
|
||||||
|
if _, err := TimeStrToTimestamp("bad"); err == nil {
|
||||||
|
t.Error("非法格式应返回错误")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user