@@ -852,10 +852,7 @@ def _validateFieldValue(self, filterField, values, libtype=None):
852852 if fieldType .type == 'boolean' :
853853 value = int (bool (value ))
854854 elif fieldType .type == 'date' :
855- if isinstance (value , datetime ):
856- value = int (value .timestamp ())
857- else :
858- value = int (utils .toDatetime (value , '%Y-%m-%d' ).timestamp ())
855+ value = self ._validateFieldValueDate (value )
859856 elif fieldType .type == 'integer' :
860857 value = int (value )
861858 elif fieldType .type == 'string' :
@@ -866,12 +863,23 @@ def _validateFieldValue(self, filterField, values, libtype=None):
866863 value = next ((f .key for f in filterChoices
867864 if matchValue in {f .key .lower (), f .title .lower ()}), value )
868865 results .append (str (value ))
869- except ValueError :
866+ except ( ValueError , AttributeError ) :
870867 raise BadRequest ('Invalid value "%s" for filter field "%s", value should be type %s'
871868 % (value , filterField .key , fieldType .type )) from None
872869
873870 return results
874871
872+ def _validateFieldValueDate (self , value ):
873+ """ Validates a filter date value. A filter date value can be a datetime object,
874+ a relative date (e.g. -30d), or a date in YYYY-MM-DD format.
875+ """
876+ if isinstance (value , datetime ):
877+ return int (value .timestamp ())
878+ elif re .match (r'^-?\d+(mon|[smhdwy])$' , value ):
879+ return '-' + value .lstrip ('-' )
880+ else :
881+ return int (utils .toDatetime (value , '%Y-%m-%d' ).timestamp ())
882+
875883 def _validateSortField (self , sort , libtype = None ):
876884 """ Validates a filter sort field is available for the library.
877885 Returns the validated sort field string.
@@ -942,10 +950,7 @@ def search(self, title=None, sort=None, maxresults=None,
942950 * See :func:`~plexapi.library.LibrarySection.listFilterChoices` to get a list of all available filter values.
943951
944952 The following filter fields are just some examples of the possible filters. The list is not exaustive,
945- and not all filters apply to all library types. For tag type filters, a :class:`~plexapi.media.MediaTag`
946- object, the exact name :attr:`MediaTag.tag` (*str*), or the exact id :attr:`MediaTag.id` (*int*) can be
947- provided. For date type filters, either a ``datetime`` object or a date in ``YYYY-MM-DD`` (*str*) format
948- can be provided. Multiple values can be ``OR`` together by providing a list of values.
953+ and not all filters apply to all library types.
949954
950955 * **actor** (:class:`~plexapi.media.MediaTag`): Search for the name of an actor.
951956 * **addedAt** (*datetime*): Search for items added before or after a date. See operators below.
@@ -973,6 +978,24 @@ def search(self, title=None, sort=None, maxresults=None,
973978 * **writer** (:class:`~plexapi.media.MediaTag`): Search for the name of a writer.
974979 * **year** (*int*): Search for a specific year.
975980
981+ Tag type filter values can be a :class:`~plexapi.media.MediaTag` object, the exact name
982+ :attr:`MediaTag.tag` (*str*), or the exact id :attr:`MediaTag.id` (*int*).
983+
984+ Date type filter values can be a ``datetime`` object, a relative date using a one of the
985+ available date suffixes (e.g. ``30d``) (*str*), or a date in ``YYYY-MM-DD`` (*str*) format.
986+
987+ Relative date suffixes:
988+
989+ * ``s``: ``seconds``
990+ * ``m``: ``minutes``
991+ * ``h``: ``hours``
992+ * ``d``: ``days``
993+ * ``w``: ``weeks``
994+ * ``mon``: ``months``
995+ * ``y``: ``years``
996+
997+ Multiple values can be ``OR`` together by providing a list of values.
998+
976999 Examples:
9771000
9781001 .. code-block:: python
@@ -1071,6 +1094,9 @@ def search(self, title=None, sort=None, maxresults=None,
10711094 # Title starts with Marvel and added before 2021-01-01
10721095 library.search(**{"title<": "Marvel", "addedAt<<": "2021-01-01"})
10731096
1097+ # Added in the last 30 days using relative dates
1098+ library.search(**{"addedAt>>": "30d"})
1099+
10741100 # Collection is James Bond and user rating is greater than 8
10751101 library.search(**{"collection": "James Bond", "userRating>>": 8})
10761102
0 commit comments