diff --git a/src/calibre/library/caches.py b/src/calibre/library/caches.py index 181e2af800..ec98ecb15d 100644 --- a/src/calibre/library/caches.py +++ b/src/calibre/library/caches.py @@ -12,7 +12,7 @@ from datetime import timedelta from threading import Thread from calibre.utils.config import tweaks, prefs -from calibre.utils.date import parse_date, now, UNDEFINED_DATE +from calibre.utils.date import parse_date, now, UNDEFINED_DATE, clean_date_for_sort from calibre.utils.search_query_parser import SearchQueryParser from calibre.utils.pyparsing import ParseException from calibre.utils.localization import canonicalize_lang, lang_map @@ -1062,7 +1062,16 @@ class SortKeyGenerator(object): if dt == 'datetime': if val is None: val = UNDEFINED_DATE - + format = None + if name == 'timestamp': + format = tweaks['gui_timestamp_display_format'] + elif name == 'pubdate': + format = tweaks['gui_pubdate_display_format'] + elif name == 'last_modified': + format = tweaks['gui_last_modified_display_format'] + elif fm['is_custom']: + format = fm['display'].get('date_format', None) + val = clean_date_for_sort(val, format) elif dt == 'series': if val is None: val = ('', 1) diff --git a/src/calibre/utils/date.py b/src/calibre/utils/date.py index 5b0e15749c..978c09d752 100644 --- a/src/calibre/utils/date.py +++ b/src/calibre/utils/date.py @@ -242,6 +242,69 @@ def format_date(dt, format, assume_utc=False, as_utc=False): '(s{1,2})|(m{1,2})|(h{1,2})|(ap)|(AP)|(d{1,4}|M{1,4}|(?:yyyy|yy))', repl_func, format) +def clean_date_for_sort(dt, format): + ''' Return a date formatted as a string using a subset of Qt's formatting codes ''' + if not format: + format = 'yyMd' + + if not isinstance(dt, datetime): + dt = datetime.combine(dt, time()) + + if hasattr(dt, 'tzinfo'): + if dt.tzinfo is not None: + dt = as_utc(dt) + + if format == 'iso': + format = 'yyMdhms' + + tt = {'year':UNDEFINED_DATE.year, 'mon':UNDEFINED_DATE.month, + 'day':UNDEFINED_DATE.day, 'hour':UNDEFINED_DATE.hour, + 'min':UNDEFINED_DATE.minute, 'sec':UNDEFINED_DATE.second} + + def has_hour(tt, hr): + tt['hour'] = dt.hour + return '' + + def has_minute(tt, min): + tt['min'] = dt.minute + return '' + + def has_second(tt, min): + tt['sec'] = dt.second + return '' + + def has_day(tt, dy): + tt['day'] = dt.day + return '' + + def has_month(tt, mo): + tt['mon'] = dt.month + return '' + + def has_year(tt, yr): + tt['year'] = dt.year + return '' + + function_index = { + 'd': has_day, + 'M': has_month, + 'y': has_year, + 'h': has_hour, + 'm': has_minute, + 's': has_second + } + def repl_func(mo): + s = mo.group(0) + if s is None: + return '' + return function_index[s[0]](tt, s) + + re.sub( + '(s{1,2})|(m{1,2})|(h{1,2})|(d{1,4}|M{1,4}|(?:yyyy|yy))', + repl_func, format) + + return datetime(tt['year'], tt['mon'], tt['day'], tt['hour'], tt['min'], tt['sec']) + def replace_months(datestr, clang): # Replace months by english equivalent for parse_date frtoen = {