Add datetime.lua

Move date and time related functions from util.lua
(and the statistics plugin) to a new datetime.lua.
reviewable/pr9876/r2
zwim 1 year ago committed by Frans de Jonge
parent 2e5284051a
commit 192a243b4d

@ -20,8 +20,8 @@ local UIManager = require("ui/uimanager")
local VerticalGroup = require("ui/widget/verticalgroup")
local VerticalSpan = require("ui/widget/verticalspan")
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local datetime = require("datetime")
local logger = require("logger")
local util = require("util")
local T = require("ffi/util").template
local _ = require("gettext")
local C_ = _.pgettext
@ -229,7 +229,7 @@ local footerTextGeneratorMap = {
time = function(footer)
local symbol_type = footer.settings.item_prefix
local prefix = symbol_prefix[symbol_type].time
local clock = util.secondsToHour(os.time(), G_reader_settings:isTrue("twelve_hour_clock"))
local clock = datetime.secondsToHour(os.time(), G_reader_settings:isTrue("twelve_hour_clock"))
if not prefix then
return clock
else
@ -2098,7 +2098,7 @@ function ReaderFooter:getDataFromStatistics(title, pages)
local average_time_per_page = self:getAvgTimePerPage()
local user_duration_format = G_reader_settings:readSetting("duration_format", "classic")
if average_time_per_page then
sec = util.secondsToClockDuration(user_duration_format, pages * average_time_per_page, true)
sec = datetime.secondsToClockDuration(user_duration_format, pages * average_time_per_page, true)
end
return title .. sec
end

@ -0,0 +1,296 @@
--[[--
This module contains date translations and helper functions for the KOReader frontend.
]]
local BaseUtil = require("ffi/util")
local _ = require("gettext")
local C_ = _.pgettext
local T = BaseUtil.template
local datetime = {}
datetime.weekDays = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" } -- in Lua wday order
datetime.shortMonthTranslation = {
["Jan"] = _("Jan"),
["Feb"] = _("Feb"),
["Mar"] = _("Mar"),
["Apr"] = _("Apr"),
["May"] = _("May"),
["Jun"] = _("Jun"),
["Jul"] = _("Jul"),
["Aug"] = _("Aug"),
["Sep"] = _("Sep"),
["Oct"] = _("Oct"),
["Nov"] = _("Nov"),
["Dec"] = _("Dec"),
}
datetime.longMonthTranslation = {
["January"] = _("January"),
["February"] = _("February"),
["March"] = _("March"),
["April"] = _("April"),
["May"] = _("May"),
["June"] = _("June"),
["July"] = _("July"),
["August"] = _("August"),
["September"] = _("September"),
["October"] = _("October"),
["November"] = _("November"),
["December"] = _("December"),
}
datetime.shortDayOfWeekTranslation = {
["Mon"] = _("Mon"),
["Tue"] = _("Tue"),
["Wed"] = _("Wed"),
["Thu"] = _("Thu"),
["Fri"] = _("Fri"),
["Sat"] = _("Sat"),
["Sun"] = _("Sun"),
}
datetime.shortDayOfWeekToLongTranslation = {
["Mon"] = _("Monday"),
["Tue"] = _("Tuesday"),
["Wed"] = _("Wednesday"),
["Thu"] = _("Thursday"),
["Fri"] = _("Friday"),
["Sat"] = _("Saturday"),
["Sun"] = _("Sunday"),
}
--[[--
Converts seconds to a clock string.
Source: <a href="https://gist.github.com/jesseadams/791673">https://gist.github.com/jesseadams/791673</a>
]]
---- @int seconds number of seconds
---- @bool withoutSeconds if true 00:00, if false 00:00:00
---- @treturn string clock string in the form of 00:00 or 00:00:00
function datetime.secondsToClock(seconds, withoutSeconds, withDays)
seconds = tonumber(seconds)
if not seconds then
if withoutSeconds then
return "--:--"
else
return "--:--:--"
end
elseif seconds == 0 or seconds ~= seconds then
if withoutSeconds then
return "00:00"
else
return "00:00:00"
end
else
local round = withoutSeconds and require("optmath").round or function(n) return n end
local days = "0"
local hours
if withDays then
days = string.format("%d", seconds * (1/(24*3600))) -- implicit math.floor for string.format
hours = string.format("%02d", (seconds * (1/3600)) % 24)
else
hours = string.format("%02d", seconds * (1/3600))
end
local mins = string.format("%02d", round(seconds % 3600 * (1/60)))
if withoutSeconds then
if mins == "60" then
-- Can only happen because of rounding, which only happens if withoutSeconds...
mins = string.format("%02d", 0)
hours = string.format("%02d", hours + 1)
end
return (days ~= "0" and (days .. "d") or "") .. hours .. ":" .. mins
else
local secs = string.format("%02d", seconds % 60)
return (days ~= "0" and (days .. "d") or "") .. hours .. ":" .. mins .. ":" .. secs
end
end
end
--- Converts seconds to a period of time string.
---- @int seconds number of seconds
---- @bool withoutSeconds if true 1h30', if false 1h30'10"
---- @bool hmsFormat, if true format 1h30m10s
---- @bool withDays, if true format 1d12h30m10s
---- @treturn string clock string in the form of 1h30'10" or 1h30m10s
function datetime.secondsToHClock(seconds, withoutSeconds, hmsFormat, withDays, compact)
local SECONDS_SYMBOL = "\""
seconds = tonumber(seconds)
if seconds == 0 then
if withoutSeconds then
if hmsFormat then
return T(_("%1m"), "0")
else
return "0'"
end
else
if hmsFormat then
return T(C_("Time", "%1s"), "0")
else
return "0" .. SECONDS_SYMBOL
end
end
elseif seconds < 60 then
if withoutSeconds and seconds < 30 then
if hmsFormat then
return T(C_("Time", "%1m"), "0")
else
return "0'"
end
elseif withoutSeconds and seconds >= 30 then
if hmsFormat then
return T(C_("Time", "%1m"), "1")
else
return "1'"
end
else
if hmsFormat then
if compact then
return T(C_("Time", "%1s"), string.format("%d", seconds))
else
return T(C_("Time", "%1m%2s"), "0", string.format("%02d", seconds))
end
else
if compact then
return string.format("%d", seconds) .. SECONDS_SYMBOL
else
return "0'" .. string.format("%02d", seconds) .. SECONDS_SYMBOL
end
end
end
else
local time_string = datetime.secondsToClock(seconds, withoutSeconds, withDays)
if withoutSeconds then
time_string = time_string .. ":"
end
time_string = time_string:gsub(":", C_("Time", "h"), 1)
time_string = time_string:gsub(":", C_("Time", "m"), 1)
time_string = time_string:gsub("^00" .. C_("Time", "h"), "") -- delete leading "00h"
time_string = time_string:gsub("^00" .. C_("Time", "m"), "") -- delete leading "00m"
if time_string:find("^0%d") then
time_string = time_string:gsub("^0", "") -- delete leading "0"
end
if withoutSeconds and time_string == "" then
time_string = "0" .. C_("Time", "m")
end
if hmsFormat then
return withoutSeconds and time_string or (time_string .. C_("Time", "s"))
else
time_string = time_string:gsub(C_("Time", "m"), "'") -- replace m with '
return withoutSeconds and time_string or (time_string .. SECONDS_SYMBOL)
end
end
end
--- Converts seconds to a clock type (classic or modern), based on the given format preference
--- "Classic" format calls secondsToClock, and "Modern" format calls secondsToHClock
---- @string Either "modern" for 1h30'10" or "classic" for 1:30:10
---- @bool withoutSeconds if true 1h30' or 1h30m, if false 1h30'10" or 1h30m10s
---- @bool hmsFormat, modern format only, if true format 1h30m or 1h30m10s
---- @bool withDays, if hours>=24 include days in clock string 1d12h10m10s
---- @bool compact, if set removes all leading zeros (incl. units if necessary)
---- @treturn string clock string in the specific format of 1h30', 1h30'10" resp. 1h30m, 1h30m10s
function datetime.secondsToClockDuration(format, seconds, withoutSeconds, hmsFormat, withDays, compact)
if format == "modern" then
return datetime.secondsToHClock(seconds, withoutSeconds, hmsFormat, withDays, compact)
else
-- Assume "classic" to give safe default
return datetime.secondsToClock(seconds, withoutSeconds, withDays)
end
end
if jit.os == "Windows" then
--- Converts timestamp to an hour string
---- @int seconds number of seconds
---- @bool twelve_hour_clock
---- @treturn string hour string
---- @note: The MS CRT doesn't support either %l & %k, or the - format modifier (as they're not technically C99 or POSIX).
---- They are otherwise supported on Linux, BSD & Bionic, so, just special-case Windows...
---- We *could* arguably feed the os.date output to gsub("^0(%d)(.*)$", "%1%2"), but, while unlikely,
---- it's conceivable that a translator would put something other that the hour at the front of the string ;).
function datetime.secondsToHour(seconds, twelve_hour_clock)
if twelve_hour_clock then
if os.date("%p", seconds) == "AM" then
-- @translators This is the time in the morning using a 12-hour clock (%I is the hour, %M the minute).
return os.date(_("%I:%M AM"), seconds)
else
-- @translators This is the time in the afternoon using a 12-hour clock (%I is the hour, %M the minute).
return os.date(_("%I:%M PM"), seconds)
end
else
-- @translators This is the time using a 24-hour clock (%H is the hour, %M the minute).
return os.date(_("%H:%M"), seconds)
end
end
else
function datetime.secondsToHour(seconds, twelve_hour_clock, pad_with_spaces)
if twelve_hour_clock then
if os.date("%p", seconds) == "AM" then
if pad_with_spaces then
-- @translators This is the time in the morning using a 12-hour clock (%_I is the hour, %M the minute).
return os.date(_("%_I:%M AM"), seconds)
else
-- @translators This is the time in the morning using a 12-hour clock (%-I is the hour, %M the minute).
return os.date(_("%-I:%M AM"), seconds)
end
else
if pad_with_spaces then
-- @translators This is the time in the afternoon using a 12-hour clock (%_I is the hour, %M the minute).
return os.date(_("%_I:%M PM"), seconds)
else
-- @translators This is the time in the afternoon using a 12-hour clock (%-I is the hour, %M the minute).
return os.date(_("%-I:%M PM"), seconds)
end
end
else
if pad_with_spaces then
-- @translators This is the time using a 24-hour clock (%_H is the hour, %M the minute).
return os.date(_("%_H:%M"), seconds)
else
-- @translators This is the time using a 24-hour clock (%-H is the hour, %M the minute).
return os.date(_("%-H:%M"), seconds)
end
end
end
end
--- Converts timestamp to a date string
---- @int seconds number of seconds
---- @use_locale if true allows to translate the date-time string, if false return "%Y-%m-%d time"
---- @treturn string date string
function datetime.secondsToDate(seconds, use_locale)
seconds = seconds or os.time()
if use_locale then
local wday = os.date("%a", seconds)
local month = os.date("%b", seconds)
local day = os.date("%d", seconds)
local year = os.date("%Y", seconds)
-- @translators Use the following placeholders in the desired order: %1 name of day, %2 name of month, %3 day, %4 year
return T(C_("Date string", "%1 %2 %3 %4"),
datetime.shortDayOfWeekTranslation[wday], datetime.shortMonthTranslation[month], day, year)
else
-- @translators This is the date (%Y is the year, %m the month, %d the day)
return os.date(C_("Date string", "%Y-%m-%d"), seconds)
end
end
--- Converts timestamp to a date+time string
---- @int seconds number of seconds
---- @bool twelve_hour_clock
---- @use_locale if true allows to translate the date-time string, if false return "%Y-%m-%d time"
---- @treturn string date+time
function datetime.secondsToDateTime(seconds, twelve_hour_clock, use_locale)
seconds = seconds or os.time()
local BD = require("ui/bidi")
local date_string = datetime.secondsToDate(seconds, use_locale)
local time_string = datetime.secondsToHour(seconds, twelve_hour_clock, not use_locale)
-- @translators Use the following placeholders in the desired order: %1 date, %2 time
local message_text = T(C_("Date string", "%1 %2"), BD.wrap(date_string), BD.wrap(time_string))
return message_text
end
return datetime

