# Path: protector/influxdb/daterange.py
# class DateRange(object):
#     """
#     A thin abstraction layer for date ranges
#     """
# 
#     def __init__(self, start, end):
#         self.start = start
#         self.end = end
# 
#     def timespan(self):
#         return self.end - self.start
# 
#     def timespan_seconds(self):
#         t = self.timespan()
#         # A duration can never be negative
#         return max(0, t.total_seconds())
# 
#     def __str__(self):
#         return "Start: {}, End: {}, (Time span: {})".format(self.start, self.end, self.timespan())
# 
#     def __repr__(self):
#         return self.__str__()
# 
#     def __eq__(self, other):
#         if isinstance(other, self.__class__):
#             return (self.start == other.start) and (self.end == other.end)
#         else:
#             return False
# 
#     def __ne__(self, other):
#         return not self.__eq__(other)
# 
# Path: protector/influxdb/time_expression.py
# class TimeExpression(object):
#     # Smallest possible system date.
#     # This is required for the calculation of the max duration between datetime objects.
#     # We use the release day of InfluxDB 0.8 as the epoch
#     # because it is the first official version supported by this tool.
#     INFLUXDB_EPOCH = datetime.strptime('2014-08-22', "%Y-%m-%d")
# 
#     # Full names of all supported relative time units.
#     # Useful for conversions of the internal InfluxDB format to the Python timedelta format.
#     UNIT_NAMES = {
#         'u': 'microseconds',
#         's': 'seconds',
#         'm': 'minutes',
#         'h': 'hours',
#         'd': 'days',
#         'w': 'weeks'
#     }
# 
#     # Conversions of all InfluxDB relative time units to seconds.
#     # Useful for datapoint calculations.
#     UNIT_CONVERSION = {'u': 0.001, 's': 1, 'm': 60, 'h': 3600, 'd': 86400, 'w': 604800}
# 
# Path: protector/parser/subparsers/time_range.py
# class TimeRangeParser(object):
#     """
#     Creates a list of TimeExpression objects from InfluxDB time statements.
#     Example:
# 
#     "time > now() - 2h" will create [ TimeExpressionBigger(datetime_obj)]
#     """
# 
#     def __init__(self):
#         self.epoch = TimeExpression.INFLUXDB_EPOCH
# 
#     def parse(self, where_stmt):
#         if not where_stmt:
#             return []
#         return self.parse_time_expressions(where_stmt)
# 
#     def parse_time_expressions(self, where_stmt):
#         raw_statements = self.split_statements(where_stmt)
#         time_expressions = []
#         for raw_statement in raw_statements:
#             time_expression = self.parse_time_expression(raw_statement)
#             if time_expression:
#                 time_expressions.append(time_expression)
#         return time_expressions
# 
#     def parse_time_expression(self, raw_statement):
#         match = TimeGrammar.TIME_STATEMENT.match(raw_statement)
#         if not match:
#             return
#         comparison_operator = match.group(1)
#         time_expression = match.group(2)
#         return self.create_time_expression(comparison_operator, time_expression)
# 
#     def create_time_expression(self, comparison_operator, time_expression):
#         for pattern_name, pattern in TimeGrammar.TIME_PATTERNS:
#             match = pattern.match(time_expression)
#             if match:
#                 datetime_obj = getattr(self, 'parse_%s' % pattern_name)(match)
#                 return self._create_time(comparison_operator, datetime_obj)
# 
#     @staticmethod
#     def split_statements(raw_statements):
#         return [stmt.strip() for stmt in raw_statements.split(TimeGrammar.KEYWORD_AND)]
# 
#     def parse_relative_time(self, match):
#         sign, number, unit = match.groups()
#         if sign:
#             number = int(sign + number)
#         # If no unit is given, the value is interpreted as microseconds.
#         if not unit:
#             unit = 'u'
#         now = datetime.now()
#         delta = self._create_timedelta(number, unit)
#         return now + delta
# 
#     @staticmethod
#     def _create_timedelta(value, unit):
#         if unit not in TimeExpression.UNIT_NAMES.keys():
#             # Invalid query
#             return None
#         params = {TimeExpression.UNIT_NAMES[unit]: value}
#         return timedelta(**params)
# 
#     @staticmethod
#     def parse_date_time(match):
#         text = match.group(1)
#         for fmt in ('%Y-%m-%d', '%Y-%m-%d %H:%M:%S', '%Y-%m-%d %H:%M:%S.%f'):
#             try:
#                 return datetime.strptime(text, fmt)
#             except ValueError:
#                 pass
#         raise ValueError('No valid date format found')
# 
#     @staticmethod
#     def parse_unix_time(match):
#         ts_string = match.group(1)
#         # Truncate milliseconds
#         ts = int(ts_string[:10])
#         return datetime.fromtimestamp(ts)
# 
#     def _create_time(self, comparison_operator, datetime_obj):
#         if comparison_operator == '=':
#             return DateRange(datetime_obj, datetime_obj)
#         elif comparison_operator == '>':
#             return DateRange(datetime_obj, datetime.now())
#         elif comparison_operator == '<':
#             return DateRange(self.epoch, datetime_obj)
#         else:
#             # Invalid format
#             return None


