docs: def quantize_datetime(dt, resolution=None):
      """Quantize a datetime to integer years, months, days, hours, minutes, seconds or microseconds
  
      Also works with a `datetime.timetuple` or `time.struct_time` or a 1to9-tuple of ints or floats.
      Also works with a sequenece of struct_times, tuples, or datetimes
  
      >>> quantize_datetime(datetime.datetime(1970,1,2,3,4,5,6), resolution=3)
      datetime.datetime(1970, 1, 2, 0, 0)
  
      Notice that 6 is the highest resolution value with any utility
      >>> quantize_datetime(datetime.datetime(1970,1,2,3,4,5,6), resolution=7)
      datetime.datetime(1970, 1, 2, 3, 4, 5)
      >>> quantize_datetime(datetime.datetime(1971,2,3,4,5,6,7), 1)
      datetime.datetime(1971, 1, 1, 0, 0)
      """
      # FIXME: this automatically truncates off microseconds just because timtuple() only goes out to sec
      resolution = int(resolution or 6)
      if hasattr(dt, 'timetuple'):
          dt = dt.timetuple()  # strips timezone info
  
      if isinstance(dt, time.struct_time):
          # strip last 3 fields (tm_wday, tm_yday, tm_isdst)
          dt = list(dt)[:6]
          # struct_time has no microsecond, but accepts float seconds
          dt += [int((dt[5] - int(dt[5])) * 1000000)]
          dt[5] = int(dt[5])
          return datetime.datetime(*(dt[:resolution] + [1] * max(3 - resolution, 0)))
  
      if isinstance(dt, tuple) and len(dt) <= 9 and all(isinstance(val, (float, int)) for val in dt):
          dt = list(dt) + [0] * (max(6 - len(dt), 0))
          # if the 6th element of the tuple looks like a float set of seconds need to add microseconds
          if len(dt) == 6 and isinstance(dt[5], float):
              dt = list(dt) + [1000000 * (dt[5] - int(dt[5]))]
              dt[5] = int(dt[5])
          dt = tuple(int(val) for val in dt)
          return datetime.datetime(*(dt[:resolution] + [1] * max(resolution - 3, 0)))
  
      return [quantize_datetime(value) for value in dt]