示例#1
0
    def test_range_fully_overlaps_other(self) -> None:
        range_1 = DateRange(datetime.date(2019, 2, 5), datetime.date(2019, 5, 2))
        range_2 = DateRange(datetime.date(2019, 3, 1), datetime.date(2019, 3, 5))

        time_range_diff = DateRangeDiff(range_1, range_2)

        self.assertEqual(range_2, time_range_diff.overlapping_range)
        self.assertEqual(
            [
                DateRange(datetime.date(2019, 2, 5), datetime.date(2019, 3, 1)),
                DateRange(datetime.date(2019, 3, 5), datetime.date(2019, 5, 2)),
            ],
            time_range_diff.range_1_non_overlapping_parts,
        )
        self.assertEqual([], time_range_diff.range_2_non_overlapping_parts)

        time_range_diff = DateRangeDiff(range_2, range_1)
        self.assertEqual(range_2, time_range_diff.overlapping_range)
        self.assertEqual([], time_range_diff.range_1_non_overlapping_parts)
        self.assertEqual(
            [
                DateRange(datetime.date(2019, 2, 5), datetime.date(2019, 3, 1)),
                DateRange(datetime.date(2019, 3, 5), datetime.date(2019, 5, 2)),
            ],
            time_range_diff.range_2_non_overlapping_parts,
        )
示例#2
0
    def test_partially_overlapping_ranges(self):
        range_1 = DateRange(datetime.date(2019, 2, 5),
                            datetime.date(2019, 5, 2))
        range_2 = DateRange(datetime.date(2019, 3, 1),
                            datetime.date(2019, 6, 5))

        time_range_diff = DateRangeDiff(range_1, range_2)

        self.assertEqual(
            DateRange(datetime.date(2019, 3, 1), datetime.date(2019, 5, 2)),
            time_range_diff.overlapping_range)
        self.assertEqual(
            [DateRange(datetime.date(2019, 2, 5), datetime.date(2019, 3, 1))],
            time_range_diff.range_1_non_overlapping_parts)
        self.assertEqual(
            [DateRange(datetime.date(2019, 5, 2), datetime.date(2019, 6, 5))],
            time_range_diff.range_2_non_overlapping_parts)

        time_range_diff = DateRangeDiff(range_2, range_1)
        self.assertEqual(
            DateRange(datetime.date(2019, 3, 1), datetime.date(2019, 5, 2)),
            time_range_diff.overlapping_range)
        self.assertEqual(
            [DateRange(datetime.date(2019, 5, 2), datetime.date(2019, 6, 5))],
            time_range_diff.range_1_non_overlapping_parts)
        self.assertEqual(
            [DateRange(datetime.date(2019, 2, 5), datetime.date(2019, 3, 1))],
            time_range_diff.range_2_non_overlapping_parts)
def supervision_period_counts_towards_supervision_population_in_date_range_state_specific(
    date_range: DateRange,
    supervision_sentences: List[StateSupervisionSentence],
    incarceration_sentences: List[StateIncarcerationSentence],
    supervision_period: StateSupervisionPeriod,
) -> bool:
    """Returns False if there is state-specific information to indicate that the supervision period should not count
    towards any supervision metrics in the date range. Returns True if either there is a state-specific check that
    indicates that the supervision period should count or if there is no state-specific check to perform.
    """
    if supervision_period.state_code == "US_MO":
        overlapping_range = DateRangeDiff(
            range_1=date_range, range_2=supervision_period.duration
        ).overlapping_range

        if not overlapping_range:
            return False

        return (
            us_mo_get_most_recent_supervision_period_supervision_type_before_upper_bound_day(
                upper_bound_exclusive_date=overlapping_range.upper_bound_exclusive_date,
                lower_bound_inclusive_date=overlapping_range.lower_bound_inclusive_date,
                incarceration_sentences=incarceration_sentences,
                supervision_sentences=supervision_sentences,
            )
            is not None
        )

    return True
def ip_is_nested_in_previous_period(
        ip: StateIncarcerationPeriod,
        previous_ip: StateIncarcerationPeriod) -> bool:
    """Returns whether the StateIncarcerationPeriod |ip| is entirely nested within the
    |previous_ip|. Both periods must have set admission and release dates.
    A nested period is defined as an incarceration period that overlaps with the
    previous_ip and has no parts that are non-overlapping with the previous_ip.
    Single-day periods (admission_date = release_date) by definition do not have
    overlapping ranges with another period because the ranges are end date exclusive.
    If a single-day period falls within the admission and release of the previous_ip,
    then it is nested within that period. If a single-day period falls on the
    previous_ip.release_date, then it is not nested within that period.
    """
    ip_range_diff = DateRangeDiff(ip.duration, previous_ip.duration)

    if not ip.admission_date or not ip.release_date:
        raise ValueError(f"ip cannot have unset dates: {ip}")

    if not previous_ip.admission_date or not previous_ip.release_date:
        raise ValueError(f"previous_ip cannot have unset dates: {previous_ip}")

    if ip.admission_date < previous_ip.admission_date:
        raise ValueError(
            "previous_ip should be sorted after ip. Error in _sort_ips_by_set_dates_and_statuses. "
            f"ip: {ip}, previous_ip: {previous_ip}")

    return (ip_range_diff.overlapping_range
            and not ip_range_diff.range_1_non_overlapping_parts) or (
                ip.admission_date == ip.release_date
                and ip.release_date < previous_ip.release_date)
