Example #1
0
def _parse_duration_prescribed(durationstr, builder):
    # durationstr can be of the form PnYnMnDTnHnMnS or PnW

    # Don't allow negative elements
    # https://bitbucket.org/nielsenb/aniso8601/issues/20/negative-duration
    if durationstr.find("-") != -1:
        raise NegativeDurationError("ISO 8601 durations must be positive.")

    # Make sure the end character is valid
    # https://bitbucket.org/nielsenb/aniso8601/issues/9/durations-with-trailing-garbage-are-parsed
    if durationstr[-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
    separator_index = find_separator(durationstr)
    if separator_index != -1:
        remaining = durationstr[separator_index + 1 :]
        if find_separator(remaining) != -1:
            raise ISOFormatError(
                "ISO 8601 allows only lowest order element to "
                "have a decimal fraction."
            )

        # There should only ever be 1 letter after a decimal if there is more
        # then one, the string is invalid
        lettercount = 0

        for character in remaining:
            if character.isalpha() is True:
                lettercount += 1

                if lettercount > 1:
                    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, builder)

    return _parse_duration_prescribed_time(durationstr, builder)
Example #2
0
def _parse_duration_prescribed_notime(durationstr, builder):
    # durationstr can be of the form PnYnMnD or PnW

    # Don't allow negative elements
    # https://bitbucket.org/nielsenb/aniso8601/issues/20/negative-duration
    if durationstr.find('-') != -1:
        raise NegativeDurationError('ISO 8601 durations must be positive.')

    # Make sure no time portion is included
    # https://bitbucket.org/nielsenb/aniso8601/issues/7/durations-with-time-components-before-t
    if _has_any_component(durationstr, ['H', 'S']):
        raise ISOFormatError(
            'ISO 8601 time components not allowed in duration '
            'without prescribed time.')

    if _component_order_correct(durationstr,
                                ['P', 'Y', 'M', 'D', 'W']) is False:
        raise ISOFormatError('ISO 8601 duration components must be in the '
                             'correct order.')

    if durationstr.find('Y') != -1:
        yearstr = _parse_duration_element(durationstr, 'Y')
    else:
        yearstr = None

    if durationstr.find('M') != -1:
        monthstr = _parse_duration_element(durationstr, 'M')
    else:
        monthstr = None

    if durationstr.find('W') != -1:
        weekstr = _parse_duration_element(durationstr, 'W')
    else:
        weekstr = None

    if durationstr.find('D') != -1:
        daystr = _parse_duration_element(durationstr, 'D')
    else:
        daystr = None

    return builder.build_duration(PnY=yearstr,
                                  PnM=monthstr,
                                  PnW=weekstr,
                                  PnD=daystr)
Example #3
0
def _parse_duration_prescribed_notime(durationstr, builder):
    # durationstr can be of the form PnYnMnD or PnW

    # Don't allow negative elements
    # https://bitbucket.org/nielsenb/aniso8601/issues/20/negative-duration
    if durationstr.find("-") != -1:
        raise NegativeDurationError("ISO 8601 durations must be positive.")

    # Make sure no time portion is included
    # https://bitbucket.org/nielsenb/aniso8601/issues/7/durations-with-time-components-before-t
    if _has_any_component(durationstr, ["H", "S"]):
        raise ISOFormatError(
            "ISO 8601 time components not allowed in duration "
            "without prescribed time.")

    if _component_order_correct(durationstr,
                                ["P", "Y", "M", "D", "W"]) is False:
        raise ISOFormatError("ISO 8601 duration components must be in the "
                             "correct order.")

    if durationstr.find("Y") != -1:
        yearstr = _parse_duration_element(durationstr, "Y")
    else:
        yearstr = None

    if durationstr.find("M") != -1:
        monthstr = _parse_duration_element(durationstr, "M")
    else:
        monthstr = None

    if durationstr.find("W") != -1:
        weekstr = _parse_duration_element(durationstr, "W")
    else:
        weekstr = None

    if durationstr.find("D") != -1:
        daystr = _parse_duration_element(durationstr, "D")
    else:
        daystr = None

    return builder.build_duration(PnY=yearstr,
                                  PnM=monthstr,
                                  PnW=weekstr,
                                  PnD=daystr)
Example #4
0
def _parse_duration_prescribed(durationstr, builder):
    #durationstr can be of the form PnYnMnDTnHnMnS or PnW

    #Don't allow negative elements
    #https://bitbucket.org/nielsenb/aniso8601/issues/20/negative-duration
    if durationstr.find('-') != -1:
        raise NegativeDurationError('ISO 8601 durations must be positive.')

    #Make sure the end character is valid
    #https://bitbucket.org/nielsenb/aniso8601/issues/9/durations-with-trailing-garbage-are-parsed
    if durationstr[-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
    if durationstr.count('.') > 1:
        raise ISOFormatError('ISO 8601 allows only lowest order element to '
                             'have a decimal fraction.')
    elif durationstr.count('.') == 1:
        #There should only ever be 1 letter after a decimal if there is more
        #then one, the string is invalid
        lettercount = 0

        for character in durationstr.split('.')[1]:
            if character.isalpha() is True:
                lettercount += 1

                if lettercount > 1:
                    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, builder)

    return _parse_duration_prescribed_time(durationstr, builder)
