'''
Test suite for pyRFC3339.

'''

from datetime import datetime

from pyrfc3339 import generate, parse
from pyrfc3339.utils import timezone
import pytz

from nose.tools import eq_, raises


class TestCore():
    '''
    This test suite contains tests to address cases not tested in the doctests,
    as well as additional tests for end-to-end verification.

    '''
    def test_timezone_rounding(self):
        '''
        Test rounding of timezone values to the nearest second.

        '''
        eq_(timezone(5429), '+01:30')
        eq_(timezone(5431), '+01:31')

    def test_zero_offset(self):
        '''
        Both +00:00 and -00:00 are equivalent to the offset 'Z' (UTC).

        '''
        timestamp = '2009-01-01T10:02:03+00:00'
        dt = parse(timestamp)
        eq_(dt.tzinfo, pytz.utc)

        timestamp = '2009-01-01T10:02:03-00:00'
        dt = parse(timestamp)
        eq_(dt.tzinfo, pytz.utc)

    def test_parse_microseconds(self):
        '''
        Test parsing timestamps with microseconds.

        '''
        timestamp = '2009-01-01T10:02:03.25Z'
        dt = parse(timestamp)
        eq_(dt.microsecond, 250000)

    def test_generate_microseconds(self):
        '''
        Test generating timestamps with microseconds.

        '''
        dt = datetime(2009, 1, 1, 10, 2, 3, 500000, pytz.utc)
        timestamp = generate(dt, microseconds=True)
        eq_(timestamp, '2009-01-01T10:02:03.500000Z')

    def test_mixed_case(self):
        '''
        Timestamps may use either 'T' or 't' and either 'Z' or 'z'
        according to :RFC:`3339`.

        '''
        dt1 = parse('2009-01-01t10:01:02z')
        dt2 = datetime(2009, 1, 1, 10, 1, 2, tzinfo=pytz.utc)

        eq_(dt1, dt2)

    def test_parse_naive_utc(self):
        '''
        Test parsing a UTC timestamp to a naive datetime.

        '''
        dt1 = parse('2009-01-01T10:01:02Z', produce_naive=True)
        eq_(dt1.tzinfo, None)

    @raises(ValueError)
    def test_parse_naive_local(self):
        '''
        Test that parsing a local timestamp to a naive datetime fails.

        '''
        parse('2009-01-01T10:01:02-04:00', produce_naive=True)

    def test_generate_utc_parse_utc(self):
        '''
        Generate a UTC timestamp and parse it into a UTC datetime.

        '''
        dt1 = datetime.utcnow()
        dt1 = dt1.replace(tzinfo=pytz.utc)

        dt2 = parse(generate(dt1, microseconds=True))
        eq_(dt1, dt2)

    def test_generate_local_parse_local(self):
        '''
        Generate a local timestamp and parse it into a local datetime.

        '''
        eastern = pytz.timezone('US/Eastern')
        dt1 = eastern.localize(datetime.utcnow())
        dt2 = parse(generate(dt1, utc=False, microseconds=True), utc=False)
        eq_(dt1, dt2)

    def test_generate_local_parse_utc(self):
        '''
        Generate a local timestamp and parse it into a UTC datetime.

        '''
        eastern = pytz.timezone('US/Eastern')
        dt1 = eastern.localize(datetime.utcnow())
        dt2 = parse(generate(dt1, utc=False, microseconds=True))
        eq_(dt1, dt2)


class TestExhaustiveRoundtrip():
    '''
    This test suite exhaustively tests parsing and generation by generating
    a local RFC 3339 timestamp for every timezone supported by pytz,
    and parsing that timestamp into a local datetime and a UTC datetime.
    '''

    slow = True

    def test_local_roundtrip(self):
        for tz_name in pytz.all_timezones:
            yield self.local_roundtrip, tz_name

    def local_roundtrip(self, tz_name):
        '''
        Generates a local datetime using the given timezone,
        produces a local timestamp from the datetime, parses the timestamp
        to a local datetime, and verifies that the two datetimes are equal.

        '''
        tzinfo = pytz.timezone(tz_name)
        dt1 = tzinfo.localize(datetime.utcnow())
        timestamp = generate(dt1, utc=False, microseconds=True)
        dt2 = parse(timestamp, utc=False)
        eq_(dt1, dt2)

    def test_utc_roundtrip(self):
        for tz_name in pytz.all_timezones:
            yield self.utc_roundtrip, tz_name

    def utc_roundtrip(self, tz_name):
        '''
        Generates a local datetime using the given timezone,
        produces a local timestamp from the datetime, parses the timestamp
        to a UTC datetime, and verifies that the two datetimes are equal.

        '''
        tzinfo = pytz.timezone(tz_name)
        dt1 = tzinfo.localize(datetime.utcnow())
        timestamp = generate(dt1, utc=False, microseconds=True)
        dt2 = parse(timestamp)
        eq_(dt1, dt2)
