Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Record installation date and time in DB #7334

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 60 additions & 1 deletion lib/spack/llnl/util/lang.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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):
Expand Down
17 changes: 17 additions & 0 deletions lib/spack/spack/cmd/find.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
import sys

import llnl.util.tty as tty
import llnl.util.lang
import spack
import spack.database
import spack.cmd.common.arguments as arguments
from spack.cmd import display_specs

Expand Down Expand Up @@ -96,6 +98,14 @@ def setup_parser(subparser):
action='store_true',
help='show fully qualified package names')

subparser.add_argument(
'--start-date',
help='earliest date of installation [YYYY-MM-DD]'
)
subparser.add_argument(
'--end-date', help='latest date of installation [YYYY-MM-DD]'
)

arguments.add_common_arguments(subparser, ['constraint'])


Expand All @@ -114,6 +124,13 @@ def query_arguments(args):
if args.implicit:
explicit = False
q_args = {'installed': installed, 'known': known, "explicit": explicit}

# Time window of installation
for attribute in ('start_date', 'end_date'):
date = getattr(args, attribute)
if date:
q_args[attribute] = llnl.util.lang.pretty_string_to_date(date)

return q_args


Expand Down
Loading