enum TimeRangeBound {
  inclusive,
  exclusive,
}

class TimeRange {
  const TimeRange({
    this.from,
    this.fromBound = TimeRangeBound.inclusive,
    this.to,
    this.toBound = TimeRangeBound.exclusive,
  });

  @override
  String toString() {
    return "${fromBound == TimeRangeBound.inclusive ? "[" : "("}"
        "$from, $to"
        "${toBound == TimeRangeBound.inclusive ? "]" : ")"}";
  }

  final DateTime? from;
  final TimeRangeBound fromBound;
  final DateTime? to;
  final TimeRangeBound toBound;
}

extension TimeRangeExtension on TimeRange {
  /// Return if an arbitrary time [a] is inside this range
  ///
  /// The comparison is independent of whether the time is in UTC or in the
  /// local time zone
  bool isIn(DateTime a) {
    if (from != null) {
      if (a.isBefore(from!)) {
        return false;
      }
      if (fromBound == TimeRangeBound.exclusive) {
        if (a.isAtSameMomentAs(from!)) {
          return false;
        }
      }
    }
    if (to != null) {
      if (a.isAfter(to!)) {
        return false;
      }
      if (toBound == TimeRangeBound.exclusive) {
        if (a.isAtSameMomentAs(to!)) {
          return false;
        }
      }
    }
    return true;
  }
}