From ded29fd751cb8318c59006d09d4cfcc797f42a23 Mon Sep 17 00:00:00 2001 From: William Wilgus Date: Mon, 5 Jan 2026 09:31:27 -0500 Subject: [PATCH] lua plugin remove strfrtime in favor of strfrtm.lua saves 2.2k on the bin also supplies gmtime, and a test script to check the returned time/dates Change-Id: Ib83b11d89bdf44a50830ff51c72ac6395b675603 --- apps/plugins/lua/SOURCES | 1 - apps/plugins/lua/include_lua/strftime.lua | 299 ++++++++++++++++++ apps/plugins/lua/loslib.c | 15 +- .../plugins/lua/lua_tests/time_date_tests.lua | 212 +++++++++++++ apps/plugins/lua/rockaux.c | 2 +- apps/plugins/lua/rockconf.h | 3 + apps/plugins/lua_scripts/time_date.lua | 48 +++ 7 files changed, 574 insertions(+), 6 deletions(-) create mode 100644 apps/plugins/lua/include_lua/strftime.lua create mode 100644 apps/plugins/lua/lua_tests/time_date_tests.lua create mode 100644 apps/plugins/lua_scripts/time_date.lua diff --git a/apps/plugins/lua/SOURCES b/apps/plugins/lua/SOURCES index d30552343b..157fe3db72 100644 --- a/apps/plugins/lua/SOURCES +++ b/apps/plugins/lua/SOURCES @@ -31,7 +31,6 @@ rockaux.c rocklib.c rocklib_img.c tlsf_helper.c -strftime.c strpbrk.c rocklua.c luadir.c diff --git a/apps/plugins/lua/include_lua/strftime.lua b/apps/plugins/lua/include_lua/strftime.lua new file mode 100644 index 0000000000..6cf449aeec --- /dev/null +++ b/apps/plugins/lua/include_lua/strftime.lua @@ -0,0 +1,299 @@ +--[[ + __________ __ ___. + Open \______ \ ____ ____ | | _\_ |__ _______ ___ + Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + \/ \/ \/ \/ \/ + $Id$ + + strfrtime + Copyright (C) 2026 William Wilgus + gmtime + * Copyright (C) 2017 by Michael Sevakis + * Copyright (C) 2012 by Bertrik Sikken + * Based on code from: rtc_as3514.c + * Copyright (C) 2007 by Barry Wardell + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + KIND, either express or implied. +]]-- + +-- Lua implementation of strftime +-- if not os.time() then rb.splash(rb.HZ, "No Support!") return nil end + +-- Weekday and month names +local weekdays = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"} +local months = {"January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December" +} +--local ampm = {"am", "pm", "AM", "PM"} + +local strformat = string.format + +-- Main strftime function +local function strftime(tmfmt, tm) + local result = {} + local i = 1 + + while i <= #tmfmt do + local out = "" + local c = tmfmt:sub(i,i) + if c == "%" then + i = i + 1 + c = tmfmt:sub(i,i) + if c ~= "%" then + local handled + repeat + handled = true + if c == "n" then + out = "\n" + elseif c == "N" then --custom for rocklua + out = strftime("%a %d %T %b %Y", tm) + elseif c == "t" then + out = "\t" + elseif c == "c" then + out = strftime("%x %T %Z %Y", tm) + elseif c == "r" then + out = strftime("%I:%M:%S %p", tm) + elseif c == "R" then + out = strftime("%H:%M", tm) + elseif c == "x" then + out = strftime("%b %a %d", tm) + elseif c == "T" or c == "X" then + out = strformat("%02d:%02d:%02d", + tm.hour, tm.min, tm.sec) + elseif c == "D" then + out = strformat("%02d/%02d/%02d", + tm.mon, tm.day, tm.year % 100) + elseif c == "F" then + out = strftime("%Y-%m-%d", tm) + elseif c == "a" then + out = weekdays[tm.wday + 1]:sub(1, 3) + elseif c == "A" then + out = weekdays[tm.wday + 1] + elseif c == "h" or c == "b" then + out = months[tm.month + 1]:sub(1, 3) + elseif c == "B" then + out = months[tm.month + 1] + elseif c == "p" then + --local idx = tm.hour > 12 and 4 or 5 + out = tm.hour > 12 and "PM" or "AM" + elseif c == "P" then + --local idx = tm.hour > 12 and 2 or 1 + out = tm.hour > 12 and "pm" or "am" + elseif c == "C" then + local no = (tm.year / 100) + 19 + out = strformat("%02d", no) + elseif c == "d" then + out = strformat("%02d", tm.day) + elseif c == "e" then + out = strformat("%2.0d", tm.day) + elseif c == "H" then + out = strformat("%02d", tm.hour) + elseif c == "I" then + local no = tm.hour % 12 + if no == 0 then no = 12 end + out = strformat("%02d", no) + elseif c == "j" then + out = strformat("%03d", tm.yday) + elseif c == "k" then + out = strformat("%2.0d", tm.hour) + elseif c == "l" then + local no = tm.hour % 12 + if no == 0 then no = 12 end + out = strformat("%2.0d", no) + elseif c == "m" then + out = strformat("%02d", tm.mon) + elseif c == "M" then + out = strformat("%02d", tm.min) + elseif c == "S" then + out = strformat("%02d", tm.sec) + elseif c == "u" then + local no = tm.wday == 0 and 7 or tm.wday + out = strformat("%d", no) + elseif c == "w" then + out = strformat("%d", tm.wday) + elseif c == "U" then + local no = ((tm.yday - tm.wday + 7) / 7) + out = strformat("%02d", no) + elseif c == "W" then + local no = ((tm.yday - (tm.wday + 7) % 7 + 7) / 7) + out = strformat("%02d", no) + elseif c == "s" then + out = os.time() + elseif c == "Z" then + out = "[ETC?]" + elseif c == "Y" then + local y1 = (tm.year / 100) + 19 + local y2 = tm.year % 100 + out = strformat("%02d%02d", y1, y2) + elseif c == "y" then + out = strformat("%02d", tm.year % 100) + elseif c == "O" or c == "E" then + i = i + 1 + c = tmfmt:sub(i,i) + handled = false + else + out = "%" .. c + end + until (handled == true) + else -- c == "%" + out = "%" + end + else + out = c + end + table.insert(result, out) + i = i + 1 + end + + return table.concat(result) +end + +--[[ +Note: This implementation assumes the following structure for the `tm` +table (similar to C's `struct tm`): + +local tm = { + year = 126, -- Years since 1900 + mon = 0, -- Month (0-11) + day = 5, -- Day of month (1-31) + hour = 14, -- Hours (0-23) + min = 30, -- Minutes (0-59) + sec = 45, -- Seconds (0-59) + wday = 2, -- Day of week (0-6, Sunday=0) + yday = 4, -- Day of year (0-365) + isdst = false -- Daylight saving time flag +} + +For a complete implementation, you would need to add proper timezone handling +]] + +local UNIX_EPOCH_DAY_NUM = 134774 +local UNIX_EPOCH_YEAR = (1601 - 1900) +-- Last day number it can do +local MAX_DAY_NUM = 551879 + +--[[ d is days since epoch start, Monday, 1 January 1601 (d = 0) + UNIX_EPOCH_DAY_NUM + * + * That date is the beginning of a full 400 year cycle and so simplifies the + * calculations a bit, not requiring offsets before divisions to shift the + * leap year cycle. + * + * It can handle dates up through Sunday, 31 December 3111 (d = 551879). + * + * time_t can't get near the limits anyway for now but algorithm can be + * altered slightly to increase range if even needed. +--Different than the rockbox version starting from midnight UTC on January 1, 1970 + ]] +local mon_yday = { + -- year day of 1st of month (non-leap) +-- +31 +28 +31 +30 +31 +30 +31 +31 +30 +31 +30 +31 +31 + 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 +} + +local function get_tmdate(d, tm) + d = d + UNIX_EPOCH_DAY_NUM -- different than the rb version + local x0 = (d / 1460) + local x1 = (x0 / 25) + local x2 = (x1 / 4) + + local y = ((d - x0 + x1 - x2) / 365) + + x0 = (y / 4) + x1 = (x0 / 25) + x2 = (x1 / 4) + + local yday = d - x0 + x1 - x2 - y * 365 + + local x3 = yday + local tm_yday = yday + + -- check if leap year; adjust February->March transition if so rather + -- than keeping a leap year version of mon_yday[] + + if y - x0 * 4 == 3 and (x0 - x1 * 25 ~= 24 or x1 - x2 * 4 == 3) then + if x3 >= mon_yday[3] then + x3 = x3 - 1 + if x3 >= mon_yday[3] then + yday = yday - 1 + end + end + end + + -- stab approximately at current month based on year day; advance if + -- it fell short (never initially more than 1 short). + + x0 = (x3 / 32) + if mon_yday[x0 + 2] <= x3 then + x0 = x0 + 1 + end + + tm = tm or {} + tm.year = y + UNIX_EPOCH_YEAR -- year - 1900 + tm.month = x0 -- 0..11 + tm.yday = tm_yday + tm.day = yday - mon_yday[x0 + 1] + 1 -- 1..31 + tm.wday = (d + 1) % 7 -- 0..6 + return tm--return tm +end + +local function gmtime(t, tm) + tm = tm or {} + + local d = (t / 86400) + local s = t - d * 86400 + + if s < 0 then + d = d - 1 + s = s + 86400 + end + + local x = (s / 3600) + tm.hour = x -- 0..23 + + s = s - x * 3600 + x = (s / 60) + tm.min = x -- 0..59 + + s = s - x * 60 + tm.sec = s -- 0..59 + + tm.isdst = false -- not implemented right now + + return get_tmdate(d, tm) +end + +local function os_date(format_string, timestamp) + format_string = format_string or "%N" + timestamp = timestamp or os.time() + if format_string:sub(1, 1) == "!" then -- UTC + format_string = format_string:sub(2) + --else -- Localtime -- Rockbox doesn't support timezones + --timestamp = get_tz(timestamp) + end + local tt = gmtime(timestamp); + + if format_string == "*t" then + return tt + else + return strftime(format_string, tt) + end +end + +--fill os.date +if not os.date() then + os.date = os_date; +end + +return { + strftime = strftime; + os_date = os_date; + get_tmdate = get_tmdate; + gmtime = gmtime; +} diff --git a/apps/plugins/lua/loslib.c b/apps/plugins/lua/loslib.c index a0ea8e8c24..fcd5c6a16c 100644 --- a/apps/plugins/lua/loslib.c +++ b/apps/plugins/lua/loslib.c @@ -54,7 +54,7 @@ static int os_rename (lua_State *L) { ** wday=%w+1, yday=%j, isdst=? } ** ======================================================= */ - +#if 0 /* supplied by strfrtime.lua*/ static void setfield (lua_State *L, const char *key, int value) { lua_pushinteger(L, value); lua_setfield(L, -2, key); @@ -66,6 +66,7 @@ static void setboolfield (lua_State *L, const char *key, int value) { lua_pushboolean(L, value); lua_setfield(L, -2, key); } +#endif #if CONFIG_RTC static int getboolfield (lua_State *L, const char *key) { @@ -94,10 +95,11 @@ static int getfield (lua_State *L, const char *key, int d) { static int os_date (lua_State *L) { +#if 0 const char *s = luaL_optstring(L, 1, "%c"); time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, #if CONFIG_RTC - rb->mktime(rb->get_time()) + mktime(get_time()) #else 0 #endif @@ -139,13 +141,18 @@ static int os_date (lua_State *L) { luaL_pushresult(&b); } return 1; +#else /* supplied by strfrtime.lua*/ + lua_pushnil(L); + return 1; +#endif + } static int os_time (lua_State *L) { time_t t = -1; #if CONFIG_RTC if (lua_isnoneornil(L, 1)) /* called without args? */ - t = rb->mktime(rb->get_time()); /* get current time */ + t = mktime(get_time()); /* get current time */ else { struct tm ts; luaL_checktype(L, 1, LUA_TTABLE); @@ -157,7 +164,7 @@ static int os_time (lua_State *L) { ts.tm_mon = getfield(L, "month", -1) - 1; ts.tm_year = getfield(L, "year", -1) - 1900; ts.tm_isdst = getboolfield(L, "isdst"); - t = rb->mktime(&ts); + t = mktime(&ts); } #endif if (t == (time_t)(-1)) diff --git a/apps/plugins/lua/lua_tests/time_date_tests.lua b/apps/plugins/lua/lua_tests/time_date_tests.lua new file mode 100644 index 0000000000..4fd56de6f6 --- /dev/null +++ b/apps/plugins/lua/lua_tests/time_date_tests.lua @@ -0,0 +1,212 @@ +--[[ + __________ __ ___. + Open \______ \ ____ ____ | | _\_ |__ _______ ___ + Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + \/ \/ \/ \/ \/ + $Id$ + + Copyright (C) 2026 William Wilgus + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + KIND, either express or implied. +]]-- + +if not os.time() then rb.splash(rb.HZ, "No Support!") return nil end + +local timefns = require("strftime") +-- Random timestamps with expected UTC tm fields +-- yday is 0-based, wday is 1=Sunday + +local tests = { +{ts = 0, --Thu Jan 1 00:00:00 1970 + tm = {year=70, month=0, day=1, hour=0, min=0, sec=0, wday=4, yday=0}}, +{ts = 15620300, --Tue Jun 30 18:58:20 1970 + tm = {year=70, month=5, day=30, hour=18, min=58, sec=20, wday=2, yday=180}}, +{ts = 70679700, --Wed Mar 29 01:15:00 1972 + tm = {year=72, month=2, day=29, hour=1, min=15, sec=0, wday=3, yday=88}}, +{ts = 118231000, --Sun Sep 30 09:56:40 1973 + tm = {year=73, month=8, day=30, hour=9, min=56, sec=40, wday=0, yday=272}}, +{ts = 135663600, --Sat Apr 20 04:20:00 1974 + tm = {year=74, month=3, day=20, hour=4, min=20, sec=0, wday=6, yday=109}}, +{ts = 142740200, --Thu Jul 11 02:03:20 1974 + tm = {year=74, month=6, day=11, hour=2, min=3, sec=20, wday=4, yday=191}}, +{ts = 161467300, --Wed Feb 12 20:01:40 1975 + tm = {year=75, month=1, day=12, hour=20, min=1, sec=40, wday=3, yday=42}}, +{ts = 163538500, --Sat Mar 8 19:21:40 1975 + tm = {year=75, month=2, day=8, hour=19, min=21, sec=40, wday=6, yday=66}}, +{ts = 199525600, --Wed Apr 28 07:46:40 1976 + tm = {year=76, month=3, day=28, hour=7, min=46, sec=40, wday=3, yday=118}}, +{ts = 251219300, --Sat Dec 17 15:08:20 1977 + tm = {year=77, month=11, day=17, hour=15, min=8, sec=20, wday=6, yday=350}}, +{ts = 265027300, --Fri May 26 10:41:40 1978 + tm = {year=78, month=4, day=26, hour=10, min=41, sec=40, wday=5, yday=145}}, +{ts = 274951800, --Mon Sep 18 07:30:00 1978 + tm = {year=78, month=8, day=18, hour=7, min=30, sec=0, wday=1, yday=260}}, +{ts = 286861200, --Sat Feb 3 03:40:00 1979 + tm = {year=79, month=1, day=3, hour=3, min=40, sec=0, wday=6, yday=33}}, +{ts = 299892500, --Tue Jul 3 23:28:20 1979 + tm = {year=79, month=6, day=3, hour=23, min=28, sec=20, wday=2, yday=183}}, +{ts = 324488000, --Sun Apr 13 15:33:20 1980 + tm = {year=80, month=3, day=13, hour=15, min=33, sec=20, wday=0, yday=103}}, +{ts = 369450300, --Wed Sep 16 01:05:00 1981 + tm = {year=81, month=8, day=16, hour=1, min=5, sec=0, wday=3, yday=258}}, +{ts = 423042600, --Sun May 29 07:50:00 1983 + tm = {year=83, month=4, day=29, hour=7, min=50, sec=0, wday=0, yday=148}}, +{ts = 442891600, --Sat Jan 14 01:26:40 1984 + tm = {year=84, month=0, day=14, hour=1, min=26, sec=40, wday=6, yday=13}}, +{ts = 449968200, --Wed Apr 4 23:10:00 1984 + tm = {year=84, month=3, day=4, hour=23, min=10, sec=0, wday=3, yday=94}}, +{ts = 468609000, --Tue Nov 6 17:10:00 1984 + tm = {year=84, month=10, day=6, hour=17, min=10, sec=0, wday=2, yday=310}}, +{ts = 477670500, --Tue Feb 19 14:15:00 1985 + tm = {year=85, month=1, day=19, hour=14, min=15, sec=0, wday=2, yday=49}}, +{ts = 481295100, --Tue Apr 2 13:05:00 1985 + tm = {year=85, month=3, day=2, hour=13, min=5, sec=0, wday=2, yday=91}}, +{ts = 543517400, --Mon Mar 23 17:03:20 1987 + tm = {year=87, month=2, day=23, hour=17, min=3, sec=20, wday=1, yday=81}}, +{ts = 599439800, --Thu Dec 29 23:03:20 1988 + tm = {year=88, month=11, day=29, hour=23, min=3, sec=20, wday=4, yday=363}}, +{ts = 653808800, --Thu Sep 20 05:33:20 1990 + tm = {year=90, month=8, day=20, hour=5, min=33, sec=20, wday=4, yday=262}}, +{ts = 670723600, --Thu Apr 4 00:06:40 1991 + tm = {year=91, month=3, day=4, hour=0, min=6, sec=40, wday=4, yday=93}}, +{ts = 718274900, --Mon Oct 5 08:48:20 1992 + tm = {year=92, month=9, day=5, hour=8, min=48, sec=20, wday=1, yday=278}}, +{ts = 725351500, --Sat Dec 26 06:31:40 1992 + tm = {year=92, month=11, day=26, hour=6, min=31, sec=40, wday=6, yday=360}}, +{ts = 760389300, --Fri Feb 4 19:15:00 1994 + tm = {year=94, month=1, day=4, hour=19, min=15, sec=0, wday=5, yday=34}}, +{ts = 763841300, --Wed Mar 16 18:08:20 1994 + tm = {year=94, month=2, day=16, hour=18, min=8, sec=20, wday=3, yday=74}}, +{ts = 765135800, --Thu Mar 31 17:43:20 1994 + tm = {year=94, month=2, day=31, hour=17, min=43, sec=20, wday=4, yday=89}}, +{ts = 814930900, --Sun Oct 29 01:41:40 1995 + tm = {year=95, month=9, day=29, hour=1, min=41, sec=40, wday=0, yday=301}}, +{ts = 834003200, --Wed Jun 5 19:33:20 1996 + tm = {year=96, month=5, day=5, hour=19, min=33, sec=20, wday=3, yday=156}}, +{ts = 890270800, --Thu Mar 19 01:26:40 1998 + tm = {year=98, month=2, day=19, hour=1, min=26, sec=40, wday=4, yday=77}}, +{ts = 924445600, --Sun Apr 18 14:26:40 1999 + tm = {year=99, month=3, day=18, hour=14, min=26, sec=40, wday=0, yday=107}}, +{ts = 960864200, --Tue Jun 13 02:43:20 2000 + tm = {year=100, month=5, day=13, hour=2, min=43, sec=20, wday=2, yday=164}}, +{ts = 961123100, --Fri Jun 16 02:38:20 2000 + tm = {year=100, month=5, day=16, hour=2, min=38, sec=20, wday=5, yday=167}}, +{ts = 1014025000, --Mon Feb 18 09:36:40 2002 + tm = {year=102, month=1, day=18, hour=9, min=36, sec=40, wday=1, yday=48}}, +{ts = 1052514800, --Fri May 9 21:13:20 2003 + tm = {year=103, month=4, day=9, hour=21, min=13, sec=20, wday=5, yday=128}}, +{ts = 1088760800, --Fri Jul 2 09:33:20 2004 + tm = {year=104, month=6, day=2, hour=9, min=33, sec=20, wday=5, yday=183}}, +{ts = 1130184800, --Mon Oct 24 20:13:20 2005 + tm = {year=105, month=9, day=24, hour=20, min=13, sec=20, wday=1, yday=296}}, +{ts = 1182396300, --Thu Jun 21 03:25:00 2007 + tm = {year=107, month=5, day=21, hour=3, min=25, sec=0, wday=4, yday=171}}, +{ts = 1228566800, --Sat Dec 6 12:33:20 2008 + tm = {year=108, month=11, day=6, hour=12, min=33, sec=20, wday=6, yday=340}}, +{ts = 1281900200, --Sun Aug 15 19:23:20 2010 + tm = {year=110, month=7, day=15, hour=19, min=23, sec=20, wday=0, yday=226}}, +{ts = 1284057700, --Thu Sep 9 18:41:40 2010 + tm = {year=110, month=8, day=9, hour=18, min=41, sec=40, wday=4, yday=251}}, +{ts = 1291652100, --Mon Dec 6 16:15:00 2010 + tm = {year=110, month=11, day=6, hour=16, min=15, sec=0, wday=1, yday=339}}, +{ts = 1326776200, --Tue Jan 17 04:56:40 2012 + tm = {year=112, month=0, day=17, hour=4, min=56, sec=40, wday=2, yday=16}}, +{ts = 1382439700, --Tue Oct 22 11:01:40 2013 + tm = {year=113, month=9, day=22, hour=11, min=1, sec=40, wday=2, yday=294}}, +{ts = 1409796800, --Thu Sep 4 02:13:20 2014 + tm = {year=114, month=8, day=4, hour=2, min=13, sec=20, wday=4, yday=246}}, +{ts = 1451997500, --Tue Jan 5 12:38:20 2016 + tm = {year=116, month=0, day=5, hour=12, min=38, sec=20, wday=2, yday=4}}, +{ts = 1463216500, --Sat May 14 09:01:40 2016 + tm = {year=116, month=4, day=14, hour=9, min=1, sec=40, wday=6, yday=134}}, +{ts = 1499635100, --Sun Jul 9 21:18:20 2017 + tm = {year=117, month=6, day=9, hour=21, min=18, sec=20, wday=0, yday=189}}, +{ts = 1545460400, --Sat Dec 22 06:33:20 2018 + tm = {year=118, month=11, day=22, hour=6, min=33, sec=20, wday=6, yday=355}}, +{ts = 1555816400, --Sun Apr 21 03:13:20 2019 + tm = {year=119, month=3, day=21, hour=3, min=13, sec=20, wday=0, yday=110}}, +{ts = 1585072100, --Tue Mar 24 17:48:20 2020 + tm ={year=120, month=2, day=24, hour=17, min=48, sec=20, wday=2, yday=83}}, +{ts = 1622181100, --Fri May 28 05:51:40 2021 + tm = {year=121, month=4, day=28, hour=5, min=51, sec=40, wday=5, yday=147}}, +{ts = 1649451900, --Fri Apr 8 21:05:00 2022 + tm = {year=122, month=3, day=8, hour=21, min=5, sec=0, wday=5, yday=97}}, +{ts = 1663173600, --Wed Sep 14 16:40:00 2022 + tm = {year=122, month=8, day=14, hour=16, min=40, sec=0, wday=3, yday=256}}, +{ts = 1707272900, --Wed Feb 7 02:28:20 2024 + tm = {year=124, month=1, day=7, hour=2, min=28, sec=20, wday=3, yday=37}}, +{ts = 1769495200, --Tue Jan 27 06:26:40 2026 + tm = {year=126, month=0, day=27, hour=6, min=26, sec=40, wday=2, yday=26}}, +{ts = 1786582600, --Thu Aug 13 00:56:40 2026 + tm = {year=126, month=7, day=13, hour=0, min=56, sec=40, wday=4, yday=224}}, +{ts = 1831890100, --Wed Jan 19 10:21:40 2028 + tm = {year=128, month=0, day=19, hour=10, min=21, sec=40, wday=3, yday=18}}, +{ts = 1880735900, --Mon Aug 6 18:38:20 2029 + tm = {year=129, month=7, day=6, hour=18, min=38, sec=20, wday=1, yday=217}}, +{ts = 1916809300, --Sat Sep 28 07:01:40 2030 + tm = {year=130, month=8, day=28, hour=7, min=1, sec=40, wday=6, yday=270}}, +{ts = 1955299100, --Wed Dec 17 18:38:20 2031 + tm = {year=131, month=11, day=17, hour=18, min=38, sec=20, wday=3, yday=350}}, +{ts = 1975234400, --Wed Aug 4 12:13:20 2032 + tm = {year=132, month=7, day=4, hour=12, min=13, sec=20, wday=3, yday=216}}, +{ts = 1984554800, --Sat Nov 20 09:13:20 2032 + tm = {year=132, month=10, day=20, hour=9, min=13, sec=20, wday=6, yday=324}}, +{ts = 2023217200, --Fri Feb 10 20:46:40 2034 + tm = {year=134, month=1, day=10, hour=20, min=46, sec=40, wday=5, yday=40}}, +{ts = 2032882800, --Fri Jun 2 17:40:00 2034 + tm = {year=134, month=5, day=2, hour=17, min=40, sec=0, wday=5, yday=152}}, +{ts = 2080606700, --Fri Dec 7 02:18:20 2035 + tm = {year=135, month=11, day=7, hour=2, min=18, sec=20, wday=5, yday=340}}, +{ts = 2092429800, --Mon Apr 21 22:30:00 2036 + tm = {year=136, month=3, day=21, hour=22, min=30, sec=0, wday=1, yday=111}}, +{ts = 2131903647, --Wednesday July 22, 2037 19:27:27 (pm) in time zone UTC (UTC) + tm = {year=137, month=6, day=22, hour=19, min=27, sec=27, wday=3, yday=202}}, + +} + +local function check_field(entry, timestamp, name, got, exp) + if not got or not exp then + return false , string.format("entry: %d ts: %d error: key[%s] does not exist", entry, timestamp, name) + end + if got ~= exp then + return false, string.format("entry: %d ts: %d error: key[%s] mismatch got %d, expected %d", + entry, timestamp, name, got, exp) + end + return true +end +local passed = 0; +local ok = true; + +for _, test in ipairs(tests) do + local s_t = {} + s_t[1] = "" + local out = {} + timefns.gmtime(test.ts, out) + + for k, exp in pairs(test.tm) do + + local pass, err = check_field(passed, test.ts, k, out[k], exp) + if not pass then + ok = false + s_t[#s_t + 1] = err; + break + end + end + + if not ok then + s_t[1] = "FAIL" + rb.splash_scroller(10 * rb.HZ, table.concat(s_t, "\n")) + break; + end + passed = passed + 1 +end + +if ok then + rb.splash(rb.HZ * 5, tostring(passed) .. " / " .. #tests .. " timestamps match") +end diff --git a/apps/plugins/lua/rockaux.c b/apps/plugins/lua/rockaux.c index 6937b164d7..95986943c7 100644 --- a/apps/plugins/lua/rockaux.c +++ b/apps/plugins/lua/rockaux.c @@ -201,7 +201,7 @@ int strcoll(const char * str1, const char * str2) return rb->strcmp(str1, str2); } -#ifndef _WIN32 +#if 0 //ndef _WIN32 /* supplied by strfrtime.lua*/ struct tm * gmtime(const time_t *timep) { static struct tm time; diff --git a/apps/plugins/lua/rockconf.h b/apps/plugins/lua/rockconf.h index 0f97135340..87fec966db 100644 --- a/apps/plugins/lua/rockconf.h +++ b/apps/plugins/lua/rockconf.h @@ -66,6 +66,9 @@ int splash_scroller(int timeout, const char* str); #define strtoul rb->strtoul #define strstr rb->strstr #define yield() rb->yield() +#define gmtime_r rb->gmtime_r +#define mktime rb->mktime +#define get_time rb->get_time #endif /* _ROCKCONF_H_ */ diff --git a/apps/plugins/lua_scripts/time_date.lua b/apps/plugins/lua_scripts/time_date.lua new file mode 100644 index 0000000000..bf7f7bd5ec --- /dev/null +++ b/apps/plugins/lua_scripts/time_date.lua @@ -0,0 +1,48 @@ +--[[ + __________ __ ___. + Open \______ \ ____ ____ | | _\_ |__ _______ ___ + Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + \/ \/ \/ \/ \/ + $Id$ + + Copyright (C) 2026 William Wilgus + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + KIND, either express or implied. +]]-- + +if not os.time() then rb.splash(rb.HZ, "No Support!") return nil end + +if not os.date() then + require("strftime") -- needed for os.time.. +end + +local tmo_noblock = -1 +local ctx = 0 --CONTEXT_STD + +while rb.get_action(ctx, 50) == 0 do + rb.splash(0, os.date()) +end + +collectgarbage("collect") + +local used, allocd, free = rb.mem_stats() +local lu = collectgarbage("count") +local fmt = function(t, v) return string.format("%s: %d b\n", t, v) end + +-- this is how lua recommends to concat strings rather than .. +local s_t = {} +s_t[1] = os.date() +s_t[2] = "\n" +s_t[3] = fmt("Used ", used) +s_t[4] = fmt("Allocd ", allocd) +s_t[5] = fmt("Free ", free) +s_t[6] = "\nlua:\n" +s_t[7] = fmt("Used", lu * 1024) +s_t[8] = "\n\nNote that the rockbox used count is a high watermark\n" +rb.splash_scroller(10 * rb.HZ, table.concat(s_t))