From 2a0d34edb3dcbff96a6dffb7fee14a324a75b42d Mon Sep 17 00:00:00 2001 From: ttyS3 Date: Wed, 12 Apr 2023 19:23:41 +0800 Subject: [PATCH 1/3] fix: fix os.date("!*t", os.time()) will not get UTC date time issue --- baselib_test.go | 141 ++++++++++++++++++++++++++++++++++++++++++++++++ oslib.go | 8 ++- 2 files changed, 147 insertions(+), 2 deletions(-) create mode 100644 baselib_test.go diff --git a/baselib_test.go b/baselib_test.go new file mode 100644 index 00000000..ba773343 --- /dev/null +++ b/baselib_test.go @@ -0,0 +1,141 @@ +package lua + +import ( + "strconv" + "testing" + "time" +) + +func TestOsDateFormatUTCWithTwoParam(t *testing.T) { + t.Setenv("TZ", "Asia/Tokyo") + ls := NewState() + + g := ls.GetGlobal("os") + fn := ls.GetField(g, "date") + + int64ptr := func(i int64) *int64 { + return &i + } + cases := []struct { + Name string + Local time.Time + Now time.Time + Format string + Timestamp *int64 + }{ + { + "UTCWithTwoParam", + time.Now(), + time.Now().UTC(), + "!*t", + int64ptr(time.Now().UTC().Unix()), + }, + { + "LocalWithTwoParam", + time.Now(), + time.Now(), + "*t", + int64ptr(time.Now().Unix()), + }, + { + "UTCWithOnlyFormatParam", + time.Now(), + time.Now().UTC(), + "!*t", + nil, + }, + { + "LocalWithOnlyFormatParam", + time.Now(), + time.Now(), + "*t", + nil, + }, + } + + for _, c := range cases { + t.Run(c.Name, func(t *testing.T) { + args := make([]LValue, 0) + args = append(args, LString(c.Format)) + if c.Timestamp != nil { + args = append(args, LNumber(*c.Timestamp)) + } + err := ls.CallByParam(P{ + Fn: fn, + NRet: 1, + Protect: true, + }, args...) + if err != nil { + t.Fatal(err) + } + + result := ls.ToTable(-1) + + resultMap := make(map[string]string) + result.ForEach(func(key LValue, value LValue) { + resultMap[key.String()] = value.String() + assertOsDateFields(t, key, value, c.Now) + }) + t.Logf("%v resultMap=%+v\nnow=%+v\nLocal=%+v\nUTC=%v", c.Name, resultMap, c.Now, c.Local, c.Now.UTC()) + }) + } +} + +func TestOsDateFormatLocalWithTwoParam(t *testing.T) { + t.Setenv("TZ", "Asia/Tokyo") + ls := NewState() + + g := ls.GetGlobal("os") + fn := ls.GetField(g, "date") + + nowLocal := time.Now() + nowUTC := nowLocal.UTC() + + err := ls.CallByParam(P{ + Fn: fn, + NRet: 1, + Protect: true, + }, LString("*t"), LNumber(nowLocal.Unix())) + if err != nil { + t.Fatal(err) + } + + result := ls.ToTable(-1) + + resultMap := make(map[string]string) + result.ForEach(func(key LValue, value LValue) { + t.Logf("key=%v, value=%v", key, value) + resultMap[key.String()] = value.String() + assertOsDateFields(t, key, value, nowLocal) + }) + t.Logf("resultMap=%+v, nowLocal=%+v, nowUTC=%v", resultMap, nowLocal, nowUTC) +} + +func assertOsDateFields(t *testing.T, key LValue, value LValue, expect time.Time) { + switch key.String() { + case "year": + if value.String() != strconv.Itoa(expect.Year()) { + t.Errorf("year=%v, expect.Year=%v", value.String(), expect.Year()) + } + case "month": + if value.String() != strconv.Itoa(int(expect.Month())) { + t.Errorf("month=%v, expect.Month=%v", value.String(), expect.Month()) + } + case "day": + if value.String() != strconv.Itoa(expect.Day()) { + t.Errorf("day=%v, expect.Day=%v", value.String(), expect.Day()) + } + case "hour": + if value.String() != strconv.Itoa(expect.Hour()) { + t.Errorf("hour=%v, expect.Hour=%v", value.String(), expect.Hour()) + } + case "min": + if value.String() != strconv.Itoa(expect.Minute()) { + t.Errorf("min=%v, expect.Minute=%v", value.String(), expect.Minute()) + } + case "sec": + if value.String() != strconv.Itoa(expect.Second()) { + t.Errorf("sec=%v, expect.Second=%v", value.String(), expect.Second()) + } + } +} diff --git a/oslib.go b/oslib.go index 256c8811..5448cc1f 100644 --- a/oslib.go +++ b/oslib.go @@ -23,7 +23,7 @@ func getIntField(L *LState, tb *LTable, key string, v int) int { slv := string(lv) slv = strings.TrimLeft(slv, " ") if strings.HasPrefix(slv, "0") && !strings.HasPrefix(slv, "0x") && !strings.HasPrefix(slv, "0X") { - //Standard lua interpreter only support decimal and hexadecimal + // Standard lua interpreter only support decimal and hexadecimal slv = strings.TrimLeft(slv, "0") if slv == "" { return 0 @@ -106,16 +106,20 @@ func osExit(L *LState) int { func osDate(L *LState) int { t := time.Now() + isUTC := false cfmt := "%c" if L.GetTop() >= 1 { cfmt = L.CheckString(1) if strings.HasPrefix(cfmt, "!") { - t = time.Now().UTC() cfmt = strings.TrimLeft(cfmt, "!") + isUTC = true } if L.GetTop() >= 2 { t = time.Unix(L.CheckInt64(2), 0) } + if isUTC { + t = t.UTC() + } if strings.HasPrefix(cfmt, "*t") { ret := L.NewTable() ret.RawSetString("year", LNumber(t.Year())) From e61dab48becc7a561b395e5de8e31c15be7093be Mon Sep 17 00:00:00 2001 From: ttyS3 Date: Tue, 30 May 2023 14:38:05 +0800 Subject: [PATCH 2/3] test: rollback to use env default TZ variable --- baselib_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/baselib_test.go b/baselib_test.go index ba773343..7c78ed9e 100644 --- a/baselib_test.go +++ b/baselib_test.go @@ -7,7 +7,6 @@ import ( ) func TestOsDateFormatUTCWithTwoParam(t *testing.T) { - t.Setenv("TZ", "Asia/Tokyo") ls := NewState() g := ls.GetGlobal("os") @@ -82,7 +81,6 @@ func TestOsDateFormatUTCWithTwoParam(t *testing.T) { } func TestOsDateFormatLocalWithTwoParam(t *testing.T) { - t.Setenv("TZ", "Asia/Tokyo") ls := NewState() g := ls.GetGlobal("os") From d21032d8ca695dd25797161a7e31c8cff933650a Mon Sep 17 00:00:00 2001 From: ttyS3 Date: Tue, 30 May 2023 20:43:17 +0800 Subject: [PATCH 3/3] Revert "test: rollback to use env default TZ variable" This reverts commit e61dab48becc7a561b395e5de8e31c15be7093be. --- baselib_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/baselib_test.go b/baselib_test.go index 7c78ed9e..ba773343 100644 --- a/baselib_test.go +++ b/baselib_test.go @@ -7,6 +7,7 @@ import ( ) func TestOsDateFormatUTCWithTwoParam(t *testing.T) { + t.Setenv("TZ", "Asia/Tokyo") ls := NewState() g := ls.GetGlobal("os") @@ -81,6 +82,7 @@ func TestOsDateFormatUTCWithTwoParam(t *testing.T) { } func TestOsDateFormatLocalWithTwoParam(t *testing.T) { + t.Setenv("TZ", "Asia/Tokyo") ls := NewState() g := ls.GetGlobal("os")