Record installation date and time in DB (#7334)
* Added installation date and time to the database Information on the date and time of installation of a spec is recorded into the database. The information is retained on reindexing. * Expose the possibility to query for installation date The DB can now be queried for specs that have been installed in a given time window. This query possibility is exposed to command line via two new options of the `find` command. * Extended docstring for Database._add * Use timestamps since the epoch instead of formatted date in the DB * Allow 'pretty date' formats from command line * Substituted kwargs with explicit arguments * Simplified regex for pretty date strings. Added unit tests.
This commit is contained in:

committed by
Todd Gamblin

parent
6699ba8769
commit
5655895865
@@ -29,7 +29,7 @@
|
||||
import functools
|
||||
import collections
|
||||
import inspect
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
from six import string_types
|
||||
|
||||
# Ignore emacs backups when listing modules
|
||||
@@ -442,6 +442,65 @@ def pretty_date(time, now=None):
|
||||
return str(diff) + " years ago"
|
||||
|
||||
|
||||
def pretty_string_to_date(date_str, now=None):
|
||||
"""Parses a string representing a date and returns a datetime object.
|
||||
|
||||
Args:
|
||||
date_str (str): string representing a date. This string might be
|
||||
in different format (like ``YYYY``, ``YYYY-MM``, ``YYYY-MM-DD``)
|
||||
or be a *pretty date* (like ``yesterday`` or ``two months ago``)
|
||||
|
||||
Returns:
|
||||
(datetime): datetime object corresponding to ``date_str``
|
||||
"""
|
||||
|
||||
pattern = {}
|
||||
|
||||
now = now or datetime.now()
|
||||
|
||||
# datetime formats
|
||||
pattern[re.compile('^\d{4}$')] = lambda x: datetime.strptime(x, '%Y')
|
||||
pattern[re.compile('^\d{4}-\d{2}$')] = lambda x: datetime.strptime(
|
||||
x, '%Y-%m'
|
||||
)
|
||||
pattern[re.compile('^\d{4}-\d{2}-\d{2}$')] = lambda x: datetime.strptime(
|
||||
x, '%Y-%m-%d'
|
||||
)
|
||||
|
||||
pretty_regex = re.compile(
|
||||
r'(a|\d+)\s*(year|month|week|day|hour|minute|second)s?\s*ago')
|
||||
|
||||
def _n_xxx_ago(x):
|
||||
how_many, time_period = pretty_regex.search(x).groups()
|
||||
|
||||
how_many = 1 if how_many == 'a' else int(how_many)
|
||||
|
||||
# timedelta natively supports time periods up to 'weeks'.
|
||||
# To apply month or year we convert to 30 and 365 days
|
||||
if time_period == 'month':
|
||||
how_many *= 30
|
||||
time_period = 'day'
|
||||
elif time_period == 'year':
|
||||
how_many *= 365
|
||||
time_period = 'day'
|
||||
|
||||
kwargs = {(time_period + 's'): how_many}
|
||||
return now - timedelta(**kwargs)
|
||||
|
||||
pattern[pretty_regex] = _n_xxx_ago
|
||||
|
||||
# yesterday
|
||||
callback = lambda x: now - timedelta(days=1)
|
||||
pattern[re.compile('^yesterday$')] = callback
|
||||
|
||||
for regexp, parser in pattern.items():
|
||||
if bool(regexp.match(date_str)):
|
||||
return parser(date_str)
|
||||
|
||||
msg = 'date "{0}" does not match any valid format'.format(date_str)
|
||||
raise ValueError(msg)
|
||||
|
||||
|
||||
class RequiredAttributeError(ValueError):
|
||||
|
||||
def __init__(self, message):
|
||||
|
Reference in New Issue
Block a user