def generate_monthly(rain_day_threshold, day_end_hour, use_dst,
                     daily_data, monthly_data, process_from):
    """Generate monthly summaries from daily data."""
    start = monthly_data.before(datetime.max)
    if start is None:
        start = datetime.min
    start = daily_data.after(start + SECOND)
    if process_from:
        if start:
            start = min(start, process_from)
        else:
            start = process_from
    if start is None:
        return start
    # set start to start of first day of month (local time)
    start = timezone.local_replace(
        start, use_dst=use_dst, day=1, hour=day_end_hour, minute=0, second=0)
    if day_end_hour >= 12:
        # month actually starts on the last day of previous month
        start -= DAY
    del monthly_data[start:]
    stop = daily_data.before(datetime.max)
    if stop is None:
        return None
    acc = MonthAcc(rain_day_threshold)
    def monthlygen(inputdata):
        """Internal generator function"""
        month_start = start
        count = 0
        while month_start <= stop:
            count += 1
            if count % 12 == 0:
                logger.info("monthly: %s", month_start.isoformat(' '))
            else:
                logger.debug("monthly: %s", month_start.isoformat(' '))
            month_end = month_start + WEEK
            if month_end.month < 12:
                month_end = month_end.replace(month=month_end.month+1)
            else:
                month_end = month_end.replace(month=1, year=month_end.year+1)
            month_end = month_end - WEEK
            if use_dst:
                # month might straddle summer time start or end
                month_end = timezone.local_replace(
                    month_end + HOURx3, use_dst=use_dst, hour=day_end_hour)
            acc.reset()
            for data in inputdata[month_start:month_end]:
                acc.add_daily(data)
            new_data = acc.result()
            if new_data:
                new_data['start'] = month_start
                yield new_data
            month_start = month_end
    monthly_data.update(monthlygen(daily_data))
    return start
Generate monthly summaries from daily data.