@ -1,5 +1,6 @@
local DataStorage = require("datastorage")
local DocSettings = require("docsettings")
local datetime = require("datetime")
local dump = require("dump")
local ffiutil = require("ffi/util")
local util = require("util")
@ -41,7 +42,7 @@ local function buildEntry(input_time, input_file)
-- we fallback to if no sidecar file)
last_read_ts = DocSettings:getLastSaveTime(file_path) or input_time
end
return util.secondsToDate(last_read_ts, G_reader_settings:isTrue("twelve_hour_clock"))
return datetime.secondsToDateTime(last_read_ts, G_reader_settings:isTrue("twelve_hour_clock"))
end,
select_enabled_func = function()
return lfs.attributes(file_path, "mode") == "file"

@ -91,9 +91,9 @@ common_settings.time = {
sub_item_table = {
{
text_func = function()
local util = require('util')
local datetime = require("datetime")
-- sample text shows 1:23:45
local duration_format_str = util.secondsToClockDuration("classic", 5025, false)
local duration_format_str = datetime.secondsToClockDuration("classic", 5025, false)
return T(_("Classic (%1)"), duration_format_str)
end,
checked_func = function()
@ -106,9 +106,9 @@ common_settings.time = {
},
{
text_func = function()
local util = require('util')
local datetime = require("datetime")
-- sample text shows 1h23m45s
local duration_format_str = util.secondsToClockDuration("modern", 5025, false)
local duration_format_str = datetime.secondsToClockDuration("modern", 5025, false)
return T(_("Modern (%1)"), duration_format_str)
end,
checked_func = function()

@ -19,6 +19,7 @@ local TopContainer = require("ui/widget/container/topcontainer")
local UIManager = require("ui/uimanager")
local VerticalGroup = require("ui/widget/verticalgroup")
local VerticalSpan = require("ui/widget/verticalspan")
local datetime = require("datetime")
local ffiUtil = require("ffi/util")
local lfs = require("libs/libkoreader-lfs")
local logger = require("logger")
@ -130,7 +131,7 @@ function Screensaver:_calcAverageTimeForPages(pages)
-- Compare average_time_per_page against itself to make sure it's not nan
if average_time_per_page and average_time_per_page == average_time_per_page and pages then
local user_duration_format = G_reader_settings:readSetting("duration_format", "classic")
sec = util.secondsToClockDuration(user_duration_format, pages * average_time_per_page, true)
sec = datetime.secondsToClockDuration(user_duration_format, pages * average_time_per_page, true)
end
return sec
end

@ -24,6 +24,7 @@ local ToggleSwitch = require("ui/widget/toggleswitch")
local UIManager = require("ui/uimanager")
local VerticalGroup = require("ui/widget/verticalgroup")
local VerticalSpan = require("ui/widget/verticalspan")
local datetime = require("datetime")
local util = require("util")
local _ = require("gettext")
local Screen = Device.screen
@ -144,7 +145,7 @@ end
function BookStatusWidget:getStatHours()
if stats_book.time then
local user_duration_format = G_reader_settings:readSetting("duration_format", "classic")
return util.secondsToClockDuration(user_duration_format, stats_book.time, false)
return datetime.secondsToClockDuration(user_duration_format, stats_book.time, false)
else
return _("N/A")
end

@ -27,7 +27,7 @@ local UIManager = require("ui/uimanager")
local UnderlineContainer = require("ui/widget/container/underlinecontainer")
local VerticalGroup = require("ui/widget/verticalgroup")
local VerticalSpan = require("ui/widget/verticalspan")
local util = require("util")
local datetime = require("datetime")
local getMenuText = require("ui/widget/menu").getMenuText
local _ = require("gettext")
local T = require("ffi/util").template
@ -704,7 +704,7 @@ function TouchMenu:updateItems()
self.page_info_left_chev:enableDisable(self.page > 1)
self.page_info_right_chev:enableDisable(self.page < self.page_num)
local time_info_txt = util.secondsToHour(os.time(), G_reader_settings:isTrue("twelve_hour_clock"))
local time_info_txt = datetime.secondsToHour(os.time(), G_reader_settings:isTrue("twelve_hour_clock"))
local powerd = Device:getPowerDevice()
if Device:hasBattery() then
local batt_lvl = powerd:getCapacity()

@ -101,219 +101,6 @@ function util.gsplit(str, pattern, capture, capture_empty_entity)
end)
end
-- Stupid helper for the duration stuff
local function passthrough(n)
return n
end
--[[--
Converts seconds to a clock string.
Source: <a href="https://gist.github.com/jesseadams/791673">https://gist.github.com/jesseadams/791673</a>
]]
---- @int seconds number of seconds
---- @bool withoutSeconds if true 00:00, if false 00:00:00
---- @treturn string clock string in the form of 00:00 or 00:00:00
function util.secondsToClock(seconds, withoutSeconds, withDays)
seconds = tonumber(seconds)
if not seconds then
if withoutSeconds then
return "--:--"
else
return "--:--:--"
end
elseif seconds == 0 or seconds ~= seconds then
if withoutSeconds then
return "00:00"
else
return "00:00:00"
end
else
local round = withoutSeconds and require("optmath").round or passthrough
local days = "0"
local hours
if withDays then
days = string.format("%d", seconds * (1/(24*3600))) -- implicit math.floor for string.format
hours = string.format("%02d", (seconds * (1/3600)) % 24)
else
hours = string.format("%02d", seconds * (1/3600))
end
local mins = string.format("%02d", round(seconds % 3600 * (1/60)))
if withoutSeconds then
if mins == "60" then
-- Can only happen because of rounding, which only happens if withoutSeconds...
mins = string.format("%02d", 0)
hours = string.format("%02d", hours + 1)
end
return (days ~= "0" and (days .. "d") or "") .. hours .. ":" .. mins
else
local secs = string.format("%02d", seconds % 60)
return (days ~= "0" and (days .. "d") or "") .. hours .. ":" .. mins .. ":" .. secs
end
end
end
--- Converts seconds to a period of time string.
---- @int seconds number of seconds
---- @bool withoutSeconds if true 1h30', if false 1h30'10"
---- @bool hmsFormat, if true format 1h30m10s
---- @bool withDays, if true format 1d12h30m10s
---- @treturn string clock string in the form of 1h30'10" or 1h30m10s
function util.secondsToHClock(seconds, withoutSeconds, hmsFormat, withDays, compact)
local SECONDS_SYMBOL = "\""
seconds = tonumber(seconds)
if seconds == 0 then
if withoutSeconds then
if hmsFormat then
return T(_("%1m"), "0")
else
return "0'"
end
else
if hmsFormat then
return T(C_("Time", "%1s"), "0")
else
return "0" .. SECONDS_SYMBOL
end
end
elseif seconds < 60 then
if withoutSeconds and seconds < 30 then
if hmsFormat then
return T(C_("Time", "%1m"), "0")
else
return "0'"
end
elseif withoutSeconds and seconds >= 30 then
if hmsFormat then
return T(C_("Time", "%1m"), "1")
else
return "1'"
end
else
if hmsFormat then
if compact then
return T(C_("Time", "%1s"), string.format("%d", seconds))
else
return T(C_("Time", "%1m%2s"), "0", string.format("%02d", seconds))
end
else
if compact then
return string.format("%d", seconds) .. SECONDS_SYMBOL
else
return "0'" .. string.format("%02d", seconds) .. SECONDS_SYMBOL
end
end
end
else
local time_string = util.secondsToClock(seconds, withoutSeconds, withDays)
if withoutSeconds then
time_string = time_string .. ":"
end
time_string = time_string:gsub(":", C_("Time", "h"), 1)
time_string = time_string:gsub(":", C_("Time", "m"), 1)
time_string = time_string:gsub("^00" .. C_("Time", "h"), "") -- delete leading "00h"
time_string = time_string:gsub("^00" .. C_("Time", "m"), "") -- delete leading "00m"
if time_string:find("^0%d") then
time_string = time_string:gsub("^0", "") -- delete leading "0"
end
if withoutSeconds and time_string == "" then
time_string = "0" .. C_("Time", "m")
end
if hmsFormat then
return withoutSeconds and time_string or (time_string .. C_("Time", "s"))
else
time_string = time_string:gsub(C_("Time", "m"), "'") -- replace m with '
return withoutSeconds and time_string or (time_string .. SECONDS_SYMBOL)
end
end
end
--- Converts seconds to a clock type (classic or modern), based on the given format preference
--- "Classic" format calls secondsToClock, and "Modern" format calls secondsToHClock
---- @string Either "modern" for 1h30'10" or "classic" for 1:30:10
---- @bool withoutSeconds if true 1h30' or 1h30m, if false 1h30'10" or 1h30m10s
---- @bool hmsFormat, modern format only, if true format 1h30m or 1h30m10s
---- @bool withDays, if hours>=24 include days in clock string 1d12h10m10s
---- @bool compact, if set removes all leading zeros (incl. units if necessary)
---- @treturn string clock string in the specific format of 1h30', 1h30'10" resp. 1h30m, 1h30m10s
function util.secondsToClockDuration(format, seconds, withoutSeconds, hmsFormat, withDays, compact)
if format == "modern" then
return util.secondsToHClock(seconds, withoutSeconds, hmsFormat, withDays, compact)
else
-- Assume "classic" to give safe default
return util.secondsToClock(seconds, withoutSeconds, withDays)
end
end
if jit.os == "Windows" then
--- Converts timestamp to an hour string
---- @int seconds number of seconds
---- @bool twelve_hour_clock
---- @treturn string hour string
---- @note: The MS CRT doesn't support either %l & %k, or the - format modifier (as they're not technically C99 or POSIX).
---- They are otherwise supported on Linux, BSD & Bionic, so, just special-case Windows...
---- We *could* arguably feed the os.date output to gsub("^0(%d)(.*)$", "%1%2"), but, while unlikely,
---- it's conceivable that a translator would put something other that the hour at the front of the string ;).
function util.secondsToHour(seconds, twelve_hour_clock)
if twelve_hour_clock then
if os.date("%p", seconds) == "AM" then
-- @translators This is the time in the morning using a 12-hour clock (%I is the hour, %M the minute).
return os.date(_("%I:%M AM"), seconds)
else
-- @translators This is the time in the afternoon using a 12-hour clock (%I is the hour, %M the minute).
return os.date(_("%I:%M PM"), seconds)
end
else
-- @translators This is the time using a 24-hour clock (%H is the hour, %M the minute).
return os.date(_("%H:%M"), seconds)
end
end
else
function util.secondsToHour(seconds, twelve_hour_clock, pad_with_spaces)
if twelve_hour_clock then
if os.date("%p", seconds) == "AM" then
if pad_with_spaces then
-- @translators This is the time in the morning using a 12-hour clock (%_I is the hour, %M the minute).
return os.date(_("%_I:%M AM"), seconds)
else
-- @translators This is the time in the morning using a 12-hour clock (%-I is the hour, %M the minute).
return os.date(_("%-I:%M AM"), seconds)
end
else
if pad_with_spaces then
-- @translators This is the time in the afternoon using a 12-hour clock (%_I is the hour, %M the minute).
return os.date(_("%_I:%M PM"), seconds)
else
-- @translators This is the time in the afternoon using a 12-hour clock (%-I is the hour, %M the minute).
return os.date(_("%-I:%M PM"), seconds)
end
end
else
if pad_with_spaces then
-- @translators This is the time using a 24-hour clock (%_H is the hour, %M the minute).
return os.date(_("%_H:%M"), seconds)
else
-- @translators This is the time using a 24-hour clock (%-H is the hour, %M the minute).
return os.date(_("%-H:%M"), seconds)
end
end
end
end
--- Converts timestamp to a date string
---- @int seconds number of seconds
---- @bool twelve_hour_clock
---- @treturn string date string
function util.secondsToDate(seconds, twelve_hour_clock)
local BD = require("ui/bidi")
-- In order to keep stuff aligned, we'll want to *keep* the padding, but using blanks instead of zeroes.
local time = util.secondsToHour(seconds, twelve_hour_clock, true)
-- @translators This is the date (%Y is the year, %m the month, %d the day)
local day = os.date(_("%Y-%m-%d"), seconds)
return BD.wrap(day) .. " " .. BD.wrap(time)
end
--[[--
Compares values in two different tables.

@ -10,8 +10,8 @@ local SpinWidget = require("ui/widget/spinwidget")
local UIManager = require("ui/uimanager")
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local TrapWidget = require("ui/widget/trapwidget")
local datetime = require("datetime")
local time = require("ui/time")
local util = require("util")
local _ = require("gettext")
local C_ = _.pgettext
local Powerd = Device.powerd
@ -55,7 +55,7 @@ function AutoDim:getAutoDimMenu()
text_func = function()
return self.autodim_starttime_m <= 0 and _("Idle time for dimmer") or
T(_("Idle time for dimmer: %1"),
util.secondsToClockDuration("modern", self.autodim_starttime_m * 60, false, true, false, true))
datetime.secondsToClockDuration("modern", self.autodim_starttime_m * 60, false, true, false, true))
end,
checked_func = function() return self.autodim_starttime_m > 0 end,
callback = function(touchmenu_instance)
@ -94,7 +94,7 @@ function AutoDim:getAutoDimMenu()
{
text_func = function()
return T(_("Dimmer duration: %1"),
util.secondsToClockDuration("modern", self.autodim_duration_s, false, true, false, true))
datetime.secondsToClockDuration("modern", self.autodim_duration_s, false, true, false, true))
end,
enabled_func = function() return self.autodim_starttime_m > 0 end,
callback = function(touchmenu_instance)

@ -6,15 +6,15 @@ if not Device:canSuspend() then
end
local Event = require("ui/event")
local Math = require("optmath")
local NetworkMgr = require("ui/network/manager")
local PluginShare = require("pluginshare")
local UIManager = require("ui/uimanager")
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local datetime = require("datetime")
local logger = require("logger")
local util = require("util")
local time = require("ui/time")
local _ = require("gettext")
local Math = require("optmath")
local T = require("ffi/util").template
local default_autoshutdown_timeout_seconds = 3*24*60*60 -- three days
@ -427,14 +427,14 @@ function AutoSuspend:pickTimeoutValue(touchmenu_instance, title, info, setting,
self:_start()
end
if touchmenu_instance then touchmenu_instance:updateItems() end
local time_string = util.secondsToClockDuration("modern", self[setting],
local time_string = datetime.secondsToClockDuration("modern", self[setting],
time_scale == 2 or time_scale == 1, true, true)
UIManager:show(InfoMessage:new{
text = T(_("%1: %2"), title, time_string),
timeout = 3,
})
end,
default_value = util.secondsToClockDuration("modern", default_value,
default_value = datetime.secondsToClockDuration("modern", default_value,
time_scale == 2 or time_scale == 1, true, true),
default_callback = function()
local day, hour, min, sec -- luacheck: ignore 431
@ -481,7 +481,7 @@ function AutoSuspend:addToMainMenu(menu_items)
end,
text_func = function()
if self.auto_suspend_timeout_seconds and self.auto_suspend_timeout_seconds > 0 then
local time_string = util.secondsToClockDuration("modern",
local time_string = datetime.secondsToClockDuration("modern",
self.auto_suspend_timeout_seconds, true, true, true)
return T(_("Autosuspend timeout: %1"), time_string)
else
@ -507,7 +507,7 @@ function AutoSuspend:addToMainMenu(menu_items)
end,
text_func = function()
if self.autoshutdown_timeout_seconds and self.autoshutdown_timeout_seconds > 0 then
local time_string = util.secondsToClockDuration("modern", self.autoshutdown_timeout_seconds,
local time_string = datetime.secondsToClockDuration("modern", self.autoshutdown_timeout_seconds,
true, true, true)
return T(_("Autoshutdown timeout: %1"), time_string)
else
@ -546,7 +546,7 @@ Upon user input, the device needs a certain amount of time to wake up. Generally
end,
text_func = function()
if self.auto_standby_timeout_seconds and self.auto_standby_timeout_seconds > 0 then
local time_string = util.secondsToClockDuration("modern", self.auto_standby_timeout_seconds,
local time_string = datetime.secondsToClockDuration("modern", self.auto_standby_timeout_seconds,
false, true, true, true)
return T(_("Autostandby timeout: %1"), time_string)
else

@ -3,9 +3,9 @@ local Event = require("ui/event")
local PluginShare = require("pluginshare")
local UIManager = require("ui/uimanager")
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local datetime = require("datetime")
local logger = require("logger")
local time = require("ui/time")
local util = require("util")
local _ = require("gettext")
local T = require("ffi/util").template
@ -67,7 +67,7 @@ function AutoTurn:_start()
local text
if self.autoturn_distance == 1 then
local time_string = util.secondsToClockDuration("modern", self.autoturn_sec, false, true, true, true)
local time_string = datetime.secondsToClockDuration("modern", self.autoturn_sec, false, true, true, true)
text = T(_("Autoturn is now active and will automatically turn the page every %1."), time_string)
else
text = T(_("Autoturn is now active and will automatically scroll %1 % of the page every %2 seconds."),
@ -141,7 +141,7 @@ function AutoTurn:addToMainMenu(menu_items)
menu_items.autoturn = {
sorting_hint = "navi",
text_func = function()
local time_string = util.secondsToClockDuration("modern", self.autoturn_sec, false, true, true, true)
local time_string = datetime.secondsToClockDuration("modern", self.autoturn_sec, false, true, true, true)
return self:_enabled() and T(_("Autoturn: %1"), time_string) or _("Autoturn")
end,
checked_func = function() return self:_enabled() end,

@ -27,7 +27,7 @@ local C_ = _.pgettext
local Powerd = Device.powerd
local T = FFIUtil.template
local Screen = require("device").screen
local util = require("util")
local datetime = require("datetime")
local activate_sun = 1
local activate_schedule = 2
@ -519,7 +519,7 @@ function AutoWarmth:hoursToClock(hours)
if hours then
hours = hours % 24 * 3600 + 0.01 -- round up, due to reduced precision in settings.reader.lua
end
return util.secondsToClock(hours, self.easy_mode)
return datetime.secondsToClock(hours, self.easy_mode)
end
function AutoWarmth:addToMainMenu(menu_items)

@ -6,9 +6,9 @@ local LuaSettings = require("luasettings")
local PowerD = require("device"):getPowerDevice()
local UIManager = require("ui/uimanager")
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local datetime = require("datetime")
local dbg = require("dbg")
local time = require("ui/time")
local util = require("util")
local _ = require("gettext")
local T = require("ffi/util").template
@ -81,7 +81,7 @@ end
local function duration(number)
local duration_fmt = G_reader_settings:readSetting("duration_format", "classic")
return type(number) ~= "number" and number or
util.secondsToClockDuration(duration_fmt, number, true, true, true)
datetime.secondsToClockDuration(duration_fmt, number, true, true, true)
end
function Usage:dump(kv_pairs, id)

@ -3,7 +3,7 @@ local InfoMessage = require("ui/widget/infomessage")
local UIManager = require("ui/uimanager")
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local logger = require("logger")
local util = require("util")
local datetime = require("datetime")
local _ = require("gettext")
local T = require("ffi/util").template
@ -70,7 +70,7 @@ function ReadTimer:addToMainMenu(menu_items)
if self:scheduled() then
local user_duration_format = G_reader_settings:readSetting("duration_format")
return T(_("Read timer (%1)"),
util.secondsToClockDuration(user_duration_format, self:remaining(), false))
datetime.secondsToClockDuration(user_duration_format, self:remaining(), false))
else
return _("Read timer")
end
@ -107,7 +107,7 @@ function ReadTimer:addToMainMenu(menu_items)
-- @translators %1:%2 is a clock time (HH:MM), %3 is a duration
text = T(_("Timer set for %1:%2.\n\nThat's %3 from now."),
string.format("%02d", time.hour), string.format("%02d", time.min),
util.secondsToClockDuration(user_duration_format, seconds, false)),
datetime.secondsToClockDuration(user_duration_format, seconds, false)),
timeout = 5,
})
else
@ -151,7 +151,7 @@ function ReadTimer:addToMainMenu(menu_items)
UIManager:show(InfoMessage:new{
-- @translators This is a duration
text = T(_("Timer will expire in %1."),
util.secondsToClockDuration(user_duration_format, seconds, true)),
datetime.secondsToClockDuration(user_duration_format, seconds, true)),
timeout = 5,
})
remain_time = {time.hour, time.min}

@ -1,3 +1,4 @@
local BD = require("ui/bidi")
local Blitbuffer = require("ffi/blitbuffer")
local BottomContainer = require("ui/widget/container/bottomcontainer")

@ -17,6 +17,7 @@ local SQ3 = require("lua-ljsqlite3/init")
local SyncService = require("frontend/apps/cloudstorage/syncservice")
local UIManager = require("ui/uimanager")
local Widget = require("ui/widget/widget")
local datetime = require("datetime")
local lfs = require("libs/libkoreader-lfs")
local logger = require("logger")
local util = require("util")
@ -75,43 +76,6 @@ local ReaderStatistics = Widget:extend{
data = nil, -- table
}
local weekDays = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" } -- in Lua wday order
local shortDayOfWeekTranslation = {
["Mon"] = _("Mon"),
["Tue"] = _("Tue"),
["Wed"] = _("Wed"),
["Thu"] = _("Thu"),
["Fri"] = _("Fri"),
["Sat"] = _("Sat"),
["Sun"] = _("Sun"),
}
local longDayOfWeekTranslation = {
["Mon"] = _("Monday"),
["Tue"] = _("Tuesday"),
["Wed"] = _("Wednesday"),
["Thu"] = _("Thursday"),
["Fri"] = _("Friday"),
["Sat"] = _("Saturday"),
["Sun"] = _("Sunday"),
}
local monthTranslation = {
["January"] = _("January"),
["February"] = _("February"),
["March"] = _("March"),
["April"] = _("April"),
["May"] = _("May"),
["June"] = _("June"),
["July"] = _("July"),
["August"] = _("August"),
["September"] = _("September"),
["October"] = _("October"),
["November"] = _("November"),
["December"] = _("December"),
}
function ReaderStatistics:isDocless()
return self.ui == nil or self.ui.document == nil or self.ui.document.is_pic == true
end
@ -1023,26 +987,26 @@ The max value ensures a page you stay on for a long time (because you fell aslee
{
text_func = function()
return T(_("Calendar weeks start on %1"),
longDayOfWeekTranslation[weekDays[self.settings.calendar_start_day_of_week]])
datetime.shortDayOfWeekToLongTranslation[datetime.weekDays[self.settings.calendar_start_day_of_week]])
end,
sub_item_table = {
{ -- Friday (Bangladesh and Maldives)
text = longDayOfWeekTranslation[weekDays[6]],
text = datetime.shortDayOfWeekToLongTranslation[datetime.weekDays[6]],
checked_func = function() return self.settings.calendar_start_day_of_week == 6 end,
callback = function() self.settings.calendar_start_day_of_week = 6 end
},
{ -- Saturday (some Middle East countries)
text = longDayOfWeekTranslation[weekDays[7]],
text = datetime.shortDayOfWeekToLongTranslation[datetime.weekDays[7]],
checked_func = function() return self.settings.calendar_start_day_of_week == 7 end,
callback = function() self.settings.calendar_start_day_of_week = 7 end
},
{ -- Sunday
text = longDayOfWeekTranslation[weekDays[1]],
text = datetime.shortDayOfWeekToLongTranslation[datetime.weekDays[1]],
checked_func = function() return self.settings.calendar_start_day_of_week == 1 end,
callback = function() self.settings.calendar_start_day_of_week = 1 end
},
{ -- Monday
text = longDayOfWeekTranslation[weekDays[2]],
text = datetime.shortDayOfWeekToLongTranslation[datetime.weekDays[2]],
checked_func = function() return self.settings.calendar_start_day_of_week == 2 end,
callback = function() self.settings.calendar_start_day_of_week = 2 end
},
@ -1491,27 +1455,27 @@ function ReaderStatistics:getCurrentStat()
return {
-- Global statistics (may consider other books than current book)
-- since last resume
{ _("Time spent reading this session"), util.secondsToClockDuration(user_duration_format, current_duration, false) },
{ _("Time spent reading this session"), datetime.secondsToClockDuration(user_duration_format, current_duration, false) },
{ _("Pages read this session"), tonumber(current_pages) },
-- today
{ _("Time spent reading today"), util.secondsToClockDuration(user_duration_format, today_duration, false) },
{ _("Time spent reading today"), datetime.secondsToClockDuration(user_duration_format, today_duration, false) },
{ _("Pages read today"), tonumber(today_pages), separator = true },
-- Current book statistics
-- Includes re-reads
{ _("Total time spent on this book"), util.secondsToClockDuration(user_duration_format, total_time_book, false) },
{ _("Total time spent on this book"), datetime.secondsToClockDuration(user_duration_format, total_time_book, false) },
-- Capped to self.settings.max_sec per distinct page
{ _("Time spent reading this book"), util.secondsToClockDuration(user_duration_format, book_read_time, false) },
{ _("Time spent reading this book"), datetime.secondsToClockDuration(user_duration_format, book_read_time, false) },
-- per days
{ _("Reading started"), os.date("%Y-%m-%d (%H:%M)", tonumber(first_open))},
{ _("Days reading this book"), tonumber(total_days) },
{ _("Average time per day"), util.secondsToClockDuration(user_duration_format, book_read_time/tonumber(total_days), false) },
{ _("Average time per day"), datetime.secondsToClockDuration(user_duration_format, book_read_time/tonumber(total_days), false) },
-- per page (% read)
{ _("Average time per page"), util.secondsToClockDuration(user_duration_format, self.avg_time, false) },
{ _("Average time per page"), datetime.secondsToClockDuration(user_duration_format, self.avg_time, false) },
{ _("Pages read"), string.format("%d (%d%%)", total_read_pages, Math.round(100*total_read_pages/self.data.pages)) },
-- current page (% completed)
{ _("Current page/Total pages"), string.format("%d/%d (%d%%)", self.curr_page, self.data.pages, Math.round(100*self.curr_page/self.data.pages)) },
-- estimation, from current page to end of book
{ _("Estimated time to read"), estimates_valid and util.secondsToClockDuration(user_duration_format, time_to_read, false) or _("N/A") },
{ _("Estimated time to read"), estimates_valid and datetime.secondsToClockDuration(user_duration_format, time_to_read, false) or _("N/A") },
{ _("Estimated reading finished"), estimates_valid and
T(N_("%1 (1 day)", "%1 (%2 days)", estimate_days_to_read), estimate_end_of_read_date, estimate_days_to_read)
or _("N/A") },
@ -1612,10 +1576,10 @@ function ReaderStatistics:getBookStat(id_book)
{ _("Reading started"), os.date("%Y-%m-%d (%H:%M)", tonumber(first_open))},
{ _("Last read"), os.date("%Y-%m-%d (%H:%M)", tonumber(last_open))},
{ _("Days reading this book"), tonumber(total_days) },
{ _("Total time spent on this book"), util.secondsToClockDuration(user_duration_format, total_time_book, false) },
{ _("Time spent reading this book"), util.secondsToClockDuration(user_duration_format, book_read_time, false) },
{ _("Average time per day"), util.secondsToClockDuration(user_duration_format, book_read_time/tonumber(total_days), false) },
{ _("Average time per page"), util.secondsToClockDuration(user_duration_format, avg_time_per_page, false) },
{ _("Total time spent on this book"), datetime.secondsToClockDuration(user_duration_format, total_time_book, false) },
{ _("Time spent reading this book"), datetime.secondsToClockDuration(user_duration_format, book_read_time, false) },
{ _("Average time per day"), datetime.secondsToClockDuration(user_duration_format, book_read_time/tonumber(total_days), false) },
{ _("Average time per page"), datetime.secondsToClockDuration(user_duration_format, avg_time_per_page, false) },
{ _("Pages read"), string.format("%d (%d%%)", total_read_pages, Math.round(100*total_read_pages/pages)) },
{ _("Last read page/Total pages"), string.format("%d/%d (%d%%)", last_page, pages, Math.round(100*last_page/pages)) },
{ _("Highlights"), highlights, separator = true },
@ -1813,13 +1777,13 @@ function ReaderStatistics:getDatesFromAll(sdays, ptype, book_mode)
if ptype == "daily_weekday" then
date_text = string.format("%s (%s)",
os.date("%Y-%m-%d", timestamp),
shortDayOfWeekTranslation[os.date("%a", timestamp)])
datetime.shortDayOfWeekTranslation[os.date("%a", timestamp)])
elseif ptype == "daily" then
date_text = result_book[1][i]
elseif ptype == "weekly" then
date_text = T(_("%1 Week %2"), os.date("%Y", timestamp), os.date(" %W", timestamp))
elseif ptype == "monthly" then
date_text = monthTranslation[os.date("%B", timestamp)] .. os.date(" %Y", timestamp)
date_text = datetime.longMonthTranslation[os.date("%B", timestamp)] .. os.date(" %Y", timestamp)
else
date_text = result_book[1][i]
end
@ -1839,7 +1803,7 @@ function ReaderStatistics:getDatesFromAll(sdays, ptype, book_mode)
local stop_month = os.time{year=year_end, month=month_end, day=1, hour=0, min=0 }
table.insert(results, {
date_text,
T(_("Pages: (%1) Time: %2"), tonumber(result_book[2][i]), util.secondsToClockDuration(user_duration_format, tonumber(result_book[3][i]), false)),
T(_("Pages: (%1) Time: %2"), tonumber(result_book[2][i]), datetime.secondsToClockDuration(user_duration_format, tonumber(result_book[3][i]), false)),
callback = function()
self:callbackMonthly(start_month, stop_month, date_text, book_mode)
end,
@ -1853,7 +1817,7 @@ function ReaderStatistics:getDatesFromAll(sdays, ptype, book_mode)
begin_week = begin_week - weekday * 86400
table.insert(results, {
date_text,
T(_("Pages: (%1) Time: %2"), tonumber(result_book[2][i]), util.secondsToClockDuration(user_duration_format, tonumber(result_book[3][i]), false)),
T(_("Pages: (%1) Time: %2"), tonumber(result_book[2][i]), datetime.secondsToClockDuration(user_duration_format, tonumber(result_book[3][i]), false)),
callback = function()
self:callbackWeekly(begin_week, begin_week + 7 * 86400, date_text, book_mode)
end,
@ -1864,7 +1828,7 @@ function ReaderStatistics:getDatesFromAll(sdays, ptype, book_mode)
- 60 * tonumber(string.sub(time_book,3,4)) - tonumber(string.sub(time_book,5,6))
table.insert(results, {
date_text,
T(_("Pages: (%1) Time: %2"), tonumber(result_book[2][i]), util.secondsToClockDuration(user_duration_format, tonumber(result_book[3][i]), false)),
T(_("Pages: (%1) Time: %2"), tonumber(result_book[2][i]), datetime.secondsToClockDuration(user_duration_format, tonumber(result_book[3][i]), false)),
callback = function()
self:callbackDaily(begin_day, begin_day + 86400, date_text)
end,
@ -1905,7 +1869,7 @@ function ReaderStatistics:getDaysFromPeriod(period_begin, period_end)
day=string.sub(result_book[1][i],9,10), hour=0, min=0, sec=0 }
table.insert(results, {
result_book[1][i],
T(_("Pages: (%1) Time: %2"), tonumber(result_book[2][i]), util.secondsToClockDuration(user_duration_format, tonumber(result_book[3][i]), false)),
T(_("Pages: (%1) Time: %2"), tonumber(result_book[2][i]), datetime.secondsToClockDuration(user_duration_format, tonumber(result_book[3][i]), false)),
callback = function()
local kv = self.kv
UIManager:close(kv)
@ -1949,7 +1913,7 @@ function ReaderStatistics:getBooksFromPeriod(period_begin, period_end, callback_
for i=1, #result_book.title do
table.insert(results, {
result_book[1][i],
T(_("%1 (%2)"), util.secondsToClockDuration(user_duration_format, tonumber(result_book[2][i]), false), tonumber(result_book[3][i])),
T(_("%1 (%2)"), datetime.secondsToClockDuration(user_duration_format, tonumber(result_book[2][i]), false), tonumber(result_book[3][i])),
book_id = tonumber(result_book[4][i]),
callback = function()
local kv = self.kv
@ -2056,7 +2020,7 @@ function ReaderStatistics:getDatesForBook(id_book)
for i=1, #result_book.dates do
table.insert(results, {
result_book[1][i],
T(_("Pages: (%1) Time: %2"), tonumber(result_book[2][i]), util.secondsToClockDuration(user_duration_format, tonumber(result_book[3][i]), false)),
T(_("Pages: (%1) Time: %2"), tonumber(result_book[2][i]), datetime.secondsToClockDuration(user_duration_format, tonumber(result_book[3][i]), false)),
hold_callback = function(kv_page, kv_item)
self:resetStatsForBookForPeriod(id_book, result_book[4][i], result_book[5][i], result_book[1][i], function()
kv_page:removeKeyValueItem(kv_item) -- Reset, refresh what's displayed
@ -2155,7 +2119,7 @@ function ReaderStatistics:getTotalStats()
end
table.insert(total_stats, {
book_title,
util.secondsToClockDuration(user_duration_format, total_time_book, false),
datetime.secondsToClockDuration(user_duration_format, total_time_book, false),
callback = function()
local kv = self.kv
UIManager:close(self.kv)
@ -2176,7 +2140,7 @@ function ReaderStatistics:getTotalStats()
end
conn:close()
return T(_("Total time spent reading: %1"), util.secondsToClockDuration(user_duration_format, total_books_time, false)), total_stats
return T(_("Total time spent reading: %1"), datetime.secondsToClockDuration(user_duration_format, total_books_time, false)), total_stats
end
function ReaderStatistics:genResetBookSubItemTable()
@ -2256,7 +2220,7 @@ function ReaderStatistics:resetPerBook()
if id_book ~= self.id_curr_book then
table.insert(total_stats, {
book_title,
util.secondsToClockDuration(user_duration_format, total_time_book, false),
datetime.secondsToClockDuration(user_duration_format, total_time_book, false),
id_book,
callback = function(kv_page, kv_item)
UIManager:show(ConfirmBox:new{
@ -2599,9 +2563,9 @@ function ReaderStatistics:onShowCalendarView()
local CalendarView = require("calendarview")
UIManager:show(CalendarView:new{
reader_statistics = self,
monthTranslation = monthTranslation,
shortDayOfWeekTranslation = shortDayOfWeekTranslation,
longDayOfWeekTranslation = longDayOfWeekTranslation,
monthTranslation = datetime.longMonthTranslation,
shortDayOfWeekTranslation = datetime.shortDayOfWeekTranslation,
longDayOfWeekTranslation = datetime.shortDayOfWeekToLongTranslation,
start_day_of_week = self.settings.calendar_start_day_of_week,
nb_book_spans = self.settings.calendar_nb_book_spans,
show_hourly_histogram = self.settings.calendar_show_histogram,
@ -2616,7 +2580,7 @@ function ReaderStatistics:onShowCalendarDayView()
local title_callback = function(this)
local day = os.date("%Y-%m-%d", this.day_ts + 10800) -- use 03:00 to determine date (summer time change)
local date = os.date("*t", this.day_ts + 10800)
return string.format("%s (%s)", day, longDayOfWeekTranslation[CalendarView.weekdays[date.wday]])
return string.format("%s (%s)", day, datetime.longDayOfWeekTranslation[CalendarView.weekdays[date.wday]])
end
CalendarView:showCalendarDayView(self, title_callback)
end

@ -18,7 +18,7 @@ local TitleBar = require("ui/widget/titlebar")
local UIManager = require("ui/uimanager")
local VerticalGroup = require("ui/widget/verticalgroup")
local VerticalSpan = require("ui/widget/verticalspan")
local util = require("util")
local datetime = require("datetime")
local _ = require("gettext")
local Screen = Device.screen
@ -251,7 +251,7 @@ function ReaderProgress:genWeekStats(stats_day)
dimen = Geom:new{ w = self.screen_width , h = height * (1/3) },
TextWidget:new{
padding = Size.padding.small,
text = date_format_show .. " - " .. util.secondsToClockDuration(user_duration_format, select_day_time, true),
text = date_format_show .. " - " .. datetime.secondsToClockDuration(user_duration_format, select_day_time, true),
face = Font:getFace("smallffont"),
},
},
@ -345,7 +345,7 @@ function ReaderProgress:genSummaryDay(width)
CenterContainer:new{
dimen = Geom:new{ w = tile_width, h = tile_height },
TextWidget:new{
text = util.secondsToClockDuration(user_duration_format, self.current_duration, true),
text = datetime.secondsToClockDuration(user_duration_format, self.current_duration, true),
face = self.medium_font_face,
},
},
@ -359,7 +359,7 @@ function ReaderProgress:genSummaryDay(width)
CenterContainer:new{
dimen = Geom:new{ w = tile_width, h = tile_height },
TextWidget:new{
text = util.secondsToClockDuration(user_duration_format, self.today_duration, true),
text = datetime.secondsToClockDuration(user_duration_format, self.today_duration, true),
face = self.medium_font_face,
},
},
@ -447,7 +447,7 @@ function ReaderProgress:genSummaryWeek(width)
CenterContainer:new{
dimen = Geom:new{ w = tile_width, h = tile_height },
TextWidget:new{
text = util.secondsToClockDuration(user_duration_format, math.floor(total_time), true),
text = datetime.secondsToClockDuration(user_duration_format, math.floor(total_time), true),
face = self.medium_font_face,
},
},
@ -461,7 +461,7 @@ function ReaderProgress:genSummaryWeek(width)
CenterContainer:new{
dimen = Geom:new{ w = tile_width, h = tile_height },
TextWidget:new{
text = util.secondsToClockDuration(user_duration_format, math.floor(total_time) * (1/7), true),
text = datetime.secondsToClockDuration(user_duration_format, math.floor(total_time) * (1/7), true),
face = self.medium_font_face,
}
}

@ -4,6 +4,7 @@ local KeyValuePage = require("ui/widget/keyvaluepage")
local Math = require("optmath")
local UIManager = require("ui/uimanager")
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local datetime = require("datetime")
local time = require("ui/time")
local util = require("util")
local _ = require("gettext")
@ -69,21 +70,21 @@ function SystemStat:appendCounters()
standby = Device.total_standby_time
end
self:put({" " .. _("Up time"),
util.secondsToClockDuration("", time.to_s(uptime), false, true, true)})
datetime.secondsToClockDuration("", time.to_s(uptime), false, true, true)})
if Device:canSuspend() or Device:canStandby() then
local awake = uptime - suspend - standby
self:put({" " .. _("Time spent awake"),
util.secondsToClockDuration("", time.to_s(awake), false, true, true)
datetime.secondsToClockDuration("", time.to_s(awake), false, true, true)
.. " (" .. Math.round((awake / uptime) * 100) .. "%)"})
end
if Device:canSuspend() then
self:put({" " .. _("Time in suspend"),
util.secondsToClockDuration("", time.to_s(suspend), false, true, true)
datetime.secondsToClockDuration("", time.to_s(suspend), false, true, true)
.. " (" .. Math.round((suspend / uptime) * 100) .. "%)"})
end
if Device:canStandby() then
self:put({" " .. _("Time in standby"),
util.secondsToClockDuration("", time.to_s(standby), false, true, true)
datetime.secondsToClockDuration("", time.to_s(standby), false, true, true)
.. " (" .. Math.round((standby / uptime) * 100) .. "%)"})
end
self:put({_("Counters"), ""})

@ -0,0 +1,188 @@
describe("datetime module", function()
local datetime
setup(function()
require("commonrequire")
datetime = require("datetime")
end)
describe("secondsToClock()", function()
it("should convert seconds to 00:00 format", function()
assert.is_equal("00:00",
datetime.secondsToClock(0, true))
assert.is_equal("00:01",
datetime.secondsToClock(60, true))
end)
it("should round seconds to minutes in 00:00 format", function()
assert.is_equal("00:01",
datetime.secondsToClock(89, true))
assert.is_equal("00:02",
datetime.secondsToClock(90, true))
assert.is_equal("00:02",
datetime.secondsToClock(110, true))
assert.is_equal("00:02",
datetime.secondsToClock(120, true))
assert.is_equal("01:00",
datetime.secondsToClock(3600, true))
assert.is_equal("01:00",
datetime.secondsToClock(3599, true))
assert.is_equal("01:00",
datetime.secondsToClock(3570, true))
assert.is_equal("00:59",
datetime.secondsToClock(3569, true))
end)
it("should convert seconds to 00:00:00 format", function()
assert.is_equal("00:00:00",
datetime.secondsToClock(0))
assert.is_equal("00:01:00",
datetime.secondsToClock(60))
assert.is_equal("00:01:29",
datetime.secondsToClock(89))
assert.is_equal("00:01:30",
datetime.secondsToClock(90))
assert.is_equal("00:01:50",
datetime.secondsToClock(110))
assert.is_equal("00:02:00",
datetime.secondsToClock(120))
end)
end)
describe("secondsToHClock()", function()
it("should convert seconds to 0'00'' format", function()
assert.is_equal("0'",
datetime.secondsToHClock(0, true))
assert.is_equal("0'",
datetime.secondsToHClock(29, true))
assert.is_equal("1'",
datetime.secondsToHClock(60, true))
end)
it("should round seconds to minutes in 0h00' format", function()
assert.is_equal("1'",
datetime.secondsToHClock(89, true))
assert.is_equal("2'",
datetime.secondsToHClock(90, true))
assert.is_equal("2'",
datetime.secondsToHClock(110, true))
assert.is_equal("2'",
datetime.secondsToHClock(120, true))
assert.is_equal("1h00'",
datetime.secondsToHClock(3600, true))
assert.is_equal("1h00'",
datetime.secondsToHClock(3599, true))
assert.is_equal("1h00'",
datetime.secondsToHClock(3570, true))
assert.is_equal("59'",
datetime.secondsToHClock(3569, true))
assert.is_equal("10h01'",
datetime.secondsToHClock(36060, true))
end)
it("should round seconds to minutes in 0h00m format", function()
assert.is_equal("1m",
datetime.secondsToHClock(89, true, true))
assert.is_equal("2m",
datetime.secondsToHClock(90, true, true))
assert.is_equal("2m",
datetime.secondsToHClock(110, true, true))
assert.is_equal("1h00m",
datetime.secondsToHClock(3600, true, true))
assert.is_equal("1h00m",
datetime.secondsToHClock(3599, true, true))
assert.is_equal("59m",
datetime.secondsToHClock(3569, true, true))
assert.is_equal("10h01m",
datetime.secondsToHClock(36060, true, true))
end)
it("should convert seconds to 0h00'00'' format", function()
assert.is_equal("0\"",
datetime.secondsToHClock(0))
assert.is_equal("1'00\"",
datetime.secondsToHClock(60))
assert.is_equal("1'29\"",
datetime.secondsToHClock(89))
assert.is_equal("1'30\"",
datetime.secondsToHClock(90))
assert.is_equal("1'50\"",
datetime.secondsToHClock(110))
assert.is_equal("2'00\"",
datetime.secondsToHClock(120))
end)
end)
describe("secondsToClockDuration()", function()
it("should change type based on format", function()
assert.is_equal("10h01m30s",
datetime.secondsToClockDuration("modern", 36090, false, true))
assert.is_equal("10:01:30",
datetime.secondsToClockDuration("classic", 36090, false))
assert.is_equal("10:01:30",
datetime.secondsToClockDuration("unknown", 36090, false))
assert.is_equal("10:01:30",
datetime.secondsToClockDuration(nil, 36090, false))
end)
it("should pass along withoutSeconds", function()
assert.is_equal("10h01m30s",
datetime.secondsToClockDuration("modern", 36090, false, true))
assert.is_equal("10h02m",
datetime.secondsToClockDuration("modern", 36090, true, true))
assert.is_equal("10:01:30",
datetime.secondsToClockDuration("classic", 36090, false))
assert.is_equal("10:02",
datetime.secondsToClockDuration("classic", 36090, true))
end)
it("should pass along hmsFormat for modern format", function()
assert.is_equal("10h01'30\"",
datetime.secondsToClockDuration("modern", 36090))
assert.is_equal("10h01m30s",
datetime.secondsToClockDuration("modern", 36090, false, true))
assert.is_equal("10h02m",
datetime.secondsToClockDuration("modern", 36090, true, true))
assert.is_equal("10h02'",
datetime.secondsToClockDuration("modern", 36090, true, false))
assert.is_equal("10:01:30",
datetime.secondsToClockDuration("classic", 36090, false, true))
assert.is_equal("10:01:30",
datetime.secondsToClockDuration("classic", 36090, false, false))
end)
end)
describe("secondsToDate()", function()
it("should deliver a date string", function()
local time = { year=2022, month=12, day=6, hour=13, min=30, sec=35 }
local time_s = os.time(time)
assert.is_equal("2022-12-06",
datetime.secondsToDate(time_s))
assert.is_equal("2022-12-07",
datetime.secondsToDate(time_s + 86400)) -- one day later
assert.is_equal("Tue Dec 06 2022",
datetime.secondsToDate(time_s, true))
assert.is_equal("Wed Dec 07 2022",
datetime.secondsToDate(time_s + 86400, true))
end)
end)
describe("secondsToDateTime()", function()
it("should should deliver a date and time string", function()
local time = { year=2022, month=11, day=20, hour=9, min=57, sec=39 }
local time_s = os.time(time)
assert.is_equal("2022-11-20 9:57",
datetime.secondsToDateTime(time_s))
assert.is_equal("2022-11-21 9:57",
datetime.secondsToDateTime(time_s + 86400))
assert.is_equal("2022-11-20 9:57 AM",
datetime.secondsToDateTime(time_s, true))
assert.is_equal("2022-11-21 9:57 AM",
datetime.secondsToDateTime(time_s + 86400, true))
assert.is_equal("Sun Nov 20 2022 9:57",
datetime.secondsToDateTime(time_s, false, true))
assert.is_equal("Mon Nov 21 2022 9:57",
datetime.secondsToDateTime(time_s + 86400, false, true))
assert.is_equal("Sun Nov 20 2022 9:57 AM",
datetime.secondsToDateTime(time_s, true, true))
assert.is_equal("Mon Nov 21 2022 9:57 AM",
datetime.secondsToDateTime(time_s + 86400, true, true))
end)
end)
end)

@ -461,145 +461,6 @@ describe("util module", function()
end)
end)
describe("secondsToClock()", function()
it("should convert seconds to 00:00 format", function()
assert.is_equal("00:00",
util.secondsToClock(0, true))
assert.is_equal("00:01",
util.secondsToClock(60, true))
end)
it("should round seconds to minutes in 00:00 format", function()
assert.is_equal("00:01",
util.secondsToClock(89, true))
assert.is_equal("00:02",
util.secondsToClock(90, true))
assert.is_equal("00:02",
util.secondsToClock(110, true))
assert.is_equal("00:02",
util.secondsToClock(120, true))
assert.is_equal("01:00",
util.secondsToClock(3600, true))
assert.is_equal("01:00",
util.secondsToClock(3599, true))
assert.is_equal("01:00",
util.secondsToClock(3570, true))
assert.is_equal("00:59",
util.secondsToClock(3569, true))
end)
it("should convert seconds to 00:00:00 format", function()
assert.is_equal("00:00:00",
util.secondsToClock(0))
assert.is_equal("00:01:00",
util.secondsToClock(60))
assert.is_equal("00:01:29",
util.secondsToClock(89))
assert.is_equal("00:01:30",
util.secondsToClock(90))
assert.is_equal("00:01:50",
util.secondsToClock(110))
assert.is_equal("00:02:00",
util.secondsToClock(120))
end)
end)
describe("secondsToHClock()", function()
it("should convert seconds to 0'00'' format", function()
assert.is_equal("0'",
util.secondsToHClock(0, true))
assert.is_equal("0'",
util.secondsToHClock(29, true))
assert.is_equal("1'",
util.secondsToHClock(60, true))
end)
it("should round seconds to minutes in 0h00' format", function()
assert.is_equal("1'",
util.secondsToHClock(89, true))
assert.is_equal("2'",
util.secondsToHClock(90, true))
assert.is_equal("2'",
util.secondsToHClock(110, true))
assert.is_equal("2'",
util.secondsToHClock(120, true))
assert.is_equal("1h00'",
util.secondsToHClock(3600, true))
assert.is_equal("1h00'",
util.secondsToHClock(3599, true))
assert.is_equal("1h00'",
util.secondsToHClock(3570, true))
assert.is_equal("59'",
util.secondsToHClock(3569, true))
assert.is_equal("10h01'",
util.secondsToHClock(36060, true))
end)
it("should round seconds to minutes in 0h00m format", function()
assert.is_equal("1m",
util.secondsToHClock(89, true, true))
assert.is_equal("2m",
util.secondsToHClock(90, true, true))
assert.is_equal("2m",
util.secondsToHClock(110, true, true))
assert.is_equal("1h00m",
util.secondsToHClock(3600, true, true))
assert.is_equal("1h00m",
util.secondsToHClock(3599, true, true))
assert.is_equal("59m",
util.secondsToHClock(3569, true, true))
assert.is_equal("10h01m",
util.secondsToHClock(36060, true, true))
end)
it("should convert seconds to 0h00'00'' format", function()
assert.is_equal("0\"",
util.secondsToHClock(0))
assert.is_equal("1'00\"",
util.secondsToHClock(60))
assert.is_equal("1'29\"",
util.secondsToHClock(89))
assert.is_equal("1'30\"",
util.secondsToHClock(90))
assert.is_equal("1'50\"",
util.secondsToHClock(110))
assert.is_equal("2'00\"",
util.secondsToHClock(120))
end)
end)
describe("secondsToClockDuration()", function()
it("should change type based on format", function()
assert.is_equal("10h01m30s",
util.secondsToClockDuration("modern", 36090, false, true))
assert.is_equal("10:01:30",
util.secondsToClockDuration("classic", 36090, false))
assert.is_equal("10:01:30",
util.secondsToClockDuration("unknown", 36090, false))
assert.is_equal("10:01:30",
util.secondsToClockDuration(nil, 36090, false))
end)
it("should pass along withoutSeconds", function()
assert.is_equal("10h01m30s",
util.secondsToClockDuration("modern", 36090, false, true))
assert.is_equal("10h02m",
util.secondsToClockDuration("modern", 36090, true, true))
assert.is_equal("10:01:30",
util.secondsToClockDuration("classic", 36090, false))
assert.is_equal("10:02",
util.secondsToClockDuration("classic", 36090, true))
end)
it("should pass along hmsFormat for modern format", function()
assert.is_equal("10h01'30\"",
util.secondsToClockDuration("modern", 36090))
assert.is_equal("10h01m30s",
util.secondsToClockDuration("modern", 36090, false, true))
assert.is_equal("10h02m",
util.secondsToClockDuration("modern", 36090, true, true))
assert.is_equal("10h02'",
util.secondsToClockDuration("modern", 36090, true, false))
assert.is_equal("10:01:30",
util.secondsToClockDuration("classic", 36090, false, true))
assert.is_equal("10:01:30",
util.secondsToClockDuration("classic", 36090, false, false))
end)
end) -- end my changes
describe("urlEncode() and urlDecode", function()
it("should encode string", function()
assert.is_equal("Secret_Password123", util.urlEncode("Secret_Password123"))

Loading…
Cancel
Save