js-temporal / proposal-temporal-v2

Future additions to Temporal
MIT License
24 stars 1 forks source link

Interval type, iterating through a range #4

Open ptomato opened 3 years ago

ptomato commented 3 years ago

Summary of discussions from https://github.com/tc39/proposal-temporal/issues/205 and https://github.com/tc39/proposal-temporal/issues/682.

From user feedback, it seems that the main use cases are iterating through a range between two points on the time line (whether exact time or calendar/wall-clock time), and having an interval object which boxes up two orderable Temporal objects with methods for checking whether another Temporal object or interval lies within the range.

Possible APIs proposed:

const start = new Temporal.PlainDate(2021, 1, 1);
const end = new Temporal.PlainDate(2020, 12, 31);
const step = Temporal.Duration.from({ days: 1 });
for (const date of Temporal.range(start, end, step)) { ... }
class Interval {
  constructor(startInstant, endInstant) { ... }
  static from(isoStringOrIntervalLike) { ... }
  contains(instant) { ... }
  intersects(interval) { ... }
  encloses(interval) { ... }
  equals(interval) { ... }
  *iterate(duration) { ... }
  get start() { ... }
  get end() { ... }
  get duration() { ... }
  with(intervalLike) { ... }
  toString(startTimeZone, endTimeZone) { ... }
  ...
}

Advantages:

Intervals are not difficult to implement in userland, but it could be a benefit for Temporal to have a type with a consistent set of operations, and to avoid off-by-one errors.

Concerns:

An Interval object doesn't quite fit with the strict typing philosophy of Temporal. It's possible there would have to be different Interval types for the different Temporal types: at least Instant and ZonedDateTime, probably PlainDateTime and PlainDate, and possibly PlainYearMonth and PlainTime. Probably business logic would use at most one of these types at a time.

Prior art:

Constraints / corner cases:

MidnightDesign commented 1 year ago

@ptomato PHP's DateInterval is not what this issue describes. It is what Temporal calls Duration. You should strike it from the "Prior art" section. Also, the Luxon link leads to a 404.

ptomato commented 1 year ago

@MidnightDesign You're right, DatePeriod is PHP's equivalent of this. Thanks for the warning. I'll hide these comments since I've updated the OP.

TheOneTheOnlyJJ commented 2 months ago

It's possible there would have to be different Interval types for the different Temporal types: at least Instant and ZonedDateTime, probably PlainDateTime and PlainDate, and possibly PlainYearMonth and PlainTime.

This would make the most sense, as it would avoid type ambiguity.

TheOneTheOnlyJJ commented 2 months ago

I would also add to this 2 new potential API methods. Both could be instance methods and static methods as well.

  1. A method to get the intersection between 2 intervals. Illustrated here in static method form:
    const intersection = Temporal.Interval.getIntersection(interval1, interval2) { ... }

    Its return value can be any one of the following:

    • No Overlap: Returns null if the intervals do not overlap.
    • Partial Overlap: Returns the overlapping portion of the 2.
    • Complete Overlap: Returns the smaller/shorter interval.
    • Identical Intervals: Returns the same interval as the inputs.

Possible return types: null, Interval.

  1. A method to get the difference between 2 intervals. It is basically the opposite of the above. Illustrated here also in static method form:
    const difference = Temporal.Interval.getDifference(interval1, interval2) { ... }

    Given how differences work, this method could return up to 2 intervals, depending on the inputs:

    • No Overlap: Returns an array of the 2 unchanged input intervals.
    • Partial Overlap: Returns an array of 2 intervals.
    • Complete Overlap: Return an array of either 1 or 2 intervals, depending on the inputs.
    • Identical Intervals: Returns null, as there is no difference.

Possible return types: null, array<Interval> of length 1 or 2.

I strongly support adding these Interval classes to Temporal, as they would greatly improve the DX when working with timelines, timetables, schedules, etc. These 2 newly proposed methods would improve upon what was already discussed here and in the related issues until now. There should be no need to rely on any 3rd party package for such trivialities.