Exemplo n.º 1
0
def _parse_minute_time(timestr, tz, builder):
    # Format must be hhmm, hhmm., hh:mm or hh:mm.
    if timestr.count(':') == 1:
        # hh:mm or hh:mm.
        hourstr, minutestr = timestr.split(':')
    else:
        # hhmm or hhmm.
        hourstr = timestr[0:2]
        minutestr = timestr[2:]

    return builder.build_time(hh=normalize(hourstr), mm=normalize(minutestr), tz=tz)
Exemplo n.º 2
0
def _parse_second_time(timestr, tz, builder):
    # Format must be hhmmss, hhmmss., hh:mm:ss or hh:mm:ss.
    if timestr.count(':') == 2:
        # hh:mm:ss or hh:mm:ss.
        hourstr, minutestr, secondstr = timestr.split(':')
    else:
        # hhmmss or hhmmss.
        hourstr = timestr[0:2]
        minutestr = timestr[2:4]
        secondstr = timestr[4:]

    return builder.build_time(hh=normalize(hourstr), mm=normalize(minutestr),
                              ss=normalize(secondstr), tz=tz)
Exemplo n.º 3
0
def _parse_duration_prescribed_time(isodurationstr):
    #durationstr can be of the form PnYnMnDTnHnMnS

    timeidx = isodurationstr.find('T')

    datestr = isodurationstr[:timeidx]
    timestr = normalize(isodurationstr[timeidx + 1:])

    hourstr = None
    minutestr = None
    secondstr = None

    houridx = timestr.find('H')
    minuteidx = timestr.find('M')
    secondidx = timestr.find('S')

    if houridx != -1 and minuteidx != -1 and secondidx != -1:
        hourstr = timestr[0:houridx]
        minutestr = timestr[houridx + 1:minuteidx]
        secondstr = timestr[minuteidx + 1:-1]
    elif houridx != -1 and minuteidx != -1:
        hourstr = timestr[0:houridx]
        minutestr = timestr[houridx + 1:minuteidx]
    elif minuteidx != -1 and secondidx != -1:
        minutestr = timestr[0:minuteidx]
        secondstr = timestr[minuteidx + 1:-1]
    elif houridx != -1:
        hourstr = timestr[0:-1]
    elif minuteidx != -1:
        minutestr = timestr[0:-1]
    elif secondidx != -1:
        secondstr = timestr[0:-1]
    else:
        raise ISOFormatError(
            '"{0}" is not a valid ISO 8601 duration.'.format(isodurationstr))

    for componentstr in [hourstr, minutestr, secondstr]:
        if componentstr is not None:
            if '.' in componentstr:
                intstr, fractionalstr = componentstr.split('.', 1)

                if intstr.isdigit() is False:
                    raise ISOFormatError(
                        '"{0}" is not a valid ISO 8601 duration.'.format(
                            isodurationstr))
            else:
                if componentstr.isdigit() is False:
                    raise ISOFormatError(
                        '"{0}" is not a valid ISO 8601 duration.'.format(
                            isodurationstr))

    #Parse any date components
    durationdict = {'PnY': None, 'PnM': None, 'PnW': None, 'PnD': None}

    if len(datestr) > 1:
        durationdict = _parse_duration_prescribed_notime(datestr)

    durationdict.update({'TnH': hourstr, 'TnM': minutestr, 'TnS': secondstr})

    return durationdict
Exemplo n.º 4
0
def _parse_hour(timestr, tz, builder):
    # Format must be hh or hh.
    hourstr = timestr

    if hourstr == "24":
        return builder.build_time(tz=tz)

    return builder.build_time(hh=normalize(hourstr), tz=tz)