示例#5
0
    def test_exactly_overlapping_ranges(self):
        range_1 = DateRange.for_month(2019, 2)
        range_2 = DateRange.for_month(2019, 2)

        time_range_diff = DateRangeDiff(range_1, range_2)

        self.assertEqual(range_1, time_range_diff.overlapping_range)
        self.assertEqual([], time_range_diff.range_1_non_overlapping_parts)
        self.assertEqual([], time_range_diff.range_2_non_overlapping_parts)
示例#6
0
    def test_non_overlapping_ranges(self) -> None:
        range_1 = DateRange.for_month(2019, 2)
        range_2 = DateRange.for_month(2019, 3)

        time_range_diff = DateRangeDiff(range_1, range_2)

        self.assertEqual(None, time_range_diff.overlapping_range)
        self.assertEqual([range_1], time_range_diff.range_1_non_overlapping_parts)
        self.assertEqual([range_2], time_range_diff.range_2_non_overlapping_parts)
示例#7
0
    def _get_portions_of_range_not_covered_by_periods_subset(
        time_range_to_cover: DateRange,
        incarceration_periods_subset: List[StateIncarcerationPeriod]
    ) -> List[DateRange]:
        """Returns a list of date ranges within the provided |time_range_to_cover| which the provided set of
        incarceration periods does not fully overlap.
        """

        remaining_ranges_to_cover = [time_range_to_cover]

        for incarceration_period in incarceration_periods_subset:
            new_remaining_ranges_to_cover = []
            for time_range in remaining_ranges_to_cover:
                new_remaining_ranges_to_cover.extend(
                    DateRangeDiff(
                        range_1=incarceration_period.duration,
                        range_2=time_range).range_2_non_overlapping_parts)

            remaining_ranges_to_cover = new_remaining_ranges_to_cover
            if not remaining_ranges_to_cover:
                break

        return remaining_ranges_to_cover
示例#8
0
def should_include_in_release_cohort(
        status: StateIncarcerationPeriodStatus, release_date: Optional[date],
        release_reason: Optional[ReleaseReason],
        next_incarceration_period: Optional[StateIncarcerationPeriod]) -> bool:
    """Identifies whether a period of incarceration with the given features should be included in the release
    cohort."""
    # If the person is still in custody, there is no release to include in a cohort.
    if status == StateIncarcerationPeriodStatus.IN_CUSTODY:
        return False

    if not release_date:
        # If the person is not in custody, there should be a release_date.
        # This should not happen after validation. Throw error.
        raise ValueError("release_date is not set where it should be.")

    if not release_reason:
        # If there is no recorded release reason, then we cannot classify this as a valid release for the cohort
        return False

    if next_incarceration_period:
        time_range_release = DateRange.for_day(release_date)
        if DateRangeDiff(time_range_release,
                         next_incarceration_period.duration).overlapping_range:
            # If the release overlaps with the following incarceration period, this is not an actual release from
            # incarceration
            return False

        if next_incarceration_period.release_date and release_date == next_incarceration_period.release_date:
            # This release shares a release_date with the next incarceration period. Do not include this release.
            return False

    if release_reason in [ReleaseReason.DEATH, ReleaseReason.EXECUTION]:
        # If the person was released from this incarceration period because they died or were executed, do not include
        # them in the release cohort.
        return False
    if release_reason == ReleaseReason.ESCAPE:
        # If the person was released from this incarceration period because they escaped, do not include them in the
        # release cohort.
        return False
    if release_reason == ReleaseReason.RELEASED_FROM_TEMPORARY_CUSTODY:
        # If the person was released from a period of temporary custody, do not include them in the release_cohort.
        return False
    if release_reason == ReleaseReason.RELEASED_IN_ERROR:
        # If the person was released from this incarceration period due to an error, do not include them in the
        # release cohort.
        return False
    if release_reason == ReleaseReason.TRANSFER:
        # If the person was released from this incarceration period because they were transferred elsewhere, do not
        # include them in the release cohort.
        return False
    if release_reason == ReleaseReason.TRANSFERRED_OUT_OF_STATE:
        # Releases where the person has been transferred out of state don't really count as true releases.
        return False
    if release_reason == ReleaseReason.COURT_ORDER:
        # If the person was released from this incarceration period due to a court order, do not include them in the
        # release cohort.
        return False
    if release_reason in (ReleaseReason.EXTERNAL_UNKNOWN,
                          ReleaseReason.INTERNAL_UNKNOWN):
        # We do not have enough information to determine whether this release qualifies for inclusion in the release
        # cohort.
        return False
    if release_reason in (ReleaseReason.COMMUTED, ReleaseReason.COMPASSIONATE,
                          ReleaseReason.CONDITIONAL_RELEASE,
                          ReleaseReason.PARDONED,
                          ReleaseReason.RELEASED_FROM_ERRONEOUS_ADMISSION,
                          ReleaseReason.SENTENCE_SERVED,
                          ReleaseReason.VACATED):
        return True

    raise ValueError("Enum case not handled for "
                     "StateIncarcerationPeriodReleaseReason of type:"
                     f" {release_reason}.")