From b7d2273b1c9016e7c7d05e0570e3865fe30f8d70 Mon Sep 17 00:00:00 2001 From: Aaron Lindsay Date: Sun, 29 Jan 2017 21:09:23 -0500 Subject: [PATCH] lua: Add dates --- date_lua.go | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++ reports.go | 1 + 2 files changed, 112 insertions(+) create mode 100644 date_lua.go diff --git a/date_lua.go b/date_lua.go new file mode 100644 index 0000000..31dfd0a --- /dev/null +++ b/date_lua.go @@ -0,0 +1,111 @@ +package main + +import ( + "github.com/yuin/gopher-lua" + "time" +) + +const luaDateTypeName = "date" +const timeFormat = "2006-01-02" + +// Registers my date type to given L. +func luaRegisterDates(L *lua.LState) { + mt := L.NewTypeMetatable(luaDateTypeName) + L.SetGlobal("date", mt) + L.SetField(mt, "new", L.NewFunction(luaDateNew)) + L.SetField(mt, "__tostring", L.NewFunction(luaDate__tostring)) + L.SetField(mt, "__eq", L.NewFunction(luaDate__eq)) + L.SetField(mt, "__lt", L.NewFunction(luaDate__lt)) + L.SetField(mt, "__le", L.NewFunction(luaDate__le)) + L.SetField(mt, "__metatable", lua.LString("protected")) +} + +func TimeToLua(L *lua.LState, date *time.Time) *lua.LUserData { + ud := L.NewUserData() + ud.Value = date + L.SetMetatable(ud, L.GetTypeMetatable(luaDateTypeName)) + return ud +} + +// Checks whether the first lua argument is a *LUserData with *Time and returns this *Time. +func luaCheckTime(L *lua.LState, n int) *time.Time { + ud := L.CheckUserData(n) + if date, ok := ud.Value.(*time.Time); ok { + return date + } + L.ArgError(n, "date expected") + return nil +} + +func luaWeakCheckTableFieldInt(L *lua.LState, T *lua.LTable, n int, name string, def int) int { + lv := T.RawGetString(name) + if lv == lua.LNil { + return def + } + if i, ok := lv.(lua.LNumber); ok { + return int(i) + } + L.ArgError(n, "table field '"+name+"' expected to be int") + return def +} + +func luaDateNew(L *lua.LState) int { + v := L.Get(1) + if s, ok := v.(lua.LString); ok { + date, err := time.Parse(timeFormat, s.String()) + if err != nil { + L.ArgError(1, "error parsing date string: "+err.Error()) + return 0 + } + L.Push(TimeToLua(L, &date)) + return 1 + } + var year, month, day int + if t, ok := v.(*lua.LTable); ok { + year = luaWeakCheckTableFieldInt(L, t, 1, "year", 0) + month = luaWeakCheckTableFieldInt(L, t, 1, "month", 1) + day = luaWeakCheckTableFieldInt(L, t, 1, "day", 1) + } else { + year = L.CheckInt(1) + month = L.CheckInt(2) + day = L.CheckInt(3) + } + date := time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.Local) + L.Push(TimeToLua(L, &date)) + return 1 +} + +func luaDate__tostring(L *lua.LState) int { + a := luaCheckTime(L, 1) + + L.Push(lua.LString(a.Format(timeFormat))) + + return 1 +} + +func luaDate__eq(L *lua.LState) int { + a := luaCheckTime(L, 1) + b := luaCheckTime(L, 2) + + L.Push(lua.LBool(a.Equal(*b))) + + return 1 +} + +func luaDate__lt(L *lua.LState) int { + a := luaCheckTime(L, 1) + b := luaCheckTime(L, 2) + + L.Push(lua.LBool(a.Before(*b))) + + return 1 +} + +func luaDate__le(L *lua.LState) int { + a := luaCheckTime(L, 1) + b := luaCheckTime(L, 2) + + L.Push(lua.LBool(a.Equal(*b) || a.Before(*b))) + + return 1 +} diff --git a/reports.go b/reports.go index b109081..903bb0c 100644 --- a/reports.go +++ b/reports.go @@ -60,6 +60,7 @@ func ReportHandler(w http.ResponseWriter, r *http.Request) { luaRegisterAccounts(L) luaRegisterSecurities(L) luaRegisterBalances(L) + luaRegisterDates(L) err := L.DoString(`accounts = account.get_all() last_parent = nil