From 1311c84d11710d4aed029dd04c8deae96900d3fb Mon Sep 17 00:00:00 2001 From: Charles Haley Date: Thu, 25 Mar 2021 19:31:12 +0000 Subject: [PATCH] Template function format_date() improvement: add 'to_number' and 'from_number' as valid formats --- manual/template_lang.rst | 2 ++ src/calibre/utils/formatter_functions.py | 16 +++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/manual/template_lang.rst b/manual/template_lang.rst index c3d2fa7757..a4213832f8 100644 --- a/manual/template_lang.rst +++ b/manual/template_lang.rst @@ -431,6 +431,8 @@ In `GPM` the functions described in `Single Function Mode` all require an additi * ``ap :`` use a 12-hour clock instead of a 24-hour clock, with 'ap' replaced by the localized string for am or pm. * ``AP :`` use a 12-hour clock instead of a 24-hour clock, with 'AP' replaced by the localized string for AM or PM. * ``iso :`` the date with time and timezone. Must be the only format present. + * ``to_number :`` convert the date & time into a floating point number (a `timestamp`) + * ``from_number :`` convert a floating point number (a `timestamp`) into an ``iso`` formatted date. If you want a different date format then add the desired formatting string after ``from_number`` and a colon (``:``). Example: ``from_number:MMM dd yyyy`` You might get unexpected results if the date you are formatting contains localized month names, which can happen if you changed the date format tweaks to contain ``MMMM``. In this case, instead of using the ``field()`` function as in:: diff --git a/src/calibre/utils/formatter_functions.py b/src/calibre/utils/formatter_functions.py index 31395f2cb1..08590fcb3b 100644 --- a/src/calibre/utils/formatter_functions.py +++ b/src/calibre/utils/formatter_functions.py @@ -13,6 +13,7 @@ __copyright__ = '2010, Kovid Goyal ' __docformat__ = 'restructuredtext en' import inspect, re, traceback, numbers +from datetime import datetime from math import trunc, floor, ceil, modf from calibre import human_readable, prints @@ -1151,14 +1152,23 @@ class BuiltinFormatDate(BuiltinFormatterFunction): 'ss : the seconds with a leading 0 (00 to 59) ' 'ap : use a 12-hour clock instead of a 24-hour clock, with "ap" replaced by the localized string for am or pm ' 'AP : use a 12-hour clock instead of a 24-hour clock, with "AP" replaced by the localized string for AM or PM ' - 'iso : the date with time and timezone. Must be the only format present') + 'iso : the date with time and timezone. Must be the only format present ' + 'to_number: the date as a floating point number ' + 'from_number[:fmt]: format the timestamp using fmt if present otherwise iso') def evaluate(self, formatter, kwargs, mi, locals, val, format_string): if not val or val == 'None': return '' try: - dt = parse_date(val) - s = format_date(dt, format_string) + if format_string == 'to_number': + s = parse_date(val).timestamp() + elif format_string.startswith('from_number'): + val = datetime.fromtimestamp(float(val)) + f = format_string[12:] + s = format_date(val, f if f else 'iso') + else: + s = format_date(parse_date(val), format_string) + return s except: s = 'BAD DATE' return s