HearthSim / python-hslog

Python module to parse Hearthstone Power.log files
https://hearthsim.info
MIT License
60 stars 14 forks source link

Add (failing) test case for unroundable time stamp #3

Closed beheh closed 6 years ago

beheh commented 6 years ago

This PR adds a failing test case for the following issue:

These log lines will fail to parse due to their timestamp:

https://github.com/HearthSim/python-hslog/blob/71c29cadeeb530e4a2d346b60686032513618e91/tests/data.py#L154-L163

The following error occurs:

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
hslog/parser.py:628: in read
    self.read_line(line)
hslog/parser.py:651: in read_line
    ts = self.parse_timestamp(ts, method)
hslog/parser.py:597: in parse_timestamp
    ret = parse_time(ts)
.tox/py36/lib/python3.6/site-packages/aniso8601/time.py:107: in parse_time
    return _parse_time_naive(timestr)
.tox/py36/lib/python3.6/site-packages/aniso8601/time.py:136: in _parse_time_naive
    return _RESOLUTION_MAP[get_time_resolution(timestr)](timestr)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

timestr = '14:43:59.9999997'

    def _parse_second_time(timestr):
        #Format must be hhmmss, hhmmss., hh:mm:ss or hh:mm:ss.
        if timestr.count(':') == 2:
            #hh:mm:ss or hh:mm:ss.
            timestrarray = timestr.split(':')

            isohour = int(timestrarray[0])
            isominute = int(timestrarray[1])

            #Since the time constructor doesn't handle fractional seconds, we put
            #the seconds in to a timedelta, and add it to the time before returning
            secondsdelta = datetime.timedelta(seconds=float(timestrarray[2]))
        else:
            #hhmmss or hhmmss.
            isohour = int(timestr[0:2])
            isominute = int(timestr[2:4])

            #Since the time constructor doesn't handle fractional seconds, we put
            #the seconds in to a timedelta, and add it to the time before returning
            secondsdelta = datetime.timedelta(seconds=float(timestr[4:]))

        if secondsdelta.seconds >= 60:
            #https://bitbucket.org/nielsenb/aniso8601/issues/13/parsing-of-leap-second-gives-wildly
>           raise ValueError('Seconds must be less than 60.')
E           ValueError: Seconds must be less than 60.

isohour    = 14
isominute  = 43
secondsdelta = datetime.timedelta(0, 60)
timestr    = '14:43:59.9999997'
timestrarray = ['14', '43', '59.9999997']

The issue is pretty evident from the first if-branch in _parse_second_time: seconds are converted to a timedelta, and timedelta rounds 59.9999997 to 60. We then fail the secondsdelta.seconds >= 60 check and throw the error.

This should probably be handled because it's breaking some replays.

beheh commented 6 years ago

Refs https://sentry.io/hearthsim/hsreplaynet-lambdas/issues/404983945/ in Sentry.