# Path: moira/graphite/attime.py
# def parseTimeOffset(offset):
#     if not offset:
#         return timedelta()
# 
#     t = timedelta()
# 
#     if offset[0].isdigit():
#         sign = 1
#     else:
#         sign = {'+': 1, '-': -1}[offset[0]]
#         offset = offset[1:]
# 
#     while offset:
#         i = 1
#         while offset[:i].isdigit() and i <= len(offset):
#             i += 1
#         num = int(offset[:i - 1])
#         offset = offset[i - 1:]
#         i = 1
#         while offset[:i].isalpha() and i <= len(offset):
#             i += 1
#         unit = offset[:i - 1]
#         offset = offset[i - 1:]
#         unitString = getUnitString(unit)
#         if unitString == 'months':
#             unitString = 'days'
#             num = num * 30
#         if unitString == 'years':
#             unitString = 'days'
#             num = num * 365
#         t += timedelta(**{unitString: sign * num})
# 
#     return t
# 
# def parseATTime(s, tzinfo=None):
#     if tzinfo is None:
#         tzinfo = pytz.utc
#     s = s.strip().lower().replace('_', '').replace(',', '').replace(' ', '')
#     if s.isdigit():
#         if len(s) == 8 and int(s[:4]) > 1900 and int(
#                 s[4:6]) < 13 and int(s[6:]) < 32:
#             pass  # Fall back because its not a timestamp, its YYYYMMDD form
#         else:
#             return datetime.fromtimestamp(int(s), tzinfo)
#     elif ':' in s and len(s) == 13:
#         return tzinfo.localize(datetime.strptime(s, '%H:%M%Y%m%d'), daylight)
#     if '+' in s:
#         ref, offset = s.split('+', 1)
#         offset = '+' + offset
#     elif '-' in s:
#         ref, offset = s.split('-', 1)
#         offset = '-' + offset
#     else:
#         ref, offset = s, ''
#     return (
#         parseTimeReference(ref) +
#         parseTimeOffset(offset)).astimezone(tzinfo)
# 
# Path: moira/graphite/datalib.py
# class TimeSeries(list):
# 
#     def __init__(self, name, start, end, step, values, consolidate='average'):
#         list.__init__(self, values)
#         self.name = name
#         self.start = start
#         self.end = end
#         self.step = step
#         self.consolidationFunc = consolidate
#         self.valuesPerPoint = 1
#         self.options = {}
#         self.stub = False
# 
#     def __iter__(self):
#         if self.valuesPerPoint > 1:
#             return self.__consolidatingGenerator(list.__iter__(self))
#         else:
#             return list.__iter__(self)
# 
#     def consolidate(self, valuesPerPoint):
#         self.valuesPerPoint = int(valuesPerPoint)
# 
#     def __consolidatingGenerator(self, gen):
#         buf = []
#         for x in gen:
#             buf.append(x)
#             if len(buf) == self.valuesPerPoint:
#                 while None in buf:
#                     buf.remove(None)
#                 if buf:
#                     yield self.__consolidate(buf)
#                     buf = []
#                 else:
#                     yield None
#         while None in buf:
#             buf.remove(None)
#         if buf:
#             yield self.__consolidate(buf)
#         else:
#             yield None
#         raise StopIteration
# 
#     def __consolidate(self, values):
#         usable = [v for v in values if v is not None]
#         if not usable:
#             return None
#         if self.consolidationFunc == 'sum':
#             return sum(usable)
#         if self.consolidationFunc == 'average':
#             return float(sum(usable)) / len(usable)
#         if self.consolidationFunc == 'max':
#             return max(usable)
#         if self.consolidationFunc == 'min':
#             return min(usable)
#         raise Exception("Invalid consolidation function!")
# 
#     def __repr__(self):
#         return 'TimeSeries(name=%s, start=%s, end=%s, step=%s)' % (
#             self.name, self.start, self.end, self.step)
# 
#     def getInfo(self):
#         """Pickle-friendly representation of the series"""
#         return {
#             'name': self.name,
#             'start': self.start,
#             'end': self.end,
#             'step': self.step,
#             'values': list(self),
#         }


import math
import random
import re
import time
from datetime import datetime, timedelta
from itertools import izip, imap
from moira.graphite.attime import parseTimeOffset, parseATTime
from moira.graphite.util import epoch
from moira.graphite.datalib import TimeSeries
from twisted.internet import defer
from twisted.internet.defer import inlineCallbacks, returnValue
from functools import reduce
from moira.graphite.evaluator import evaluateTarget
                    shiftedSeries.start + series.start
            shiftedSeries.start = series.start
            results.append(shiftedSeries)

    returnValue(results)


@inlineCallbacks
def timeSlice(requestContext, seriesList, startSliceAt, endSliceAt="now"):
    """
    Takes one metric or a wildcard metric, followed by a quoted string with the
    time to start the line and another quoted string with the time to end the line.
    The start and end times are inclusive. See ``from / until`` in the render\_api_
    for examples of time formats.

    Useful for filtering out a part of a series of data from a wider range of
    data.

    Example:

    .. code-block:: none

      &target=timeSlice(network.core.port1,"00:00 20140101","11:59 20140630")
      &target=timeSlice(network.core.port1,"12:00 20140630","now")

    """

    yield defer.succeed(None)
    results = []
    start = time.mktime(parseATTime(startSliceAt).timetuple())