from freezegun import freeze_time
from datetime import datetime, timedelta
from protector.influxdb.daterange import DateRange
from protector.influxdb.time_expression import TimeExpression
from protector.parser.subparsers.time_range import TimeRangeParser
import unittest



@freeze_time("2015-12-24")  # Ho ho ho!
class TestParseTimeRange(unittest.TestCase):
    def test_invalid_duration(self):
        """
        Test invalid time durations
        """
        self.assertEqual(TimeRangeParser().parse(None), [])
        self.assertEqual(TimeRangeParser().parse("hello"), [])

# Path: protector/influxdb/daterange.py
# class DateRange(object):
#     """
#     A thin abstraction layer for date ranges
#     """
# 
#     def __init__(self, start, end):
#         self.start = start
#         self.end = end
# 
#     def timespan(self):
#         return self.end - self.start
# 
#     def timespan_seconds(self):
#         t = self.timespan()
#         # A duration can never be negative
#         return max(0, t.total_seconds())
# 
#     def __str__(self):
#         return "Start: {}, End: {}, (Time span: {})".format(self.start, self.end, self.timespan())
# 
#     def __repr__(self):
#         return self.__str__()
# 
#     def __eq__(self, other):
#         if isinstance(other, self.__class__):
#             return (self.start == other.start) and (self.end == other.end)
#         else:
#             return False
# 
#     def __ne__(self, other):
#         return not self.__eq__(other)
# 
# Path: protector/influxdb/time_expression.py
# class TimeExpression(object):
#     # Smallest possible system date.
#     # This is required for the calculation of the max duration between datetime objects.
#     # We use the release day of InfluxDB 0.8 as the epoch
#     # because it is the first official version supported by this tool.
#     INFLUXDB_EPOCH = datetime.strptime('2014-08-22', "%Y-%m-%d")
# 
#     # Full names of all supported relative time units.
#     # Useful for conversions of the internal InfluxDB format to the Python timedelta format.
#     UNIT_NAMES = {
#         'u': 'microseconds',
#         's': 'seconds',
#         'm': 'minutes',
#         'h': 'hours',
#         'd': 'days',
#         'w': 'weeks'
#     }
# 
#     # Conversions of all InfluxDB relative time units to seconds.
#     # Useful for datapoint calculations.
#     UNIT_CONVERSION = {'u': 0.001, 's': 1, 'm': 60, 'h': 3600, 'd': 86400, 'w': 604800}
# 
# Path: protector/parser/subparsers/time_range.py
# class TimeRangeParser(object):
#     """
#     Creates a list of TimeExpression objects from InfluxDB time statements.
#     Example:
# 
#     "time > now() - 2h" will create [ TimeExpressionBigger(datetime_obj)]
#     """
# 
#     def __init__(self):
#         self.epoch = TimeExpression.INFLUXDB_EPOCH
# 
#     def parse(self, where_stmt):
#         if not where_stmt:
#             return []
#         return self.parse_time_expressions(where_stmt)
# 
#     def parse_time_expressions(self, where_stmt):
#         raw_statements = self.split_statements(where_stmt)
#         time_expressions = []
#         for raw_statement in raw_statements:
#             time_expression = self.parse_time_expression(raw_statement)
#             if time_expression:
#                 time_expressions.append(time_expression)
#         return time_expressions
# 
#     def parse_time_expression(self, raw_statement):
#         match = TimeGrammar.TIME_STATEMENT.match(raw_statement)
#         if not match:
#             return
#         comparison_operator = match.group(1)
#         time_expression = match.group(2)
#         return self.create_time_expression(comparison_operator, time_expression)
# 
#     def create_time_expression(self, comparison_operator, time_expression):
#         for pattern_name, pattern in TimeGrammar.TIME_PATTERNS:
#             match = pattern.match(time_expression)
#             if match:
#                 datetime_obj = getattr(self, 'parse_%s' % pattern_name)(match)
#                 return self._create_time(comparison_operator, datetime_obj)
# 
#     @staticmethod
#     def split_statements(raw_statements):
#         return [stmt.strip() for stmt in raw_statements.split(TimeGrammar.KEYWORD_AND)]
# 
#     def parse_relative_time(self, match):
#         sign, number, unit = match.groups()
#         if sign:
#             number = int(sign + number)
#         # If no unit is given, the value is interpreted as microseconds.
#         if not unit:
#             unit = 'u'
#         now = datetime.now()
#         delta = self._create_timedelta(number, unit)
#         return now + delta
# 
#     @staticmethod
#     def _create_timedelta(value, unit):
#         if unit not in TimeExpression.UNIT_NAMES.keys():
#             # Invalid query
#             return None
#         params = {TimeExpression.UNIT_NAMES[unit]: value}
#         return timedelta(**params)
# 
#     @staticmethod
#     def parse_date_time(match):
#         text = match.group(1)
#         for fmt in ('%Y-%m-%d', '%Y-%m-%d %H:%M:%S', '%Y-%m-%d %H:%M:%S.%f'):
#             try:
#                 return datetime.strptime(text, fmt)
#             except ValueError:
#                 pass
#         raise ValueError('No valid date format found')
# 
#     @staticmethod
#     def parse_unix_time(match):
#         ts_string = match.group(1)
#         # Truncate milliseconds
#         ts = int(ts_string[:10])
#         return datetime.fromtimestamp(ts)
# 
#     def _create_time(self, comparison_operator, datetime_obj):
#         if comparison_operator == '=':
#             return DateRange(datetime_obj, datetime_obj)
#         elif comparison_operator == '>':
#             return DateRange(datetime_obj, datetime.now())
#         elif comparison_operator == '<':
#             return DateRange(self.epoch, datetime_obj)
#         else:
#             # Invalid format
#             return None


# Path: protector/tests/parser_test/subparser_test/test_time_range_parser.py
from freezegun import freeze_time
from datetime import datetime, timedelta
from protector.influxdb.daterange import DateRange
from protector.influxdb.time_expression import TimeExpression
from protector.parser.subparsers.time_range import TimeRangeParser
import unittest




@freeze_time("2015-12-24")  # Ho ho ho!
class TestParseTimeRange(unittest.TestCase):
    def test_invalid_duration(self):
        """
        Test invalid time durations
        """
        self.assertEqual(TimeRangeParser().parse(None), [])
        self.assertEqual(TimeRangeParser().parse("hello"), [])

        self.assertEqual(TimeRangeParser().parse("tim"), [])