mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 03:10:24 +03:00
fix: timezone in timeline bucketing (#25894)
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
@@ -85,14 +85,14 @@ LIMIT $limit;
|
|||||||
mergedBucket(:group_by AS INTEGER):
|
mergedBucket(:group_by AS INTEGER):
|
||||||
SELECT
|
SELECT
|
||||||
COUNT(*) as asset_count,
|
COUNT(*) as asset_count,
|
||||||
CASE
|
bucket_date
|
||||||
WHEN :group_by = 0 THEN STRFTIME('%Y-%m-%d', created_at, 'localtime') -- day
|
|
||||||
WHEN :group_by = 1 THEN STRFTIME('%Y-%m', created_at, 'localtime') -- month
|
|
||||||
END AS bucket_date
|
|
||||||
FROM
|
FROM
|
||||||
(
|
(
|
||||||
SELECT
|
SELECT
|
||||||
rae.created_at
|
CASE
|
||||||
|
WHEN :group_by = 0 THEN STRFTIME('%Y-%m-%d', rae.local_date_time)
|
||||||
|
WHEN :group_by = 1 THEN STRFTIME('%Y-%m', rae.local_date_time)
|
||||||
|
END as bucket_date
|
||||||
FROM
|
FROM
|
||||||
remote_asset_entity rae
|
remote_asset_entity rae
|
||||||
LEFT JOIN
|
LEFT JOIN
|
||||||
@@ -107,7 +107,10 @@ FROM
|
|||||||
)
|
)
|
||||||
UNION ALL
|
UNION ALL
|
||||||
SELECT
|
SELECT
|
||||||
lae.created_at
|
CASE
|
||||||
|
WHEN :group_by = 0 THEN STRFTIME('%Y-%m-%d', lae.created_at, 'localtime')
|
||||||
|
WHEN :group_by = 1 THEN STRFTIME('%Y-%m', lae.created_at, 'localtime')
|
||||||
|
END as bucket_date
|
||||||
FROM
|
FROM
|
||||||
local_asset_entity lae
|
local_asset_entity lae
|
||||||
WHERE NOT EXISTS (
|
WHERE NOT EXISTS (
|
||||||
|
|||||||
+1
-1
@@ -79,7 +79,7 @@ class MergedAssetDrift extends i1.ModularAccessor {
|
|||||||
final expandeduserIds = $expandVar($arrayStartIndex, userIds.length);
|
final expandeduserIds = $expandVar($arrayStartIndex, userIds.length);
|
||||||
$arrayStartIndex += userIds.length;
|
$arrayStartIndex += userIds.length;
|
||||||
return customSelect(
|
return customSelect(
|
||||||
'SELECT COUNT(*) AS asset_count, CASE WHEN ?1 = 0 THEN STRFTIME(\'%Y-%m-%d\', created_at, \'localtime\') WHEN ?1 = 1 THEN STRFTIME(\'%Y-%m\', created_at, \'localtime\') END AS bucket_date FROM (SELECT rae.created_at FROM remote_asset_entity AS rae LEFT JOIN stack_entity AS se ON rae.stack_id = se.id WHERE rae.deleted_at IS NULL AND rae.visibility = 0 AND rae.owner_id IN ($expandeduserIds) AND(rae.stack_id IS NULL OR rae.id = se.primary_asset_id)UNION ALL SELECT lae.created_at FROM local_asset_entity AS lae WHERE NOT EXISTS (SELECT 1 FROM remote_asset_entity AS rae WHERE rae.checksum = lae.checksum AND rae.owner_id IN ($expandeduserIds)) AND EXISTS (SELECT 1 FROM local_album_asset_entity AS laa INNER JOIN local_album_entity AS la ON laa.album_id = la.id WHERE laa.asset_id = lae.id AND la.backup_selection = 0) AND NOT EXISTS (SELECT 1 FROM local_album_asset_entity AS laa INNER JOIN local_album_entity AS la ON laa.album_id = la.id WHERE laa.asset_id = lae.id AND la.backup_selection = 2)) GROUP BY bucket_date ORDER BY bucket_date DESC',
|
'SELECT COUNT(*) AS asset_count, bucket_date FROM (SELECT CASE WHEN ?1 = 0 THEN STRFTIME(\'%Y-%m-%d\', rae.local_date_time) WHEN ?1 = 1 THEN STRFTIME(\'%Y-%m\', rae.local_date_time) END AS bucket_date FROM remote_asset_entity AS rae LEFT JOIN stack_entity AS se ON rae.stack_id = se.id WHERE rae.deleted_at IS NULL AND rae.visibility = 0 AND rae.owner_id IN ($expandeduserIds) AND(rae.stack_id IS NULL OR rae.id = se.primary_asset_id)UNION ALL SELECT CASE WHEN ?1 = 0 THEN STRFTIME(\'%Y-%m-%d\', lae.created_at, \'localtime\') WHEN ?1 = 1 THEN STRFTIME(\'%Y-%m\', lae.created_at, \'localtime\') END AS bucket_date FROM local_asset_entity AS lae WHERE NOT EXISTS (SELECT 1 FROM remote_asset_entity AS rae WHERE rae.checksum = lae.checksum AND rae.owner_id IN ($expandeduserIds)) AND EXISTS (SELECT 1 FROM local_album_asset_entity AS laa INNER JOIN local_album_entity AS la ON laa.album_id = la.id WHERE laa.asset_id = lae.id AND la.backup_selection = 0) AND NOT EXISTS (SELECT 1 FROM local_album_asset_entity AS laa INNER JOIN local_album_entity AS la ON laa.album_id = la.id WHERE laa.asset_id = lae.id AND la.backup_selection = 2)) GROUP BY bucket_date ORDER BY bucket_date DESC',
|
||||||
variables: [
|
variables: [
|
||||||
i0.Variable<int>(groupBy),
|
i0.Variable<int>(groupBy),
|
||||||
for (var $ in userIds) i0.Variable<String>($),
|
for (var $ in userIds) i0.Variable<String>($),
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final assetCountExp = _db.localAssetEntity.id.count();
|
final assetCountExp = _db.localAssetEntity.id.count();
|
||||||
final dateExp = _db.localAssetEntity.createdAt.dateFmt(groupBy);
|
final dateExp = _db.localAssetEntity.createdAt.dateFmt(groupBy, toLocal: true);
|
||||||
|
|
||||||
final query =
|
final query =
|
||||||
_db.localAssetEntity.selectOnly().join([
|
_db.localAssetEntity.selectOnly().join([
|
||||||
@@ -203,7 +203,7 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
|||||||
final album = albums.first;
|
final album = albums.first;
|
||||||
final isAscending = album.order == AlbumAssetOrder.asc;
|
final isAscending = album.order == AlbumAssetOrder.asc;
|
||||||
final assetCountExp = _db.remoteAssetEntity.id.count();
|
final assetCountExp = _db.remoteAssetEntity.id.count();
|
||||||
final dateExp = _db.remoteAssetEntity.createdAt.dateFmt(groupBy);
|
final dateExp = _db.remoteAssetEntity.localDateTime.dateFmt(groupBy);
|
||||||
|
|
||||||
final query = _db.remoteAssetEntity.selectOnly()
|
final query = _db.remoteAssetEntity.selectOnly()
|
||||||
..addColumns([assetCountExp, dateExp])
|
..addColumns([assetCountExp, dateExp])
|
||||||
@@ -280,7 +280,8 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
|||||||
final sorted = List<BaseAsset>.from(assets)..sort((a, b) => b.createdAt.compareTo(a.createdAt));
|
final sorted = List<BaseAsset>.from(assets)..sort((a, b) => b.createdAt.compareTo(a.createdAt));
|
||||||
final Map<DateTime, int> bucketCounts = {};
|
final Map<DateTime, int> bucketCounts = {};
|
||||||
for (final asset in sorted) {
|
for (final asset in sorted) {
|
||||||
final date = DateTime(asset.createdAt.year, asset.createdAt.month, asset.createdAt.day);
|
final localTime = asset.createdAt.toLocal();
|
||||||
|
final date = DateTime(localTime.year, localTime.month, localTime.day);
|
||||||
bucketCounts[date] = (bucketCounts[date] ?? 0) + 1;
|
bucketCounts[date] = (bucketCounts[date] ?? 0) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,7 +361,7 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final assetCountExp = _db.remoteAssetEntity.id.count();
|
final assetCountExp = _db.remoteAssetEntity.id.count();
|
||||||
final dateExp = _db.remoteAssetEntity.createdAt.dateFmt(groupBy);
|
final dateExp = _db.remoteAssetEntity.localDateTime.dateFmt(groupBy);
|
||||||
|
|
||||||
final query = _db.remoteAssetEntity.selectOnly()
|
final query = _db.remoteAssetEntity.selectOnly()
|
||||||
..addColumns([assetCountExp, dateExp])
|
..addColumns([assetCountExp, dateExp])
|
||||||
@@ -430,7 +431,7 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final assetCountExp = _db.remoteAssetEntity.id.count();
|
final assetCountExp = _db.remoteAssetEntity.id.count();
|
||||||
final dateExp = _db.remoteAssetEntity.createdAt.dateFmt(groupBy);
|
final dateExp = _db.remoteAssetEntity.localDateTime.dateFmt(groupBy);
|
||||||
|
|
||||||
final query = _db.remoteAssetEntity.selectOnly()
|
final query = _db.remoteAssetEntity.selectOnly()
|
||||||
..addColumns([assetCountExp, dateExp])
|
..addColumns([assetCountExp, dateExp])
|
||||||
@@ -500,7 +501,7 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final assetCountExp = _db.remoteAssetEntity.id.count();
|
final assetCountExp = _db.remoteAssetEntity.id.count();
|
||||||
final dateExp = _db.remoteAssetEntity.createdAt.dateFmt(groupBy);
|
final dateExp = _db.remoteAssetEntity.localDateTime.dateFmt(groupBy);
|
||||||
|
|
||||||
final query = _db.remoteAssetEntity.selectOnly()
|
final query = _db.remoteAssetEntity.selectOnly()
|
||||||
..addColumns([assetCountExp, dateExp])
|
..addColumns([assetCountExp, dateExp])
|
||||||
@@ -602,7 +603,7 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final assetCountExp = _db.remoteAssetEntity.id.count();
|
final assetCountExp = _db.remoteAssetEntity.id.count();
|
||||||
final dateExp = _db.remoteAssetEntity.createdAt.dateFmt(groupBy);
|
final dateExp = _db.remoteAssetEntity.localDateTime.dateFmt(groupBy);
|
||||||
|
|
||||||
final query = _db.remoteAssetEntity.selectOnly()
|
final query = _db.remoteAssetEntity.selectOnly()
|
||||||
..addColumns([assetCountExp, dateExp])
|
..addColumns([assetCountExp, dateExp])
|
||||||
@@ -664,10 +665,11 @@ List<Bucket> _generateBuckets(int count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension on Expression<DateTime> {
|
extension on Expression<DateTime> {
|
||||||
Expression<String> dateFmt(GroupAssetsBy groupBy) {
|
Expression<String> dateFmt(GroupAssetsBy groupBy, {bool toLocal = false}) {
|
||||||
// DateTimes are stored in UTC, so we need to convert them to local time inside the query before formatting
|
// DateTimes are stored in UTC, so we need to convert them to local time inside the query before formatting
|
||||||
// to create the correct time bucket
|
// to create the correct time bucket when toLocal is true
|
||||||
final localTimeExp = modify(const DateTimeModifier.localTime());
|
// toLocal is false for remote assets where localDateTime is already in the correct timezone
|
||||||
|
final localTimeExp = toLocal ? modify(const DateTimeModifier.localTime()) : this;
|
||||||
return switch (groupBy) {
|
return switch (groupBy) {
|
||||||
GroupAssetsBy.day || GroupAssetsBy.auto => localTimeExp.date,
|
GroupAssetsBy.day || GroupAssetsBy.auto => localTimeExp.date,
|
||||||
GroupAssetsBy.month => localTimeExp.strftime("%Y-%m"),
|
GroupAssetsBy.month => localTimeExp.strftime("%Y-%m"),
|
||||||
|
|||||||
Reference in New Issue
Block a user