Add DateRange

This commit is contained in:
Ming Ming 2024-05-04 20:04:31 +08:00
parent efb32a785a
commit 7b98a282ed
3 changed files with 108 additions and 0 deletions

View file

@ -1,5 +1,6 @@
library np_datetime;
export 'src/date.dart';
export 'src/date_range.dart';
export 'src/time_range.dart';
export 'src/util.dart';

View file

@ -76,8 +76,12 @@ extension DateExtension on Date {
return day < other.day;
}
bool operator <(Date other) => isBefore(other);
bool isBeforeOrAt(Date other) => !isAfter(other);
bool operator <=(Date other) => isBeforeOrAt(other);
bool isAfter(Date other) {
if (year < other.year) {
return false;
@ -92,7 +96,17 @@ extension DateExtension on Date {
return day > other.day;
}
bool operator >(Date other) => isAfter(other);
bool isAfterOrAt(Date other) => !isBefore(other);
bool operator >=(Date other) => isAfterOrAt(other);
/// Return the earlier date
Date min(Date other) => isBefore(other) ? this : other;
/// Return the later date
Date max(Date other) => isAfter(other) ? this : other;
}
extension DateTimeDateExtension on DateTime {

View file

@ -0,0 +1,93 @@
import 'package:np_datetime/src/date.dart';
import 'package:np_datetime/src/time_range.dart';
class DateRange {
const DateRange({
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 Date? from;
final TimeRangeBound fromBound;
final Date? to;
final TimeRangeBound toBound;
}
extension DateRangeExtension on DateRange {
/// 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 contains(Date a) {
if (from != null) {
if (a.isBefore(from!)) {
return false;
}
if (fromBound == TimeRangeBound.exclusive) {
if (a == from) {
return false;
}
}
}
if (to != null) {
if (a.isAfter(to!)) {
return false;
}
if (toBound == TimeRangeBound.exclusive) {
if (a == to!) {
return false;
}
}
}
return true;
}
bool isOverlapped(DateRange other) {
final aFrom = _inclusiveFrom;
final aTo = _inclusiveTo;
final bFrom = other._inclusiveFrom;
final bTo = other._inclusiveTo;
return (aFrom == null || bTo == null || aFrom <= bTo) &&
(bFrom == null || aTo == null || bFrom <= aTo);
}
/// Return the union of two DateRanges
///
/// Warning: this function always assume the two DateRanges being overlapped,
/// you may want to call [isOverlapped] first
DateRange union(DateRange other) {
assert(isOverlapped(other));
return DateRange(
from: from == null || other.from == null
? null
: _inclusiveFrom!.min(other._inclusiveFrom!),
fromBound: TimeRangeBound.inclusive,
to: to == null || other.to == null
? null
: _inclusiveTo!.max(other._inclusiveTo!),
toBound: TimeRangeBound.inclusive,
);
}
TimeRange toLocalTimeRange() => TimeRange(
from: from?.toLocalDateTime(),
fromBound: fromBound,
to: (toBound == TimeRangeBound.inclusive ? to?.add(day: 1) : to)
?.toLocalDateTime(),
toBound: TimeRangeBound.exclusive,
);
Date? get _inclusiveFrom =>
fromBound == TimeRangeBound.inclusive ? from : from?.add(day: -1);
Date? get _inclusiveTo =>
toBound == TimeRangeBound.inclusive ? to : to?.add(day: -1);
}