beets icon indicating copy to clipboard operation
beets copied to clipboard

Add a new `date` field that abstracts over `day`, `month`, and `year` and allows date queries

Open jones1008 opened this issue 7 years ago • 5 comments

In some cases it would be useful to use date and date range querys with the year tag.

So a query like: beet list 'added:-5y..' would also be useful with the year tag: beet list 'year:-5y..' This query would list all tracks from the last 5 years. It is more dynamic than those:

beet list 'year:2013..2018'
beet list 'year:2013..'

Any thoughts on that?

jones1008 avatar Apr 08 '18 14:04 jones1008

Interesting! What do you think about a slightly refined proposal: we create a virtual (i.e., computed) field called date that includes the information from the year, month, and day fields that get stored in files' metadata? This field would work the same way as added or mtime and support these queries, but year itself would remain a plain integer.

sampsyo avatar Apr 08 '18 15:04 sampsyo

This sounds more solid than my version! Very good!

jones1008 avatar Apr 08 '18 16:04 jones1008

OK, this is a good idea. Thanks for the suggestion.

sampsyo avatar Apr 08 '18 21:04 sampsyo

FYI it seems like you can implement this with the following configuration:

plugins: inline types

types:
  date: date

item_fields:
  date: |
    import datetime
    return datetime.datetime(year or 1, month or 1, day or 1).timestamp()

album_fields:
  date: |
    import datetime
    return datetime.datetime(year or 1, month or 1, day or 1).timestamp()

The reason I have all the x or 1 expressions is that many of my tags seem to lack specific dates, and set things like year:1994 month:0 day:0 when only the year is known. I'm not sure what an official implementation of date should do in this case, but it would be nice to figure it out. It's nice that inline makes this possible, but this seems like a case where it should be replaced by a built-in feature.

solson avatar Aug 17 '20 09:08 solson

You can also collapse the definition into a one-liner by using __import__ (and some slight changes to work on my Python, due to negative timezones making year 1 become the illegal year 0 internally in datetime):

plugins: inline types

types:
  date: date

item_fields:
  date: __import__("datetime").datetime(max(year, 2), month or 1, day or 1).timestamp()

album_fields:
  date: __import__("datetime").datetime(max(year, 2), month or 1, day or 1).timestamp()

I did this, and the same for the original_ fields.

eternaleye avatar Feb 11 '24 05:02 eternaleye