Search code examples
pythondatetimeldappython-ldap

Querying LDAP by date


The Problem:

Certain LDAP date fields, like createTimestamp or pwdChangedTime, are kept in a "generalized datetime format":

{"createTimestamp": "20100226142156Z"}

Which contains both date and time components inside.

The Question:

What is the canonical way to query LDAP records by a specific date?

Example use case: get all users created yesterday.


Solution

  • First of all, we need a reusable function to convert from datetime to a generalized time format:

    def convert_datetime_to_generalized_time(dt):
        """Convert datetime object to generalized time format."""
        dt = dt.timetuple()
        gtime = str(dt.tm_year) + ''.join('0' * (2 - len(str(item))) + str(item)
                                          for item in (dt.tm_mon, dt.tm_mday, dt.tm_hour, dt.tm_min, dt.tm_sec))
        return gtime + 'Z'
    

    Now, there is no direct way to filter the date component of a generalized time stamp. The idea would be to ask the date to be:

    • greater or equal to than date with a 00:00:00 time part
    • less than or equal to date with a 23:59:59 time part

    Implementation:

    import datetime
    
    def get_ldap_date_range_query(dt):
        start_date = dt.replace(hour=0, minute=0, second=0)
        end_date = dt.replace(hour=23, minute=59, second=59)
    
        return "(&(createTimestamp>=%s)(createTimestamp<=%s))" % (convert_datetime_to_generalized_time(start_date),
                                                                  convert_datetime_to_generalized_time(end_date))
    
    print(get_ldap_date_range_query(datetime.datetime.now() - datetime.timedelta(days=1)))
    

    This would print an LDAP query which would match all users created yesterday:

    (&(createTimestamp>=20160604000000Z)(createTimestamp<=20160604235959Z))
    

    Hope that would help someone in the future.