Exemplo n.º 5
0
def _parse_duration_prescribed_notime(isodurationstr):
    # durationstr can be of the form PnYnMnD or PnW

    durationstr = normalize(isodurationstr)

    yearstr = None
    monthstr = None
    daystr = None
    weekstr = None

    weekidx = durationstr.find("W")
    yearidx = durationstr.find("Y")
    monthidx = durationstr.find("M")
    dayidx = durationstr.find("D")

    if weekidx != -1:
        weekstr = durationstr[1:-1]
    elif yearidx != -1 and monthidx != -1 and dayidx != -1:
        yearstr = durationstr[1:yearidx]
        monthstr = durationstr[yearidx + 1:monthidx]
        daystr = durationstr[monthidx + 1:-1]
    elif yearidx != -1 and monthidx != -1:
        yearstr = durationstr[1:yearidx]
        monthstr = durationstr[yearidx + 1:monthidx]
    elif yearidx != -1 and dayidx != -1:
        yearstr = durationstr[1:yearidx]
        daystr = durationstr[yearidx + 1:dayidx]
    elif monthidx != -1 and dayidx != -1:
        monthstr = durationstr[1:monthidx]
        daystr = durationstr[monthidx + 1:-1]
    elif yearidx != -1:
        yearstr = durationstr[1:-1]
    elif monthidx != -1:
        monthstr = durationstr[1:-1]
    elif dayidx != -1:
        daystr = durationstr[1:-1]
    else:
        raise ISOFormatError(
            '"{0}" is not a valid ISO 8601 duration.'.format(isodurationstr))

    for componentstr in [yearstr, monthstr, daystr, weekstr]:
        if componentstr is not None:
            if "." in componentstr:
                intstr, fractionalstr = componentstr.split(".", 1)

                if intstr.isdigit() is False:
                    raise ISOFormatError(
                        '"{0}" is not a valid ISO 8601 duration.'.format(
                            isodurationstr))
            else:
                if componentstr.isdigit() is False:
                    raise ISOFormatError(
                        '"{0}" is not a valid ISO 8601 duration.'.format(
                            isodurationstr))

    return {"PnY": yearstr, "PnM": monthstr, "PnW": weekstr, "PnD": daystr}
Exemplo n.º 6
0
def _parse_duration_prescribed_notime(isodurationstr):
    #durationstr can be of the form PnYnMnD or PnW

    durationstr = normalize(isodurationstr)

    yearstr = None
    monthstr = None
    daystr = None
    weekstr = None

    weekidx = durationstr.find('W')
    yearidx = durationstr.find('Y')
    monthidx = durationstr.find('M')
    dayidx = durationstr.find('D')

    if weekidx != -1:
        weekstr = durationstr[1:-1]
    elif yearidx != -1 and monthidx != -1 and dayidx != -1:
        yearstr = durationstr[1:yearidx]
        monthstr = durationstr[yearidx + 1:monthidx]
        daystr = durationstr[monthidx + 1:-1]
    elif yearidx != -1 and monthidx != -1:
        yearstr = durationstr[1:yearidx]
        monthstr = durationstr[yearidx + 1:monthidx]
    elif monthidx != -1 and dayidx != -1:
        monthstr = durationstr[1:monthidx]
        daystr = durationstr[monthidx + 1:-1]
    elif yearidx != -1:
        yearstr = durationstr[1:-1]
    elif monthidx != -1:
        monthstr = durationstr[1:-1]
    elif dayidx != -1:
        daystr = durationstr[1:-1]
    else:
        raise ISOFormatError(
            '"{0}" is not a valid ISO 8601 duration.'.format(isodurationstr))

    for componentstr in [yearstr, monthstr, daystr, weekstr]:
        if componentstr is not None:
            if '.' in componentstr:
                intstr, fractionalstr = componentstr.split('.', 1)

                if intstr.isdigit() is False:
                    raise ISOFormatError(
                        '"{0}" is not a valid ISO 8601 duration.'.format(
                            isodurationstr))
            else:
                if componentstr.isdigit() is False:
                    raise ISOFormatError(
                        '"{0}" is not a valid ISO 8601 duration.'.format(
                            isodurationstr))

    return {'PnY': yearstr, 'PnM': monthstr, 'PnW': weekstr, 'PnD': daystr}
Exemplo n.º 7
0
def _parse_duration_element(durationstr, elementstr):
    # Extracts the specified portion of a duration, for instance, given:
    # durationstr = 'T4H5M6.1234S'
    # elementstr = 'H'
    #
    # returns 4
    #
    # Note that the string must start with a character, so its assumed the
    # full duration string would be split at the 'T'

    durationstartindex = 0
    durationendindex = durationstr.find(elementstr)

    for characterindex in compat.range(durationendindex - 1, 0, -1):
        if durationstr[characterindex].isalpha() is True:
            durationstartindex = characterindex
            break

    durationstartindex += 1

    return normalize(durationstr[durationstartindex:durationendindex])
