mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 10:44:09 -04:00
New formatter function 'date_arithmetic' that simplifies computing new dates from an existing one
This commit is contained in:
parent
06c7d20872
commit
e03405df1b
@ -389,6 +389,16 @@ In `GPM` the functions described in `Single Function Mode` all require an additi
|
|||||||
* ``connected_device_uuid(storage_location_key)`` -- if a device is connected then return the device uuid (unique id), otherwise return the empty string. Each storage location on a device has a different uuid. The ``storage_location_key`` location names are ``'main'``, ``'carda'`` and ``'cardb'``. This function works only in the GUI.
|
* ``connected_device_uuid(storage_location_key)`` -- if a device is connected then return the device uuid (unique id), otherwise return the empty string. Each storage location on a device has a different uuid. The ``storage_location_key`` location names are ``'main'``, ``'carda'`` and ``'cardb'``. This function works only in the GUI.
|
||||||
* ``current_library_name()`` -- return the last name on the path to the current calibre library.
|
* ``current_library_name()`` -- return the last name on the path to the current calibre library.
|
||||||
* ``current_library_path()`` -- return the full path to the current calibre library.
|
* ``current_library_path()`` -- return the full path to the current calibre library.
|
||||||
|
* ``date_arithmetic(date, calc_spec, fmt)`` -- Calculate a new date from ``date`` using ``calc_spec``. Return the new date formatted according to optional ``fmt``: if not supplied then the result will be in ISO format. The calc_spec is a string formed by concatenating pairs of ``vW`` (``valueWhat``) where ``v`` is a possibly-negative number and W is one of the following letters:
|
||||||
|
|
||||||
|
* ``s``: add ``v`` seconds to ``date``
|
||||||
|
* ``m``: add ``v`` minutes to ``date``
|
||||||
|
* ``h``: add ``v`` hours to ``date``
|
||||||
|
* ``d``: add ``v`` days to ``date``
|
||||||
|
* ``w``: add ``v`` weeks to ``date``
|
||||||
|
* ``y``: add ``v`` years to ``date``, where a year is 365 days.
|
||||||
|
|
||||||
|
Example: ``'1s3d-1m'`` will add 1 second, add 3 days, and subtract 1 month from ``date``.
|
||||||
* ``days_between(date1, date2)`` -- return the number of days between ``date1`` and ``date2``. The number is positive if ``date1`` is greater than ``date2``, otherwise negative. If either ``date1`` or ``date2`` are not dates, the function returns the empty string.
|
* ``days_between(date1, date2)`` -- return the number of days between ``date1`` and ``date2``. The number is positive if ``date1`` is greater than ``date2``, otherwise negative. If either ``date1`` or ``date2`` are not dates, the function returns the empty string.
|
||||||
* ``divide(x, y)`` -- returns ``x / y``. Throws an exception if either ``x`` or ``y`` are not numbers. This function can usually be replaced by the ``/`` operator.
|
* ``divide(x, y)`` -- returns ``x / y``. Throws an exception if either ``x`` or ``y`` are not numbers. This function can usually be replaced by the ``/`` operator.
|
||||||
* ``eval(string)`` -- evaluates the string as a program, passing the local variables. This permits using the template processor to construct complex results from local variables. In :ref:`Template Program Mode <template_mode>`, because the `{` and `}` characters are interpreted before the template is evaluated you must use `[[` for the `{` character and `]]` for the ``}`` character. They are converted automatically. Note also that prefixes and suffixes (the `|prefix|suffix` syntax) cannot be used in the argument to this function when using :ref:`Template Program Mode <template_mode>`.
|
* ``eval(string)`` -- evaluates the string as a program, passing the local variables. This permits using the template processor to construct complex results from local variables. In :ref:`Template Program Mode <template_mode>`, because the `{` and `}` characters are interpreted before the template is evaluated you must use `[[` for the `{` character and `]]` for the ``}`` character. They are converted automatically. Note also that prefixes and suffixes (the `|prefix|suffix` syntax) cannot be used in the argument to this function when using :ref:`Template Program Mode <template_mode>`.
|
||||||
|
@ -13,7 +13,7 @@ __copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
|||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import inspect, re, traceback, numbers
|
import inspect, re, traceback, numbers
|
||||||
from datetime import datetime
|
from datetime import datetime, timedelta
|
||||||
from math import trunc, floor, ceil, modf
|
from math import trunc, floor, ceil, modf
|
||||||
|
|
||||||
from calibre import human_readable, prints
|
from calibre import human_readable, prints
|
||||||
@ -1612,6 +1612,55 @@ class BuiltinDaysBetween(BuiltinFormatterFunction):
|
|||||||
return '%.1f'%(i.days + (i.seconds/(24.0*60.0*60.0)))
|
return '%.1f'%(i.days + (i.seconds/(24.0*60.0*60.0)))
|
||||||
|
|
||||||
|
|
||||||
|
class BuiltinDateArithmetic(BuiltinFormatterFunction):
|
||||||
|
name = 'date_arithmetic'
|
||||||
|
arg_count = -1
|
||||||
|
category = 'Date functions'
|
||||||
|
__doc__ = doc = _('date_arithmetic(date, calc_spec, fmt) -- '
|
||||||
|
"Calculate a new date from 'date' using 'calc_spec'. Return the "
|
||||||
|
"new date formatted according to optional 'fmt': if not supplied "
|
||||||
|
"then the result will be in iso format. The calc_spec is a string "
|
||||||
|
"formed by concatenating pairs of 'vW' (valueWhat) where 'v' is a "
|
||||||
|
"possibly-negative number and W is one of the following letters: "
|
||||||
|
"s: add 'v' seconds to 'date' "
|
||||||
|
"m: add 'v' minutes to 'date' "
|
||||||
|
"h: add 'v' hours to 'date' "
|
||||||
|
"d: add 'v' days to 'date' "
|
||||||
|
"w: add 'v' weeks to 'date' "
|
||||||
|
"y: add 'v' years to 'date', where a year is 365 days. "
|
||||||
|
"Example: '1s3d-1m' will add 1 second, add 3 days, and subtract 1 "
|
||||||
|
"month from 'date'.")
|
||||||
|
|
||||||
|
calc_ops = {
|
||||||
|
's': lambda v: timedelta(seconds=v),
|
||||||
|
'm': lambda v: timedelta(minutes=v),
|
||||||
|
'h': lambda v: timedelta(hours=v),
|
||||||
|
'd': lambda v: timedelta(days=v),
|
||||||
|
'w': lambda v: timedelta(weeks=v),
|
||||||
|
'y': lambda v: timedelta(days=v * 365),
|
||||||
|
}
|
||||||
|
|
||||||
|
def evaluate(self, formatter, kwargs, mi, locals, date, calc_spec, fmt=None):
|
||||||
|
try:
|
||||||
|
d = parse_date(date)
|
||||||
|
if d == UNDEFINED_DATE:
|
||||||
|
return ''
|
||||||
|
while calc_spec:
|
||||||
|
mo = re.match('([-+\d]+)([smhdwy])', calc_spec)
|
||||||
|
if mo is None:
|
||||||
|
raise ValueError(
|
||||||
|
_("{0}: invalid calculation specifier '{1}'").format(
|
||||||
|
'date_arithmetic', calc_spec))
|
||||||
|
d += self.calc_ops[mo[2]](int(mo[1]))
|
||||||
|
calc_spec = calc_spec[len(mo[0]):]
|
||||||
|
return format_date(d, fmt if fmt else 'iso')
|
||||||
|
except ValueError as e:
|
||||||
|
raise e
|
||||||
|
except Exception as e:
|
||||||
|
traceback.print_exc()
|
||||||
|
raise ValueError(_("{0}: error: {1}").format('date_arithmetic', str(e)))
|
||||||
|
|
||||||
|
|
||||||
class BuiltinLanguageStrings(BuiltinFormatterFunction):
|
class BuiltinLanguageStrings(BuiltinFormatterFunction):
|
||||||
name = 'language_strings'
|
name = 'language_strings'
|
||||||
arg_count = 2
|
arg_count = 2
|
||||||
@ -2044,6 +2093,7 @@ _formatter_builtins = [
|
|||||||
BuiltinCapitalize(), BuiltinCharacter(), BuiltinCheckYesNo(), BuiltinCeiling(),
|
BuiltinCapitalize(), BuiltinCharacter(), BuiltinCheckYesNo(), BuiltinCeiling(),
|
||||||
BuiltinCmp(), BuiltinConnectedDeviceName(), BuiltinConnectedDeviceUUID(), BuiltinContains(),
|
BuiltinCmp(), BuiltinConnectedDeviceName(), BuiltinConnectedDeviceUUID(), BuiltinContains(),
|
||||||
BuiltinCount(), BuiltinCurrentLibraryName(), BuiltinCurrentLibraryPath(),
|
BuiltinCount(), BuiltinCurrentLibraryName(), BuiltinCurrentLibraryPath(),
|
||||||
|
BuiltinDateArithmetic(),
|
||||||
BuiltinDaysBetween(), BuiltinDivide(), BuiltinEval(), BuiltinFirstNonEmpty(),
|
BuiltinDaysBetween(), BuiltinDivide(), BuiltinEval(), BuiltinFirstNonEmpty(),
|
||||||
BuiltinField(), BuiltinFieldExists(),
|
BuiltinField(), BuiltinFieldExists(),
|
||||||
BuiltinFinishFormatting(), BuiltinFirstMatchingCmp(), BuiltinFloor(),
|
BuiltinFinishFormatting(), BuiltinFirstMatchingCmp(), BuiltinFloor(),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user