def time_series(
            self,
            start_date='-30d',
            end_date='now',
            precision=None,
            distrib=None,
            tzinfo=None):
        """
        Returns a generator yielding tuples of ``(<datetime>, <value>)``.

        The data points will start at ``start_date``, and be at every time interval specified by
        ``precision``.
        ``distrib`` is a callable that accepts ``<datetime>`` and returns ``<value>``

        """
        start_date = self._parse_date_time(start_date, tzinfo=tzinfo)
        end_date = self._parse_date_time(end_date, tzinfo=tzinfo)

        if end_date < start_date:
            raise ValueError("`end_date` must be greater than `start_date`.")

        if precision is None:
            precision = (end_date - start_date) / 30

        precision = self._parse_timedelta(precision)
        if distrib is None:
            def distrib(dt): return self.generator.random.uniform(0, precision)  # noqa

        if not callable(distrib):
            raise ValueError(
                "`distrib` must be a callable. Got {} instead.".format(distrib))

        datapoint = start_date
        while datapoint < end_date:
            dt = timestamp_to_datetime(datapoint, tzinfo)
            datapoint += precision
            yield (dt, distrib(dt))