Skip to content

Add intersect_spans function - #72

Merged
chetchavat merged 11 commits into
mainfrom
zc/intersect-timespans
May 27, 2026
Merged

Add intersect_spans function#72
chetchavat merged 11 commits into
mainfrom
zc/intersect-timespans

Conversation

@chetchavat

@chetchavat chetchavat commented May 19, 2026

Copy link
Copy Markdown
Contributor

This was defined in an internal repo and was deemed useful, so we're putting it in!


@chetchavat
chetchavat requested review from dhanyscode and palday May 19, 2026 22:38
Comment thread src/TimeSpans.jl Outdated
Comment thread src/TimeSpans.jl Outdated
chetchavat and others added 2 commits May 19, 2026 20:55
Co-authored-by: Phillip Alday <me@phillipalday.com>
Co-authored-by: Phillip Alday <me@phillipalday.com>
Comment thread src/TimeSpans.jl
"""
intersect_spans(span_1, span_2)

Returns a timespan that consists of the intersection of two timespans.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether "intersect" is really the right verb here. Describing it as the intersection of the two spans makes sense, but it kind of suggests to me that other set terminology would be applicable, but I don't believe there are any such cases. For example, TimeSpans.jl uses overlaps(a, b) rather than !isdisjoint(a, b), and TimeSpans.contains(a, b) rather than issubset(b, a). I could imagine that given that the query for "is there a nonempty intersection" is overlaps, "what is the intersection" would be overlap. But if overlap returns a span, it's not immediately obvious whether overlaps then is plural or present tense. I have no answers, only quandaries.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it helps any, the original function was called innerspan

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is really the set-theoretic operation though, (other than the error-if-disjoint lol).

my gripe with intersect_spans is the other part, the _spans: the other _spans functions operate on iterables of spans rather than pairs; the pairwise overlaps, contains don't have _spans.

I think TimeSpans.intersect is fine, it has the same semantics as the base function and not exporting it makes the scope clear a la contains

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll also add that Base.contains tends to come along with other collection-y methods, but the namespacing makes it pretty clear that it's different

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very, very late to the party but IMO TimeSpans.contains should be renamed to contains_span. (Actually, in basically all code I've written where I've needed that function, I do using TimeSpans: contains as contains_span, haha.) Having only part of the API namespaced feels inconsistent, and having a package with a function that has the same name as a Base function is really confusing. I strongly prefer intersect_spans over TimeSpans.intersect.

Comment thread src/TimeSpans.jl Outdated
Comment on lines +408 to +413
function intersect_spans(span_1, span_2)
overlaps(span_1, span_2) || throw(ArgumentError("provided spans must overlap"))

spans = [span_1, span_2]
return TimeSpan(maximum(start, spans), minimum(stop, spans))
end

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO it's a bit clearer not to express things as array reductions on a two-element array. Also, the other functions in this package that operate on two span arguments call the arguments a and b, so we might as well follow suit here.

Suggested change
function intersect_spans(span_1, span_2)
overlaps(span_1, span_2) || throw(ArgumentError("provided spans must overlap"))
spans = [span_1, span_2]
return TimeSpan(maximum(start, spans), minimum(stop, spans))
end
function intersect_spans(a, b)
overlaps(a, b) || throw(ArgumentError("provided spans must overlap"))
return TimeSpan(max(start(a), start(b)), min(stop(a), stop(b)))
end

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, max/min are more idiomatic when dealing with two things. it also makes the intent really clear.

Comment thread test/runtests.jl Outdated
Comment thread test/runtests.jl
chetchavat and others added 2 commits May 20, 2026 20:36
Co-authored-by: Alex Arslan <ararslan@comcast.net>
Co-authored-by: Alex Arslan <ararslan@comcast.net>

@kleinschmidt kleinschmidt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry to throw another contender into the ring

Comment thread src/TimeSpans.jl
"""
intersect_spans(span_1, span_2)

Returns a timespan that consists of the intersection of two timespans.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is really the set-theoretic operation though, (other than the error-if-disjoint lol).

my gripe with intersect_spans is the other part, the _spans: the other _spans functions operate on iterables of spans rather than pairs; the pairwise overlaps, contains don't have _spans.

I think TimeSpans.intersect is fine, it has the same semantics as the base function and not exporting it makes the scope clear a la contains

Comment thread src/TimeSpans.jl Outdated
Comment on lines +408 to +413
function intersect_spans(span_1, span_2)
overlaps(span_1, span_2) || throw(ArgumentError("provided spans must overlap"))

spans = [span_1, span_2]
return TimeSpan(maximum(start, spans), minimum(stop, spans))
end

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, max/min are more idiomatic when dealing with two things. it also makes the intent really clear.

Comment thread src/TimeSpans.jl
"""
intersect_spans(span_1, span_2)

Returns a timespan that consists of the intersection of two timespans.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll also add that Base.contains tends to come along with other collection-y methods, but the namespacing makes it pretty clear that it's different

Comment thread src/TimeSpans.jl
Co-authored-by: Dave Kleinschmidt <dave.f.kleinschmidt@gmail.com>
@chetchavat
chetchavat merged commit 0800138 into main May 27, 2026
3 checks passed
@chetchavat
chetchavat deleted the zc/intersect-timespans branch May 27, 2026 21:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants