From 6281e6daffdb20e9e546a57c6350b2d60113c206 Mon Sep 17 00:00:00 2001 From: Ming Ming Date: Wed, 10 Apr 2024 00:40:14 +0800 Subject: [PATCH] Allow TimeRange to be open --- np_datetime/lib/src/time_range.dart | 32 +++++++++++-------- .../lib/src/database/file_extension.dart | 10 +++--- np_db_sqlite/lib/src/database_extension.dart | 1 + np_db_sqlite/lib/src/util.dart | 25 +++++++++++++++ 4 files changed, 48 insertions(+), 20 deletions(-) diff --git a/np_datetime/lib/src/time_range.dart b/np_datetime/lib/src/time_range.dart index 4885dc32..90c580b9 100644 --- a/np_datetime/lib/src/time_range.dart +++ b/np_datetime/lib/src/time_range.dart @@ -5,9 +5,9 @@ enum TimeRangeBound { class TimeRange { const TimeRange({ - required this.from, + this.from, this.fromBound = TimeRangeBound.inclusive, - required this.to, + this.to, this.toBound = TimeRangeBound.exclusive, }); @@ -18,9 +18,9 @@ class TimeRange { "${toBound == TimeRangeBound.inclusive ? "]" : ")"}"; } - final DateTime from; + final DateTime? from; final TimeRangeBound fromBound; - final DateTime to; + final DateTime? to; final TimeRangeBound toBound; } @@ -30,21 +30,25 @@ extension TimeRangeExtension on TimeRange { /// The comparison is independent of whether the time is in UTC or in the /// local time zone bool isIn(DateTime a) { - if (a.isBefore(from)) { - return false; - } - if (fromBound == TimeRangeBound.exclusive) { - if (a.isAtSameMomentAs(from)) { + if (from != null) { + if (a.isBefore(from!)) { return false; } + if (fromBound == TimeRangeBound.exclusive) { + if (a.isAtSameMomentAs(from!)) { + return false; + } + } } - if (a.isAfter(to)) { - return false; - } - if (toBound == TimeRangeBound.exclusive) { - if (a.isAtSameMomentAs(to)) { + if (to != null) { + if (a.isAfter(to!)) { return false; } + if (toBound == TimeRangeBound.exclusive) { + if (a.isAtSameMomentAs(to!)) { + return false; + } + } } return true; } diff --git a/np_db_sqlite/lib/src/database/file_extension.dart b/np_db_sqlite/lib/src/database/file_extension.dart index 074f5049..742de97a 100644 --- a/np_db_sqlite/lib/src/database/file_extension.dart +++ b/np_db_sqlite/lib/src/database/file_extension.dart @@ -143,12 +143,10 @@ extension SqliteDbFileExtension on SqliteDb { } return q.build(); }); - final dateTime = accountFiles.bestDateTime.unixepoch; - query - ..where(dateTime.isBetweenValues( - range.from.millisecondsSinceEpoch ~/ 1000, - (range.to.millisecondsSinceEpoch ~/ 1000) - 1)) - ..orderBy([OrderingTerm.desc(dateTime)]); + accountFiles.bestDateTime + .isBetweenTimeRange(range) + ?.let((e) => query.where(e)); + query.orderBy([OrderingTerm.desc(accountFiles.bestDateTime.unixepoch)]); return _mapCompleteFile(query); } diff --git a/np_db_sqlite/lib/src/database_extension.dart b/np_db_sqlite/lib/src/database_extension.dart index b69c96e2..d9b4b116 100644 --- a/np_db_sqlite/lib/src/database_extension.dart +++ b/np_db_sqlite/lib/src/database_extension.dart @@ -18,6 +18,7 @@ import 'package:np_db_sqlite/src/files_query_builder.dart'; import 'package:np_db_sqlite/src/isolate_util.dart'; import 'package:np_db_sqlite/src/k.dart' as k; import 'package:np_db_sqlite/src/table.dart'; +import 'package:np_db_sqlite/src/util.dart'; import 'package:np_geocoder/np_geocoder.dart'; import 'package:np_platform_lock/np_platform_lock.dart'; import 'package:np_platform_util/np_platform_util.dart'; diff --git a/np_db_sqlite/lib/src/util.dart b/np_db_sqlite/lib/src/util.dart index 132bffcd..258157d1 100644 --- a/np_db_sqlite/lib/src/util.dart +++ b/np_db_sqlite/lib/src/util.dart @@ -2,6 +2,8 @@ import 'dart:io' as io; import 'package:drift/drift.dart'; import 'package:flutter/foundation.dart'; +import 'package:np_common/object_util.dart'; +import 'package:np_datetime/np_datetime.dart'; import 'package:np_db_sqlite/src/database.dart'; import 'package:np_db_sqlite/src/native/util.dart' if (dart.library.html) 'package:np_db_sqlite/src/web/util.dart' as impl; @@ -27,3 +29,26 @@ Future applyWorkaroundToOpenSqlite3OnOldAndroidVersions() => /// means only internal directories are allowed Future exportSqliteDb(SqliteDb db, io.Directory dir) => impl.exportSqliteDb(db, dir); + +extension DateTimeColumnExtension on Column { + Expression? isBetweenTimeRange(TimeRange range) { + final epoch = unixepoch; + // convert ranges to inclusive + final from = range.fromBound == TimeRangeBound.inclusive + ? range.from?.millisecondsSinceEpoch.let((e) => e ~/ 1000) + : range.from?.millisecondsSinceEpoch.let((e) => e ~/ 1000 + 1); + final to = range.toBound == TimeRangeBound.inclusive + ? range.to?.millisecondsSinceEpoch.let((e) => e ~/ 1000) + : range.to?.millisecondsSinceEpoch.let((e) => e ~/ 1000 - 1); + if (from != null && to != null) { + return epoch.isBetweenValues(from, to); + } else if (from != null) { + return epoch.isBiggerOrEqualValue(from); + } else if (to != null) { + return epoch.isSmallerOrEqualValue(to); + } else { + // both null + return null; + } + } +}