Exemplo n.º 8
0
def _parse_duration_prescribed(isodurationstr):
    #durationstr can be of the form PnYnMnDTnHnMnS or PnW

    #Make sure the end character is valid
    #https://bitbucket.org/nielsenb/aniso8601/issues/9/durations-with-trailing-garbage-are-parsed
    if isodurationstr[-1] not in ['Y', 'M', 'D', 'H', 'S', 'W']:
        raise ISOFormatError('ISO 8601 duration must end with a valid '
                             'character.')

    #Make sure only the lowest order element has decimal precision
    durationstr = normalize(isodurationstr)

    if durationstr.count('.') > 1:
        raise ISOFormatError('ISO 8601 allows only lowest order element to '
                             'have a decimal fraction.')

    seperatoridx = durationstr.find('.')

    if seperatoridx != -1:
        remaining = durationstr[seperatoridx + 1:-1]

        #There should only ever be 1 letter after a decimal if there is more
        #then one, the string is invalid
        if remaining.isdigit() is False:
            raise ISOFormatError('ISO 8601 duration must end with '
                                 'a single valid character.')

    #Do not allow W in combination with other designators
    #https://bitbucket.org/nielsenb/aniso8601/issues/2/week-designators-should-not-be-combinable
    if (durationstr.find('W') != -1 and _has_any_component(
            durationstr, ['Y', 'M', 'D', 'H', 'S']) is True):
        raise ISOFormatError('ISO 8601 week designators may not be combined '
                             'with other time designators.')

    #Parse the elements of the duration
    if durationstr.find('T') == -1:
        return _parse_duration_prescribed_notime(durationstr)

    return _parse_duration_prescribed_time(durationstr)
Exemplo n.º 9
0
def parse_time(isotimestr, builder=PythonTimeBuilder):
    # Given a string in any ISO 8601 time format, return a datetime.time object
    # that corresponds to the given time. Fixed offset tzdata will be included
    # if UTC offset is given in the input string. Valid time formats are:
    #
    # hh:mm:ss
    # hhmmss
    # hh:mm
    # hhmm
    # hh
    # hh:mm:ssZ
    # hhmmssZ
    # hh:mmZ
    # hhmmZ
    # hhZ
    # hh:mm:ss±hh:mm
    # hhmmss±hh:mm
    # hh:mm±hh:mm
    # hhmm±hh:mm
    # hh±hh:mm
    # hh:mm:ss±hhmm
    # hhmmss±hhmm
    # hh:mm±hhmm
    # hhmm±hhmm
    # hh±hhmm
    # hh:mm:ss±hh
    # hhmmss±hh
    # hh:mm±hh
    # hhmm±hh
    # hh±hh
    if is_string(isotimestr) is False:
        raise ValueError("Time must be string.")

    if len(isotimestr) == 0:
        raise ISOFormatError(
            '"{0}" is not a valid ISO 8601 time.'.format(isotimestr))

    timestr = normalize(isotimestr)

    hourstr = None
    minutestr = None
    secondstr = None
    tzstr = None

    fractionalstr = None

    # Split out the timezone
    for delimiter in TIMEZONE_DELIMITERS:
        delimiteridx = timestr.find(delimiter)

        if delimiteridx != -1:
            tzstr = timestr[delimiteridx:]
            timestr = timestr[0:delimiteridx]

    # Split out the fractional component
    if timestr.find(".") != -1:
        timestr, fractionalstr = timestr.split(".", 1)

        if fractionalstr.isdigit() is False:
            raise ISOFormatError(
                '"{0}" is not a valid ISO 8601 time.'.format(isotimestr))

    if len(timestr) == 2:
        # hh
        hourstr = timestr
    elif len(timestr) == 4 or len(timestr) == 5:
        # hh:mm
        # hhmm
        if timestr.count(":") == 1:
            hourstr, minutestr = timestr.split(":")
        else:
            hourstr = timestr[0:2]
            minutestr = timestr[2:]
    elif len(timestr) == 6 or len(timestr) == 8:
        # hh:mm:ss
        # hhmmss
        if timestr.count(":") == 2:
            hourstr, minutestr, secondstr = timestr.split(":")
        else:
            hourstr = timestr[0:2]
            minutestr = timestr[2:4]
            secondstr = timestr[4:]
    else:
        raise ISOFormatError(
            '"{0}" is not a valid ISO 8601 time.'.format(isotimestr))

    for componentstr in [hourstr, minutestr, secondstr]:
        if componentstr is not None and componentstr.isdigit() is False:
            raise ISOFormatError(
                '"{0}" is not a valid ISO 8601 time.'.format(isotimestr))

    if fractionalstr is not None:
        if secondstr is not None:
            secondstr = secondstr + "." + fractionalstr
        elif minutestr is not None:
            minutestr = minutestr + "." + fractionalstr
        else:
            hourstr = hourstr + "." + fractionalstr

    if tzstr is None:
        tz = None
    else:
        tz = parse_timezone(tzstr, builder=TupleBuilder)

    return builder.build_time(hh=hourstr, mm=minutestr, ss=secondstr, tz=tz)
