-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Relative date queries (continuation of #2418) #2598
Changes from 23 commits
47b0b54
5624e24
03dfaf9
bee758a
9bc75b0
868746b
8d054f3
2b89b90
3e76c21
af679de
d48d1f8
e4a7d37
c9177f2
f0aca5e
d2cd4c0
6664b65
92c118f
527d0a8
ae3f9bf
6f97787
26940b6
8a6c8cd
130c581
01cf0d0
93f064f
eaae3fb
690ed73
b1b4272
a52d3d5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -562,6 +562,9 @@ class Period(object): | |
('%Y-%m-%dT%H:%M', '%Y-%m-%d %H:%M'), # minute | ||
('%Y-%m-%dT%H:%M:%S', '%Y-%m-%d %H:%M:%S') # second | ||
) | ||
relative = {'y': 365, 'm': 30, 'w': 7, 'd': 1} | ||
relative_re = '(?P<sign>[+|-]?)(?P<quantity>[0-9]+)' + \ | ||
'(?P<timespan>[y|m|w|d])' | ||
|
||
def __init__(self, date, precision): | ||
"""Create a period with the given date (a `datetime` object) and | ||
|
@@ -575,9 +578,20 @@ def __init__(self, date, precision): | |
|
||
@classmethod | ||
def parse(cls, string): | ||
"""Parse a date and return a `Period` object, or `None` if the | ||
"""Parse a date and return a `Period` object or `None` if the | ||
string is empty, or raise an InvalidQueryArgumentValueError if | ||
the string could not be parsed to a date. | ||
the string cannot be parsed to a date. | ||
|
||
The date may be absolute or relative. Absolute dates look like | ||
`YYYY`, or `YYYY-MM-DD`, or `YYYY-MM-DD HH:MM:SS`, etc. Relative | ||
dates have three parts: | ||
|
||
- Optionally, a ``+`` or ``-`` sign indicating the future or the | ||
past. The default is the future. | ||
- A number: how much to add or subtract. | ||
- A letter indicating the unit: days, weeks, months or years | ||
(``d``, ``w``, ``m`` or ``y``). A "month" is exactly 30 days | ||
and a "year" is exactly 365 days. | ||
""" | ||
|
||
def find_date_and_format(string): | ||
|
@@ -593,10 +607,27 @@ def find_date_and_format(string): | |
|
||
if not string: | ||
return None | ||
|
||
# Check for a relative date. | ||
match_dq = re.match(cls.relative_re, string) | ||
if match_dq: | ||
sign = match_dq.group('sign') | ||
quantity = match_dq.group('quantity') | ||
timespan = match_dq.group('timespan') | ||
|
||
# Add or subtract the given amount of time from the current | ||
# date. | ||
multiplier = -1 if sign == '-' else 1 | ||
days = cls.relative[timespan] | ||
date = datetime.now() + \ | ||
timedelta(days=int(quantity) * days) * multiplier | ||
string = date.strftime(cls.date_formats[5][0]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @euri10: Turning things back into a string seems a little odd. Can we just There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done, at first I didn't know if the ordinal was used anywhere, so turning things back into a string was a way to use the find_date_and_format function that already exists |
||
|
||
# Check for an absolute date. | ||
date, ordinal = find_date_and_format(string) | ||
if date is None: | ||
raise InvalidQueryArgumentValueError(string, | ||
'a valid datetime string') | ||
'a valid date/time string') | ||
precision = cls.precisions[ordinal] | ||
return cls(date, precision) | ||
|
||
|
@@ -606,6 +637,8 @@ def open_right_endpoint(self): | |
""" | ||
precision = self.precision | ||
date = self.date | ||
if 'relative' == self.precision: | ||
return date | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. indeed, no use |
||
if 'year' == self.precision: | ||
return date.replace(year=date.year + 1, month=1) | ||
elif 'month' == precision: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -164,6 +164,29 @@ Dates are written separated by hyphens, like ``year-month-day``, but the month | |
and day are optional. If you leave out the day, for example, you will get | ||
matches for the whole month. | ||
|
||
You can also use relative dates to the current time. | ||
A relative date begins with an ``@``. | ||
It looks like ``@-3w``, ``@2m`` or ``@-4d`` which means the date 3 weeks ago, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like we need to remove the @ here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yep, corrected |
||
the date 2 months from now and the date 4 days ago. | ||
A relative date consists of three parts: | ||
- ``+`` or ``-`` sign is optional and defaults to ``+``. The ``+`` sign will | ||
add a time quantity to the current date while the ``-`` sign will do the | ||
opposite | ||
- a number follows and indicates the amount to add or substract | ||
- a final letter ends and represents the amount in either days, weeks, months or | ||
years (``d``, ``w``, ``m`` or ``y``) | ||
|
||
Please note that this relative calculation makes the assumption of 30 days per | ||
month and 365 days per year. | ||
|
||
Here is an example that finds all the albums added between now and last week:: | ||
|
||
$ beet ls -a 'added:-1w..' | ||
|
||
Find all items added in a 2 weeks period 4 weeks ago:: | ||
|
||
$ beet ls -a 'added:-6w..-4w' | ||
|
||
Date *intervals*, like the numeric intervals described above, are separated by | ||
two dots (``..``). You can specify a start, an end, or both. | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A better name might be
relative_units
.