Example #5
0
def _parse_duration_prescribed_time(durationstr, builder):
    # durationstr can be of the form PnYnMnDTnHnMnS

    # Don't allow negative elements
    # https://bitbucket.org/nielsenb/aniso8601/issues/20/negative-duration
    if durationstr.find('-') != -1:
        raise NegativeDurationError('ISO 8601 durations must be positive.')

    firsthalf = durationstr[:durationstr.find('T')]
    secondhalf = durationstr[durationstr.find('T'):]

    # Make sure no time portion is included in the date half
    # https://bitbucket.org/nielsenb/aniso8601/issues/7/durations-with-time-components-before-t
    if _has_any_component(firsthalf, ['H', 'S']):
        raise ISOFormatError('ISO 8601 time components not allowed in date '
                             'portion of duration.')

    if _component_order_correct(firsthalf, ['P', 'Y', 'M', 'D', 'W']) is False:
        raise ISOFormatError('ISO 8601 duration components must be in the '
                             'correct order.')

    # Make sure no date component is included in the time half
    if _has_any_component(secondhalf, ['Y', 'D']):
        raise ISOFormatError('ISO 8601 time components not allowed in date '
                             'portion of duration.')

    if _component_order_correct(secondhalf, ['T', 'H', 'M', 'S']) is False:
        raise ISOFormatError('ISO 8601 time components in duration must be in '
                             'the correct order.')

    if firsthalf.find('Y') != -1:
        yearstr = _parse_duration_element(firsthalf, 'Y')
    else:
        yearstr = None

    if firsthalf.find('M') != -1:
        monthstr = _parse_duration_element(firsthalf, 'M')
    else:
        monthstr = None

    if firsthalf.find('D') != -1:
        daystr = _parse_duration_element(firsthalf, 'D')
    else:
        daystr = None

    if secondhalf.find('H') != -1:
        hourstr = _parse_duration_element(secondhalf, 'H')
    else:
        hourstr = None

    if secondhalf.find('M') != -1:
        minutestr = _parse_duration_element(secondhalf, 'M')
    else:
        minutestr = None

    if secondhalf.find('S') != -1:
        secondstr = _parse_duration_element(secondhalf, 'S')
    else:
        secondstr = None

    return builder.build_duration(PnY=yearstr,
                                  PnM=monthstr,
                                  PnD=daystr,
                                  TnH=hourstr,
                                  TnM=minutestr,
                                  TnS=secondstr)
Example #6
0
def _parse_duration_prescribed_time(durationstr, builder):
    # durationstr can be of the form PnYnMnDTnHnMnS

    # Don't allow negative elements
    # https://bitbucket.org/nielsenb/aniso8601/issues/20/negative-duration
    if durationstr.find("-") != -1:
        raise NegativeDurationError("ISO 8601 durations must be positive.")

    firsthalf = durationstr[: durationstr.find("T")]
    secondhalf = durationstr[durationstr.find("T") :]

    # Make sure no time portion is included in the date half
    # https://bitbucket.org/nielsenb/aniso8601/issues/7/durations-with-time-components-before-t
    if _has_any_component(firsthalf, ["H", "S"]):
        raise ISOFormatError(
            "ISO 8601 time components not allowed in date " "portion of duration."
        )

    if _component_order_correct(firsthalf, ["P", "Y", "M", "D", "W"]) is False:
        raise ISOFormatError(
            "ISO 8601 duration components must be in the " "correct order."
        )

    # Make sure no date component is included in the time half
    if _has_any_component(secondhalf, ["Y", "D"]):
        raise ISOFormatError(
            "ISO 8601 time components not allowed in date " "portion of duration."
        )

    if _component_order_correct(secondhalf, ["T", "H", "M", "S"]) is False:
        raise ISOFormatError(
            "ISO 8601 time components in duration must be in " "the correct order."
        )

    if firsthalf.find("Y") != -1:
        yearstr = _parse_duration_element(firsthalf, "Y")
    else:
        yearstr = None

    if firsthalf.find("M") != -1:
        monthstr = _parse_duration_element(firsthalf, "M")
    else:
        monthstr = None

    if firsthalf.find("D") != -1:
        daystr = _parse_duration_element(firsthalf, "D")
    else:
        daystr = None

    if secondhalf.find("H") != -1:
        hourstr = _parse_duration_element(secondhalf, "H")
    else:
        hourstr = None

    if secondhalf.find("M") != -1:
        minutestr = _parse_duration_element(secondhalf, "M")
    else:
        minutestr = None

    if secondhalf.find("S") != -1:
        secondstr = _parse_duration_element(secondhalf, "S")
    else:
        secondstr = None

    return builder.build_duration(
        PnY=yearstr, PnM=monthstr, PnD=daystr, TnH=hourstr, TnM=minutestr, TnS=secondstr
    )