def test_trunc_ts():
    base = datetime(year=2018, month=7, day=30, hour=13)

    assert trunc_ts(base.replace(minute=36, second=13, microsecond=300000), timedelta(seconds=1)) == \
           base.replace(minute=36, second=13)
    assert trunc_ts(base.replace(minute=36, second=13, microsecond=800000), timedelta(seconds=1)) == \
           base.replace(minute=36, second=13)

    assert trunc_ts(base.replace(minute=36, second=13),
                    timedelta(seconds=10)) == base.replace(minute=36,
                                                           second=10)
    assert trunc_ts(base.replace(minute=36, second=17),
                    timedelta(seconds=10)) == base.replace(minute=36,
                                                           second=10)

    assert trunc_ts(base.replace(minute=36, second=13),
                    timedelta(seconds=20)) == base.replace(minute=36, second=0)
    assert trunc_ts(base.replace(minute=36, second=23),
                    timedelta(seconds=20)) == base.replace(minute=36,
                                                           second=20)

    assert trunc_ts(base.replace(minute=36, second=13),
                    timedelta(minutes=5)) == base.replace(minute=35)
    assert trunc_ts(base.replace(minute=39, second=59),
                    timedelta(minutes=5)) == base.replace(minute=35)
    assert trunc_ts(base.replace(minute=40, second=0),
                    timedelta(minutes=5)) == base.replace(minute=40)
def test_metrics_stats_can_add_values():
    stats = MetricsStats()

    min_ts = trunc_ts(datetime.utcnow(), stats.timestep)
    next_ts = min_ts + stats.timestep
    gap_ts = next_ts + 3 * stats.timestep
    max_ts = gap_ts + stats.timestep

    first_events = [ev for ev in generate_events(10, min_ts) if ev.timestamp < min_ts + stats.timestep]
    next_events = [ev for ev in generate_events(10, next_ts) if ev.timestamp < next_ts + stats.timestep]
    after_gap_events = [ev for ev in generate_events(10, gap_ts) if ev.timestamp < gap_ts + stats.timestep]

    all_events = first_events + next_events + after_gap_events
    for ev in all_events:
        stats.add(ev.timestamp, ev.name, ev.value)

    assert stats.min_ts == min_ts
    assert stats.max_ts == max_ts
    assert sorted(ts for ts, _ in stats.frames()) == [min_ts, next_ts, gap_ts]

    assert stats.frame(min_ts) == _metrics_stats_frame(first_events)
    assert stats.frame(next_ts) == _metrics_stats_frame(next_events)
    assert stats.frame(gap_ts) == _metrics_stats_frame(after_gap_events)
    assert stats.frame(max_ts) == MetricsStatsFrame()

    assert stats.frame(min_ts - 0.2 * stats.timestep) == MetricsStatsFrame()
    assert stats.frame(min_ts + 0.8 * stats.timestep) == _metrics_stats_frame(first_events)
    assert stats.frame(next_ts + 1.1 * stats.timestep) == MetricsStatsFrame()
    assert stats.frame(gap_ts - 0.1 * stats.timestep) == MetricsStatsFrame()
    assert stats.frame(max_ts + 4.2 * stats.timestep) == MetricsStatsFrame()
def test_trunc_ts():
    base = datetime(year=2018, month=7, day=30, hour=13)

    assert trunc_ts(base.replace(minute=36, second=13, microsecond=300000), timedelta(seconds=1)) == \
           base.replace(minute=36, second=13)
    assert trunc_ts(base.replace(minute=36, second=13, microsecond=800000), timedelta(seconds=1)) == \
           base.replace(minute=36, second=13)

    assert trunc_ts(base.replace(minute=36, second=13), timedelta(seconds=10)) == base.replace(minute=36, second=10)
    assert trunc_ts(base.replace(minute=36, second=17), timedelta(seconds=10)) == base.replace(minute=36, second=10)

    assert trunc_ts(base.replace(minute=36, second=13), timedelta(seconds=20)) == base.replace(minute=36, second=0)
    assert trunc_ts(base.replace(minute=36, second=23), timedelta(seconds=20)) == base.replace(minute=36, second=20)

    assert trunc_ts(base.replace(minute=36, second=13), timedelta(minutes=5)) == base.replace(minute=35)
    assert trunc_ts(base.replace(minute=39, second=59), timedelta(minutes=5)) == base.replace(minute=35)
    assert trunc_ts(base.replace(minute=40, second=0), timedelta(minutes=5)) == base.replace(minute=40)