Exemplo n.º 10
0
 def test_normalize(self):
     self.assertEqual(normalize(''), '')
     self.assertEqual(normalize('12.34'), '12.34')
     self.assertEqual(normalize('123,45'), '123.45')
     self.assertEqual(normalize('123,45,67'), '123.45.67')
Exemplo n.º 11
0
def _parse_duration_prescribed_time(isodurationstr):
    # durationstr can be of the form PnYnMnDTnHnMnS

    timeidx = isodurationstr.find("T")

    datestr = isodurationstr[:timeidx]
    timestr = normalize(isodurationstr[timeidx + 1:])

    hourstr = None
    minutestr = None
    secondstr = None

    houridx = timestr.find("H")
    minuteidx = timestr.find("M")
    secondidx = timestr.find("S")

    if houridx != -1 and minuteidx != -1 and secondidx != -1:
        hourstr = timestr[0:houridx]
        minutestr = timestr[houridx + 1:minuteidx]
        secondstr = timestr[minuteidx + 1:-1]
    elif houridx != -1 and minuteidx != -1:
        hourstr = timestr[0:houridx]
        minutestr = timestr[houridx + 1:minuteidx]
    elif houridx != -1 and secondidx != -1:
        hourstr = timestr[0:houridx]
        secondstr = timestr[houridx + 1:-1]
    elif minuteidx != -1 and secondidx != -1:
        minutestr = timestr[0:minuteidx]
        secondstr = timestr[minuteidx + 1:-1]
    elif houridx != -1:
        hourstr = timestr[0:-1]
    elif minuteidx != -1:
        minutestr = timestr[0:-1]
    elif secondidx != -1:
        secondstr = timestr[0:-1]
    else:
        raise ISOFormatError(
            '"{0}" is not a valid ISO 8601 duration.'.format(isodurationstr))

    for componentstr in [hourstr, minutestr, secondstr]:
        if componentstr is not None:
            if "." in componentstr:
                intstr, fractionalstr = componentstr.split(".", 1)

                if intstr.isdigit() is False:
                    raise ISOFormatError(
                        '"{0}" is not a valid ISO 8601 duration.'.format(
                            isodurationstr))
            else:
                if componentstr.isdigit() is False:
                    raise ISOFormatError(
                        '"{0}" is not a valid ISO 8601 duration.'.format(
                            isodurationstr))

    # Parse any date components
    durationdict = {"PnY": None, "PnM": None, "PnW": None, "PnD": None}

    if len(datestr) > 1:
        durationdict = _parse_duration_prescribed_notime(datestr)

    durationdict.update({"TnH": hourstr, "TnM": minutestr, "TnS": secondstr})

    return durationdict
Exemplo n.º 12
0
 def test_normalize(self):
     self.assertEqual(normalize(""), "")
     self.assertEqual(normalize("12.34"), "12.34")
     self.assertEqual(normalize("123,45"), "123.45")
     self.assertEqual(normalize("123,45,67"), "123.45.67")