# Path: moira/graphite/attime.py
# def parseTimeOffset(offset):
#     if not offset:
#         return timedelta()
# 
#     t = timedelta()
# 
#     if offset[0].isdigit():
#         sign = 1
#     else:
#         sign = {'+': 1, '-': -1}[offset[0]]
#         offset = offset[1:]
# 
#     while offset:
#         i = 1
#         while offset[:i].isdigit() and i <= len(offset):
#             i += 1
#         num = int(offset[:i - 1])
#         offset = offset[i - 1:]
#         i = 1
#         while offset[:i].isalpha() and i <= len(offset):
#             i += 1
#         unit = offset[:i - 1]
#         offset = offset[i - 1:]
#         unitString = getUnitString(unit)
#         if unitString == 'months':
#             unitString = 'days'
#             num = num * 30
#         if unitString == 'years':
#             unitString = 'days'
#             num = num * 365
#         t += timedelta(**{unitString: sign * num})
# 
#     return t
# 
# def parseATTime(s, tzinfo=None):
#     if tzinfo is None:
#         tzinfo = pytz.utc
#     s = s.strip().lower().replace('_', '').replace(',', '').replace(' ', '')
#     if s.isdigit():
#         if len(s) == 8 and int(s[:4]) > 1900 and int(
#                 s[4:6]) < 13 and int(s[6:]) < 32:
#             pass  # Fall back because its not a timestamp, its YYYYMMDD form
#         else:
#             return datetime.fromtimestamp(int(s), tzinfo)
#     elif ':' in s and len(s) == 13:
#         return tzinfo.localize(datetime.strptime(s, '%H:%M%Y%m%d'), daylight)
#     if '+' in s:
#         ref, offset = s.split('+', 1)
#         offset = '+' + offset
#     elif '-' in s:
#         ref, offset = s.split('-', 1)
#         offset = '-' + offset
#     else:
#         ref, offset = s, ''
#     return (
#         parseTimeReference(ref) +
#         parseTimeOffset(offset)).astimezone(tzinfo)
# 
# Path: moira/graphite/datalib.py
# class TimeSeries(list):
# 
#     def __init__(self, name, start, end, step, values, consolidate='average'):
#         list.__init__(self, values)
#         self.name = name
#         self.start = start
#         self.end = end
#         self.step = step
#         self.consolidationFunc = consolidate
#         self.valuesPerPoint = 1
#         self.options = {}
#         self.stub = False
# 
#     def __iter__(self):
#         if self.valuesPerPoint > 1:
#             return self.__consolidatingGenerator(list.__iter__(self))
#         else:
#             return list.__iter__(self)
# 
#     def consolidate(self, valuesPerPoint):
#         self.valuesPerPoint = int(valuesPerPoint)
# 
#     def __consolidatingGenerator(self, gen):
#         buf = []
#         for x in gen:
#             buf.append(x)
#             if len(buf) == self.valuesPerPoint:
#                 while None in buf:
#                     buf.remove(None)
#                 if buf:
#                     yield self.__consolidate(buf)
#                     buf = []
#                 else:
#                     yield None
#         while None in buf:
#             buf.remove(None)
#         if buf:
#             yield self.__consolidate(buf)
#         else:
#             yield None
#         raise StopIteration
# 
#     def __consolidate(self, values):
#         usable = [v for v in values if v is not None]
#         if not usable:
#             return None
#         if self.consolidationFunc == 'sum':
#             return sum(usable)
#         if self.consolidationFunc == 'average':
#             return float(sum(usable)) / len(usable)
#         if self.consolidationFunc == 'max':
#             return max(usable)
#         if self.consolidationFunc == 'min':
#             return min(usable)
#         raise Exception("Invalid consolidation function!")
# 
#     def __repr__(self):
#         return 'TimeSeries(name=%s, start=%s, end=%s, step=%s)' % (
#             self.name, self.start, self.end, self.step)
# 
#     def getInfo(self):
#         """Pickle-friendly representation of the series"""
#         return {
#             'name': self.name,
#             'start': self.start,
#             'end': self.end,
#             'step': self.step,
#             'values': list(self),
#         }


# Path: moira/graphite/functions.py
import math
import random
import re
import time
from datetime import datetime, timedelta
from itertools import izip, imap
from moira.graphite.attime import parseTimeOffset, parseATTime
from moira.graphite.util import epoch
from moira.graphite.datalib import TimeSeries
from twisted.internet import defer
from twisted.internet.defer import inlineCallbacks, returnValue
from functools import reduce
from moira.graphite.evaluator import evaluateTarget

                    shiftedSeries.start + series.start
            shiftedSeries.start = series.start
            results.append(shiftedSeries)

    returnValue(results)


@inlineCallbacks
def timeSlice(requestContext, seriesList, startSliceAt, endSliceAt="now"):
    """
    Takes one metric or a wildcard metric, followed by a quoted string with the
    time to start the line and another quoted string with the time to end the line.
    The start and end times are inclusive. See ``from / until`` in the render\_api_
    for examples of time formats.

    Useful for filtering out a part of a series of data from a wider range of
    data.

    Example:

    .. code-block:: none

      &target=timeSlice(network.core.port1,"00:00 20140101","11:59 20140630")
      &target=timeSlice(network.core.port1,"12:00 20140630","now")

    """

    yield defer.succeed(None)
    results = []
    start = time.mktime(parseATTime(startSliceAt).timetuple())

    end = time.mktime(parseATTime(endSliceAt).timetuple())