mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-31 14:33:54 -04:00
GPM format_duration(): make 'largest_unit' as optional parameter
This commit is contained in:
parent
85f448527b
commit
3bc9f1c4f4
@ -3418,11 +3418,11 @@ See also the functions :ref:`make_url`, :ref:`make_url_extended` and :ref:`query
|
|||||||
|
|
||||||
class BuiltinFormatDuration(BuiltinFormatterFunction):
|
class BuiltinFormatDuration(BuiltinFormatterFunction):
|
||||||
name = 'format_duration'
|
name = 'format_duration'
|
||||||
arg_count = 3
|
arg_count = -1
|
||||||
category = FORMATTING_VALUES
|
category = FORMATTING_VALUES
|
||||||
__doc__ = doc = _(
|
__doc__ = doc = _(
|
||||||
r'''
|
r'''
|
||||||
``format_duration(value, template, largest_unit)`` -- format the value, a number
|
``format_duration(value, template, [largest_unit])`` -- format the value, a number
|
||||||
of seconds, into a string showing weeks, days, hours, minutes, and seconds. If
|
of seconds, into a string showing weeks, days, hours, minutes, and seconds. If
|
||||||
the value is a float then it is rounded to the nearest integer.[/] You choose
|
the value is a float then it is rounded to the nearest integer.[/] You choose
|
||||||
how to format the value using a template consisting of value selectors
|
how to format the value using a template consisting of value selectors
|
||||||
@ -3436,23 +3436,20 @@ surrounded by ``[`` and ``]`` characters. The selectors are:
|
|||||||
[/LIST]
|
[/LIST]
|
||||||
You can put arbitrary text between selectors.
|
You can put arbitrary text between selectors.
|
||||||
|
|
||||||
The ``largest_unit`` parameter specifies the largest of weeks, days, hours, minutes,
|
|
||||||
and seconds that will be produced by the template. It must be one of the value selectors.
|
|
||||||
|
|
||||||
The following examples use a duration of 2 days (172,800 seconds) 1 hour (3,600 seconds)
|
The following examples use a duration of 2 days (172,800 seconds) 1 hour (3,600 seconds)
|
||||||
and 20 seconds, which totals to 176,420 seconds.
|
and 20 seconds, which totals to 176,420 seconds.
|
||||||
[LIST]
|
[LIST]
|
||||||
[*]``format_duration(176420, '[d][h][m][s]', 'd')`` will return the value ``2d 1h 0m 20s``.
|
[*]``format_duration(176420, '[d][h][m][s]')`` will return the value ``2d 1h 0m 20s``.
|
||||||
[*]``format_duration(176420, '[h][m][s]', 'h')`` will return the value ``49h 0m 20s``.
|
[*]``format_duration(176420, '[h][m][s]')`` will return the value ``49h 0m 20s``.
|
||||||
[*]``format_duration(176420, 'Your reading time is [d][h][m][s]', 'h')`` returns the value
|
[*]``format_duration(176420, 'Your reading time is [d][h][m][s]')`` returns the value
|
||||||
``Your reading time is 49h 0m 20s``.
|
``Your reading time is 49h 0m 20s``.
|
||||||
[*]``format_duration(176420, '[w][d][h][m][s]', 'w')`` will return the value ``2d 1h 0m 20s``.
|
[*]``format_duration(176420, '[w][d][h][m][s]')`` will return the value ``2d 1h 0m 20s``.
|
||||||
Note that the zero weeks value is not returned.
|
Note that the zero weeks value is not returned.
|
||||||
[/LIST]
|
[/LIST]
|
||||||
If you want to see zero values for items such as weeks in the above example,
|
If you want to see zero values for items such as weeks in the above example,
|
||||||
use an uppercase selector. For example, the following uses ``'W'`` to show zero weeks:
|
use an uppercase selector. For example, the following uses ``'W'`` to show zero weeks:
|
||||||
|
|
||||||
``format_duration(176420, '[W][d][h][m][s]', 'w')`` returns ``0w 2d 1h 0m 20s``.
|
``format_duration(176420, '[W][d][h][m][s]')`` returns ``0w 2d 1h 0m 20s``.
|
||||||
|
|
||||||
By default the text following a value is the selector followed by a space.
|
By default the text following a value is the selector followed by a space.
|
||||||
You can change that to whatever text you want. The format for a selector with
|
You can change that to whatever text you want. The format for a selector with
|
||||||
@ -3477,12 +3474,35 @@ For example, the selector:
|
|||||||
[*]``[w: weeks | week ]`` produces ``'0 weeks '``, ``'1 week '``, or ``'2 weeks '``.
|
[*]``[w: weeks | week ]`` produces ``'0 weeks '``, ``'1 week '``, or ``'2 weeks '``.
|
||||||
[*]``[w: weeks ]`` produces ``0 weeks '``, ``1 weeks '``, or ``2 weeks '``.
|
[*]``[w: weeks ]`` produces ``0 weeks '``, ``1 weeks '``, or ``2 weeks '``.
|
||||||
[/LIST]
|
[/LIST]
|
||||||
|
|
||||||
|
The optional ``largest_unit`` parameter specifies the largest of weeks, days, hours, minutes,
|
||||||
|
and seconds that will be produced by the template. It must be one of the value selectors.
|
||||||
|
This can be useful to truncate a value.
|
||||||
|
|
||||||
|
``format_duration(176420, '[h][m][s]', 'd')`` will return the value ``1h 0m 20s`` instead of ``49h 0m 20s``.
|
||||||
''')
|
''')
|
||||||
|
|
||||||
def evaluate(self, formatter, kwargs, mi, locals, value, template, largest_unit):
|
def evaluate(self, formatter, kwargs, mi, locals, value, template, largest_unit=''):
|
||||||
if largest_unit not in 'wdhms':
|
if largest_unit not in 'wdhms':
|
||||||
raise ValueError(_('the {0} parameter must be one of {1}').format('largest_unit', 'wdhms'))
|
raise ValueError(_('the {0} parameter must be one of {1}').format('largest_unit', 'wdhms'))
|
||||||
|
|
||||||
|
pat = re.compile(r'\[(.)(:(.*?))?\]')
|
||||||
|
|
||||||
|
if not largest_unit:
|
||||||
|
for m in pat.finditer(template):
|
||||||
|
fmt_char = m.group(1)
|
||||||
|
match fmt_char.lower():
|
||||||
|
case 'w' if largest_unit in 'dhms':
|
||||||
|
largest_unit = 'w'
|
||||||
|
case 'd' if largest_unit in 'hms':
|
||||||
|
largest_unit = 'd'
|
||||||
|
case 'h' if largest_unit in 'ms':
|
||||||
|
largest_unit = 'h'
|
||||||
|
case 'm' if largest_unit in 's':
|
||||||
|
largest_unit = 'm'
|
||||||
|
case 's' if not largest_unit:
|
||||||
|
largest_unit = 's'
|
||||||
|
|
||||||
int_val = remainder = round(float(value)) if value else 0
|
int_val = remainder = round(float(value)) if value else 0
|
||||||
weeks,remainder = divmod(remainder, 60*60*24*7) if largest_unit == 'w' else (-1,remainder)
|
weeks,remainder = divmod(remainder, 60*60*24*7) if largest_unit == 'w' else (-1,remainder)
|
||||||
days,remainder = divmod(remainder, 60*60*24) if largest_unit in 'wd' else (-1,remainder)
|
days,remainder = divmod(remainder, 60*60*24) if largest_unit in 'wd' else (-1,remainder)
|
||||||
@ -3491,9 +3511,8 @@ For example, the selector:
|
|||||||
seconds = remainder
|
seconds = remainder
|
||||||
|
|
||||||
def repl(mo):
|
def repl(mo):
|
||||||
txt = mo.group()
|
fmt_char = mo.group(1)
|
||||||
fmt_char = txt[1]
|
suffixes = re.split(r'\|', mo.group(3) or '')
|
||||||
suffixes = re.split(r'\|', txt[3:-1])
|
|
||||||
match len(suffixes):
|
match len(suffixes):
|
||||||
case 1 if not suffixes[0]:
|
case 1 if not suffixes[0]:
|
||||||
zero_suffix = one_suffix = more_suffix = fmt_char.lower() + ' '
|
zero_suffix = one_suffix = more_suffix = fmt_char.lower() + ' '
|
||||||
@ -3537,8 +3556,7 @@ For example, the selector:
|
|||||||
case _:
|
case _:
|
||||||
raise ValueError(_('The {} format specifier is not valid').format(fmt_char))
|
raise ValueError(_('The {} format specifier is not valid').format(fmt_char))
|
||||||
|
|
||||||
s = re.sub(r'\[.:?.*?\]', repl, template)
|
return pat.sub(repl, template)
|
||||||
return s
|
|
||||||
|
|
||||||
|
|
||||||
_formatter_builtins = [
|
_formatter_builtins = [
|
||||||
|
Loading…
x
Reference in New Issue
Block a user