From 2f60c9e064afd781ae400d7bfb32fd4814929907 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Sat, 29 Oct 2011 07:41:21 +0200 Subject: [PATCH] Add hour/minute/seconds formatting to date format strings. --- src/calibre/manual/template_lang.rst | 8 +++++ src/calibre/utils/date.py | 44 ++++++++++++++++++++---- src/calibre/utils/formatter_functions.py | 8 +++++ 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/src/calibre/manual/template_lang.rst b/src/calibre/manual/template_lang.rst index 26c03d8491..72e9c9aa27 100644 --- a/src/calibre/manual/template_lang.rst +++ b/src/calibre/manual/template_lang.rst @@ -258,6 +258,14 @@ The following functions are available in addition to those described in single-f MMMM : the long localized month name (e.g. "January" to "December"). yy : the year as two digit number (00 to 99). yyyy : the year as four digit number. + h : the hours without a leading 0 (0 to 11 or 0 to 23, depending on am/pm) + hh : the minutes with a leading 0 (00 to 11 or 00 to 23, depending on am/pm) + m : the minutes without a leading 0 (0 to 59) + mm : the minutes with a leading 0 (00 to 59) + s : the seconds without a leading 0 (0 to 59) + 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. * ``eval(string)`` -- evaluates the string as a program, passing the local variables (those ``assign`` ed to). This permits using the template processor to construct complex results from local variables. diff --git a/src/calibre/utils/date.py b/src/calibre/utils/date.py index 00190ac23d..e9db6e68ad 100644 --- a/src/calibre/utils/date.py +++ b/src/calibre/utils/date.py @@ -170,11 +170,37 @@ def format_date(dt, format, assume_utc=False, as_utc=False): if format == 'iso': return isoformat(dt, assume_utc=assume_utc, as_utc=as_utc) + ampm = 'ap' in format.lower() + if dt == UNDEFINED_DATE: return '' strf = partial(strftime, t=dt.timetuple()) + def format_hour(hr): + l = len(hr) + h = dt.hour + if ampm: + h = h%12 + if l == 1: return '%d'%h + return '%02d'%h + + def format_minute(min): + l = len(min) + if l == 1: return '%d'%dt.minute + return '%02d'%dt.minute + + def format_second(min): + l = len(min) + if l == 1: return '%d'%dt.second + return '%02d'%dt.second + + def format_ampm(ap): + res = strf('%p') + if ap == 'AP': + return res + return res.lower() + def format_day(dy): l = len(dy) if l == 1: return '%d'%dt.day @@ -193,17 +219,23 @@ def format_date(dt, format, assume_utc=False, as_utc=False): if len(yr) == 2: return '%02d'%(dt.year % 100) return '%04d'%dt.year + function_index = { + 'd': format_day, + 'M': format_month, + 'y': format_year, + 'h': format_hour, + 'm': format_minute, + 's': format_second, + 'a': format_ampm, + 'A': format_ampm, + } def repl_func(mo): s = mo.group(0) if s is None: return '' - if s[0] == 'd': - return format_day(s) - if s[0] == 'M': - return format_month(s) - return format_year(s) + return function_index[s[0]](s) - return re.sub('(d{1,4}|M{1,4}|(?:yyyy|yy))', repl_func, format) + return re.sub('(s{1,2})|(m{1,2})|(h{1,2})|(ap)|(AP)|(d{1,4}|M{1,4}|(?:yyyy|yy))', repl_func, format) def replace_months(datestr, clang): # Replace months by english equivalent for parse_date diff --git a/src/calibre/utils/formatter_functions.py b/src/calibre/utils/formatter_functions.py index 964120f550..d4958e5d10 100644 --- a/src/calibre/utils/formatter_functions.py +++ b/src/calibre/utils/formatter_functions.py @@ -747,6 +747,14 @@ class BuiltinFormatDate(BuiltinFormatterFunction): 'MMMM : the long localized month name (e.g. "January" to "December"). ' 'yy : the year as two digit number (00 to 99). ' 'yyyy : the year as four digit number. ' + 'h : the hours without a leading 0 (0 to 11 or 0 to 23, depending on am/pm) ' + 'hh : the minutes with a leading 0 (00 to 11 or 00 to 23, depending on am/pm) ' + 'm : the minutes without a leading 0 (0 to 59) ' + 'mm : the minutes with a leading 0 (00 to 59) ' + 's : the seconds without a leading 0 (0 to 59) ' + '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') def evaluate(self, formatter, kwargs, mi, locals, val, format_string):