Updates for new ignore timezone setting
BIN
demo/images/4MinsAroundTheWorld/20240413-203800-Unknown.jpg
Normal file
After Width: | Height: | Size: 70 KiB |
BIN
demo/images/4MinsAroundTheWorld/UTC-20240413-203430-Auckland.jpg
Normal file
After Width: | Height: | Size: 61 KiB |
After Width: | Height: | Size: 62 KiB |
After Width: | Height: | Size: 61 KiB |
BIN
demo/images/4MinsAroundTheWorld/UTC-20240413-203630-London.jpg
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
demo/images/4MinsAroundTheWorld/UTC-20240413-203720-Tokyo.jpg
Normal file
After Width: | Height: | Size: 59 KiB |
After Width: | Height: | Size: 58 KiB |
BIN
demo/images/4MinsAroundTheWorld/UTC-20240413-203830-NewYork.jpg
Normal file
After Width: | Height: | Size: 61 KiB |
@ -364,7 +364,11 @@ export class SearchManager {
|
||||
for (const sort of sortings) {
|
||||
switch (sort.method) {
|
||||
case SortByTypes.Date:
|
||||
query.addOrderBy('media.metadata.creationDate', sort.ascending ? 'ASC' : 'DESC'); //TODO: Offset: If media.metadata.creationDateOffset is defined, it is an offset of minutes (+/-). If taken into account, it will alter the sort order. Probably should not be done.
|
||||
if (Config.Gallery.ignoreTimestampOffset === true) {
|
||||
query.addOrderBy('media.metadata.creationDate + (media.metadata.creationDateOffset * 60000)', sort.ascending ? 'ASC' : 'DESC');
|
||||
} else {
|
||||
query.addOrderBy('media.metadata.creationDate', sort.ascending ? 'ASC' : 'DESC');
|
||||
}
|
||||
break;
|
||||
case SortByTypes.Rating:
|
||||
query.addOrderBy('media.metadata.rating', sort.ascending ? 'ASC' : 'DESC');
|
||||
@ -562,15 +566,17 @@ export class SearchManager {
|
||||
|
||||
const textParam: { [key: string]: unknown } = {};
|
||||
textParam['from' + queryId] = (query as FromDateSearch).value;
|
||||
q.where(
|
||||
`media.metadata.creationDate ${relation} :from${queryId}`, //TODO: Offset: If media.metadata.creationDateOffset is defined, it is an offset of minutes (+/-).
|
||||
//Example: -600 means in the database UTC-10:00. The time 20:00 in the evening in the UTC-10 timezone, is actually 06:00 the next morning
|
||||
//in UTC+00:00. To make search take that into account, one can subtract the offset from the creationDate to "pretend" the photo is taken
|
||||
//in UTC time. Subtracting -600 minutes (because it's the -10:00 timezone), corresponds to adding 10 hours to the photo's timestamp, thus
|
||||
//bringing it into the next day as if it was taken at UTC+00:00. Similarly subtracting a positive timezone from a timestamp will "pretend"
|
||||
//the photo is taken earlier in time (e.g. subtracting 300 from the UTC+05:00 timezone).
|
||||
textParam
|
||||
);
|
||||
if (Config.Gallery.ignoreTimestampOffset === true) {
|
||||
q.where(
|
||||
`(media.metadata.creationDate + (media.metadata.creationDateOffset * 60000)) ${relation} :from${queryId}`,
|
||||
textParam
|
||||
);
|
||||
} else {
|
||||
q.where(
|
||||
`media.metadata.creationDate ${relation} :from${queryId}`,
|
||||
textParam
|
||||
);
|
||||
}
|
||||
|
||||
return q;
|
||||
});
|
||||
@ -589,10 +595,18 @@ export class SearchManager {
|
||||
|
||||
const textParam: { [key: string]: unknown } = {};
|
||||
textParam['to' + queryId] = (query as ToDateSearch).value;
|
||||
q.where(
|
||||
`media.metadata.creationDate ${relation} :to${queryId}`, //TODO: Offset: If media.metadata.creationDateOffset is defined, it is an offset of minutes (+/-). See explanation above.
|
||||
textParam
|
||||
);
|
||||
if (Config.Gallery.ignoreTimestampOffset === true) {
|
||||
q.where(
|
||||
`(media.metadata.creationDate + (media.metadata.creationDateOffset * 60000)) ${relation} :to${queryId}`,
|
||||
textParam
|
||||
);
|
||||
} else {
|
||||
q.where(
|
||||
`media.metadata.creationDate ${relation} :to${queryId}`,
|
||||
textParam
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
return q;
|
||||
});
|
||||
@ -793,18 +807,25 @@ export class SearchManager {
|
||||
textParam['to' + queryId] = to.getTime();
|
||||
textParam['from' + queryId] = from.getTime();
|
||||
if (tq.negate) {
|
||||
if (Config.Gallery.ignoreTimestampOffset === true) {
|
||||
q.where(
|
||||
`(media.metadata.creationDate + (media.metadata.creationDateOffset * 60000)) >= :to${queryId}`,
|
||||
textParam
|
||||
).orWhere(`media.metadata.creationDate < :from${queryId}`,
|
||||
textParam);
|
||||
} else {
|
||||
|
||||
q.where(
|
||||
`media.metadata.creationDate >= :to${queryId}`, //TODO: Offset: If media.metadata.creationDateOffset is defined, it is an offset of minutes (+/-). See explanation above.
|
||||
textParam
|
||||
).orWhere(`media.metadata.creationDate < :from${queryId}`, //TODO: Offset: If media.metadata.creationDateOffset is defined, it is an offset of minutes (+/-). See explanation above.
|
||||
textParam);
|
||||
}
|
||||
} else {
|
||||
q.where(
|
||||
`media.metadata.creationDate < :to${queryId}`, //TODO: Offset: If media.metadata.creationDateOffset is defined, it is an offset of minutes (+/-). See explanation above.
|
||||
textParam
|
||||
).andWhere(`media.metadata.creationDate >= :from${queryId}`, //TODO: Offset: If media.metadata.creationDateOffset is defined, it is an offset of minutes (+/-). See explanation above.
|
||||
textParam);
|
||||
if (Config.Gallery.ignoreTimestampOffset === true) {
|
||||
q.where(
|
||||
`(media.metadata.creationDate + (media.metadata.creationDateOffset * 60000)) < :to${queryId}`,
|
||||
textParam
|
||||
).andWhere(`media.metadata.creationDate >= :from${queryId}`,
|
||||
textParam);
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -824,30 +845,54 @@ export class SearchManager {
|
||||
|
||||
|
||||
if (Config.Database.type === DatabaseType.sqlite) {
|
||||
//(media.metadata.creationDate + (media.metadata.creationDateOffset * 60000))
|
||||
|
||||
if (tq.daysLength == 0) {
|
||||
q.where(
|
||||
//TODO: Offset: If media.metadata.creationDateOffset is defined, it is an offset of minutes (+/-). See explanation above.
|
||||
`CAST(strftime('${duration}',media.metadataCreationDate/1000, 'unixepoch') AS INTEGER) ${relationEql} CAST(strftime('${duration}','now') AS INTEGER)`
|
||||
);
|
||||
if (Config.Gallery.ignoreTimestampOffset === true) {
|
||||
q.where(
|
||||
`CAST(strftime('${duration}',(media.metadataCreationDate + (media.metadataCreationDateOffset * 60000))/1000, 'unixepoch') AS INTEGER) ${relationEql} CAST(strftime('${duration}','now') AS INTEGER)`
|
||||
);
|
||||
} else {
|
||||
q.where(
|
||||
`CAST(strftime('${duration}',media.metadataCreationDate/1000, 'unixepoch') AS INTEGER) ${relationEql} CAST(strftime('${duration}','now') AS INTEGER)`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
q.where(
|
||||
//TODO: Offset: If media.metadata.creationDateOffset is defined, it is an offset of minutes (+/-). See explanation above.
|
||||
`CAST(strftime('${duration}',media.metadataCreationDate/1000, 'unixepoch') AS INTEGER) ${relationTop} CAST(strftime('${duration}','now') AS INTEGER)`
|
||||
)[whereFN](`CAST(strftime('${duration}',media.metadataCreationDate/1000, 'unixepoch') AS INTEGER) ${relationBottom} CAST(strftime('${duration}','now','-:diff${queryId} day') AS INTEGER)`,
|
||||
textParam);
|
||||
if (Config.Gallery.ignoreTimestampOffset === true) {
|
||||
q.where(
|
||||
`CAST(strftime('${duration}',(media.metadataCreationDate + (media.metadataCreationDateOffset * 60000))/1000, 'unixepoch') AS INTEGER) ${relationTop} CAST(strftime('${duration}','now') AS INTEGER)`
|
||||
)[whereFN](`CAST(strftime('${duration}',(media.metadataCreationDate + (media.metadataCreationDateOffset * 60000))/1000, 'unixepoch') AS INTEGER) ${relationBottom} CAST(strftime('${duration}','now','-:diff${queryId} day') AS INTEGER)`,
|
||||
textParam);
|
||||
} else {
|
||||
q.where(
|
||||
`CAST(strftime('${duration}',media.metadataCreationDate/1000, 'unixepoch') AS INTEGER) ${relationTop} CAST(strftime('${duration}','now') AS INTEGER)`
|
||||
)[whereFN](`CAST(strftime('${duration}',media.metadataCreationDate/1000, 'unixepoch') AS INTEGER) ${relationBottom} CAST(strftime('${duration}','now','-:diff${queryId} day') AS INTEGER)`,
|
||||
textParam);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (tq.daysLength == 0) {
|
||||
q.where(
|
||||
//TODO: Offset: If media.metadata.creationDateOffset is defined, it is an offset of minutes (+/-). See explanation above.
|
||||
`CAST(FROM_UNIXTIME(media.metadataCreationDate/1000, '${duration}') AS SIGNED) ${relationEql} CAST(DATE_FORMAT(CURDATE(),'${duration}') AS SIGNED)`
|
||||
);
|
||||
if (Config.Gallery.ignoreTimestampOffset === true) {
|
||||
q.where(
|
||||
`CAST(FROM_UNIXTIME((media.metadataCreationDate + (media.metadataCreationDateOffset * 60000))/1000, '${duration}') AS SIGNED) ${relationEql} CAST(DATE_FORMAT(CURDATE(),'${duration}') AS SIGNED)`
|
||||
);
|
||||
} else {
|
||||
q.where(
|
||||
`CAST(FROM_UNIXTIME(media.metadataCreationDate/1000, '${duration}') AS SIGNED) ${relationEql} CAST(DATE_FORMAT(CURDATE(),'${duration}') AS SIGNED)`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
q.where(
|
||||
//TODO: Offset: If media.metadata.creationDateOffset is defined, it is an offset of minutes (+/-). See explanation above.
|
||||
`CAST(FROM_UNIXTIME(media.metadataCreationDate/1000, '${duration}') AS SIGNED) ${relationTop} CAST(DATE_FORMAT(CURDATE(),'${duration}') AS SIGNED)`
|
||||
)[whereFN](`CAST(FROM_UNIXTIME(media.metadataCreationDate/1000, '${duration}') AS SIGNED) ${relationBottom} CAST(DATE_FORMAT((DATE_ADD(curdate(), INTERVAL -:diff${queryId} DAY)),'${duration}') AS SIGNED)`,
|
||||
textParam);
|
||||
if (Config.Gallery.ignoreTimestampOffset === true) {
|
||||
q.where(
|
||||
`CAST(FROM_UNIXTIME((media.metadataCreationDate + (media.metadataCreationDateOffset * 60000))/1000, '${duration}') AS SIGNED) ${relationTop} CAST(DATE_FORMAT(CURDATE(),'${duration}') AS SIGNED)`
|
||||
)[whereFN](`CAST(FROM_UNIXTIME((media.metadataCreationDate + (media.metadataCreationDateOffset * 60000))/1000, '${duration}') AS SIGNED) ${relationBottom} CAST(DATE_FORMAT((DATE_ADD(curdate(), INTERVAL -:diff${queryId} DAY)),'${duration}') AS SIGNED)`,
|
||||
textParam);
|
||||
} else {
|
||||
q.where(
|
||||
`CAST(FROM_UNIXTIME(media.metadataCreationDate/1000, '${duration}') AS SIGNED) ${relationTop} CAST(DATE_FORMAT(CURDATE(),'${duration}') AS SIGNED)`
|
||||
)[whereFN](`CAST(FROM_UNIXTIME(media.metadataCreationDate/1000, '${duration}') AS SIGNED) ${relationBottom} CAST(DATE_FORMAT((DATE_ADD(curdate(), INTERVAL -:diff${queryId} DAY)),'${duration}') AS SIGNED)`,
|
||||
textParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -277,8 +277,8 @@ export class DiskManager {
|
||||
directory.oldestMedia = Number.MIN_SAFE_INTEGER;
|
||||
|
||||
directory.media.forEach((m) => {
|
||||
directory.youngestMedia = Math.min(m.metadata.creationDate, directory.youngestMedia); //TODO: Offset:
|
||||
directory.oldestMedia = Math.max(m.metadata.creationDate, directory.oldestMedia);
|
||||
directory.youngestMedia = Math.min(Utils.getTimeMS(m.metadata.creationDate, m.metadata.creationDateOffset, Config.Gallery.ignoreTimestampOffset), directory.youngestMedia);
|
||||
directory.oldestMedia = Math.max(Utils.getTimeMS(m.metadata.creationDate, m.metadata.creationDateOffset, Config.Gallery.ignoreTimestampOffset), directory.oldestMedia);
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -70,7 +70,7 @@ export class EmailMessenger extends Messenger<{
|
||||
(media[i].metadata as PhotoMetadata).positionData?.country :
|
||||
((media[i].metadata as PhotoMetadata).positionData?.city ?
|
||||
(media[i].metadata as PhotoMetadata).positionData?.city : '');
|
||||
const caption = Utils.getFullYear(media[i].metadata.creationDate, media[i].metadata.creationDateOffset) + (location ? ', ' + location : ''); //TODO: Offset:
|
||||
const caption = Utils.getFullYear(Utils.getTimeMS(media[i].metadata.creationDate, media[i].metadata.creationDateOffset, Config.Gallery.ignoreTimestampOffset), undefined) + (location ? ', ' + location : '');
|
||||
attachments.push({
|
||||
filename: media[i].name,
|
||||
path: media[i].thumbnailPath,
|
||||
|
@ -33,7 +33,7 @@ export abstract class Messenger<C extends Record<string, unknown> = Record<strin
|
||||
if (Array.isArray(input) && input.length > 0
|
||||
&& (input as MediaDTO[])[0]?.name
|
||||
&& (input as MediaDTO[])[0]?.directory
|
||||
&& (input as MediaDTO[])[0]?.metadata?.creationDate) { //TODO: Offset:
|
||||
&& (input as MediaDTO[])[0]?.metadata?.creationDate) {
|
||||
const media = input as MediaDTOWithThPath[];
|
||||
for (let i = 0; i < media.length; ++i) {
|
||||
media[i].thumbnailPath = await this.getThumbnail(media[i]);
|
||||
|
@ -227,11 +227,20 @@ export class Utils {
|
||||
}
|
||||
|
||||
//Get the MS of the creationDate, adjusted for the offset. Effectively getting the MS value as if the photo did not contain an offset.
|
||||
//One can consider this "Local" time of the photo.
|
||||
//One can consider this "Local" time of the photo. Starting point is UTC, as MetadataLoader loads timestamps with unknown timestamps as UTC.
|
||||
static getLocalTimeMS(creationDate: number, creationDateOffset: string) {
|
||||
const offsetMinutes = Utils.getOffsetMinutes(creationDateOffset);
|
||||
return creationDate + (offsetMinutes ? (offsetMinutes * 60000) : 0);
|
||||
}
|
||||
|
||||
//Like getLocalTimeMS, but only if localTime is true, otherwise just returns creationDate (global time)
|
||||
static getTimeMS(creationDate: number, creationDateOffset: string, localTime: boolean) {
|
||||
if (localTime) {
|
||||
return Utils.getLocalTimeMS(creationDate, creationDateOffset);
|
||||
} else {
|
||||
return creationDate;
|
||||
}
|
||||
}
|
||||
|
||||
static isLeapYear(year: number) {
|
||||
return (0 == year % 4) && (0 != year % 100) || (0 == year % 400)
|
||||
|
@ -1089,7 +1089,10 @@ export class ClientGalleryConfig {
|
||||
},
|
||||
description: $localize`If enabled, timestamp offsets are ignored, meaning that the local times of pictures are used for searching, sorting and grouping. If disabled, global time is used and pictures with no timestamp are assumed to be in UTC (offset +00:00).`
|
||||
})
|
||||
ignoreTimestampOffset: boolean = true;
|
||||
//DEVELOPER NOTE: The Database model stores the timestamp (creationDate) as milliseconds since 1970-01-01 UTC (global time). And stores and offset (creationDateOffset) as minutes.
|
||||
//Ignoring timestamp for the user is the opposite for the database. If the user wants to ignore the offset, we have to add the offset to the creationDate to give the user the right experience.
|
||||
ignoreTimestampOffset: boolean = true;
|
||||
|
||||
|
||||
@ConfigProperty({
|
||||
tags: {
|
||||
|
@ -23,7 +23,7 @@
|
||||
<div class="col-2 align-self-center">
|
||||
{{media.metadata.fileSize | fileSize}}
|
||||
</div>
|
||||
<div class="col-3 align-self-center" [title]="media.metadata.creationDate"> <!-- //TODO: Offset: -->
|
||||
<div class="col-3 align-self-center" [title]="media.metadata.creationDate">
|
||||
{{ media.metadata.creationDate | date : 'longDate' : (media.metadata.creationDateOffset ? media.metadata.creationDateOffset : 'UTC') }},
|
||||
{{ media.metadata.creationDate | date : (media.metadata.creationDateOffset ? 'HH:mm:ss ZZZZZ' : 'HH:mm:ss') : (media.metadata.creationDateOffset ? media.metadata.creationDateOffset : 'UTC') }}
|
||||
</div>
|
||||
|
@ -6,6 +6,7 @@ import {ContentService} from '../content.service';
|
||||
import {mergeMap, Observable, shareReplay} from 'rxjs';
|
||||
import {MDFilesFilterPipe} from '../../../pipes/MDFilesFilterPipe';
|
||||
import {MDFileDTO} from '../../../../../common/entities/MDFileDTO';
|
||||
import {Config} from '../../../../../common/config/public/Config';
|
||||
|
||||
@Injectable()
|
||||
export class BlogService {
|
||||
@ -28,7 +29,7 @@ export class BlogService {
|
||||
let firstMedia = Number.MAX_SAFE_INTEGER;
|
||||
if (content.mediaGroups.length > 0) {
|
||||
firstMedia = content.mediaGroups[0].media.reduce((p, m) =>
|
||||
Math.min(m.metadata.creationDate, p), Number.MAX_SAFE_INTEGER); //TODO: Offset:
|
||||
Math.min(Utils.getTimeMS(m.metadata.creationDate, m.metadata.creationDateOffset, Config.Gallery.ignoreTimestampOffset), p), Number.MAX_SAFE_INTEGER);
|
||||
}
|
||||
|
||||
const files = this.mdFilesFilterPipe.transform(content.metaFile)
|
||||
|
@ -3,6 +3,8 @@ import {BehaviorSubject, Observable} from 'rxjs';
|
||||
import {PhotoDTO} from '../../../../../common/entities/PhotoDTO';
|
||||
import {DirectoryContent} from '../contentLoader.service';
|
||||
import {map, switchMap} from 'rxjs/operators';
|
||||
import {Config} from '../../../../../common/config/public/Config';
|
||||
import {Utils} from '../../../../../common/Utils';
|
||||
|
||||
export enum FilterRenderType {
|
||||
enum = 1,
|
||||
@ -159,11 +161,11 @@ export class FilterService {
|
||||
}
|
||||
const ret: { date: Date, endDate: Date, dateStr: string, count: number, max: number }[] = [];
|
||||
const minDate = prefiltered.media.reduce(
|
||||
(p, curr) => Math.min(p, curr.metadata.creationDate), //TODO: Offset:
|
||||
(p, curr) => Math.min(p, Utils.getTimeMS(curr.metadata.creationDate, curr.metadata.creationDateOffset, Config.Gallery.ignoreTimestampOffset)),
|
||||
Number.MAX_VALUE - 1
|
||||
);
|
||||
const maxDate = prefiltered.media.reduce(
|
||||
(p, curr) => Math.max(p, curr.metadata.creationDate), //TODO: Offset:
|
||||
(p, curr) => Math.max(p, Utils.getTimeMS(curr.metadata.creationDate, curr.metadata.creationDateOffset, Config.Gallery.ignoreTimestampOffset)),
|
||||
Number.MIN_VALUE + 1
|
||||
);
|
||||
const diff = (maxDate - minDate) / 1000;
|
||||
@ -205,7 +207,7 @@ export class FilterService {
|
||||
const startMediaDate = new Date(floorDate(minDate));
|
||||
|
||||
prefiltered.media.forEach(m => {
|
||||
const key = Math.floor((floorDate(m.metadata.creationDate) - startMediaDate.getTime()) / 1000 / usedDiv); //TODO: Offset:
|
||||
const key = Math.floor((floorDate(Utils.getTimeMS(m.metadata.creationDate, m.metadata.creationDateOffset, Config.Gallery.ignoreTimestampOffset)) - startMediaDate.getTime()) / 1000 / usedDiv);
|
||||
|
||||
const getDate = (index: number) => {
|
||||
let d: Date;
|
||||
@ -273,16 +275,16 @@ export class FilterService {
|
||||
if (c.media.length > 0) {
|
||||
// Update date filter range
|
||||
afilters.dateFilter.minDate = c.media.reduce(
|
||||
(p, curr) => Math.min(p, curr.metadata.creationDate), //TODO: Offset:
|
||||
(p, curr) => Math.min(p, Utils.getTimeMS(curr.metadata.creationDate, curr.metadata.creationDateOffset, Config.Gallery.ignoreTimestampOffset)),
|
||||
Number.MAX_VALUE - 1
|
||||
);
|
||||
afilters.dateFilter.maxDate = c.media.reduce(
|
||||
(p, curr) => Math.max(p, curr.metadata.creationDate), //TODO: Offset:
|
||||
(p, curr) => Math.max(p, Utils.getTimeMS(curr.metadata.creationDate, curr.metadata.creationDateOffset, Config.Gallery.ignoreTimestampOffset)),
|
||||
Number.MIN_VALUE + 1
|
||||
);
|
||||
// Add a few sec padding
|
||||
afilters.dateFilter.minDate -= (afilters.dateFilter.minDate % 1000) + 1000;
|
||||
afilters.dateFilter.maxDate += (afilters.dateFilter.maxDate % 1000) + 1000;
|
||||
afilters.dateFilter.minDate -= ((afilters.dateFilter.minDate % 1000) + 1000);
|
||||
afilters.dateFilter.maxDate += ((1000 - (afilters.dateFilter.maxDate % 1000)) + 1000);
|
||||
|
||||
if (afilters.dateFilter.minFilter === Number.MIN_VALUE) {
|
||||
afilters.dateFilter.minFilter = afilters.dateFilter.minDate;
|
||||
@ -294,8 +296,8 @@ export class FilterService {
|
||||
// Apply Date filter
|
||||
c.media = c.media.filter(
|
||||
(m) =>
|
||||
m.metadata.creationDate >= afilters.dateFilter.minFilter && //TODO: Offset:
|
||||
m.metadata.creationDate <= afilters.dateFilter.maxFilter //TODO: Offset:
|
||||
Utils.getTimeMS(m.metadata.creationDate, m.metadata.creationDateOffset, Config.Gallery.ignoreTimestampOffset) >= afilters.dateFilter.minFilter &&
|
||||
Utils.getTimeMS(m.metadata.creationDate, m.metadata.creationDateOffset, Config.Gallery.ignoreTimestampOffset) <= afilters.dateFilter.maxFilter
|
||||
);
|
||||
} else {
|
||||
afilters.dateFilter.minDate = Number.MIN_VALUE;
|
||||
|
@ -508,7 +508,7 @@ export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges {
|
||||
case LightBoxTitleTexts.persons:
|
||||
return m.metadata.faces?.map(f => f.name)?.join(', ');
|
||||
case LightBoxTitleTexts.date:
|
||||
return this.datePipe.transform(m.metadata.creationDate, 'longDate', m.metadata.creationDateOffset); //TODO: Offset:
|
||||
return this.datePipe.transform(Utils.getTimeMS(m.metadata.creationDate, m.metadata.creationDateOffset, Config.Gallery.ignoreTimestampOffset) , 'longDate', 'UTC');
|
||||
case LightBoxTitleTexts.location:
|
||||
if (!m.metadata.positionData) {
|
||||
return '';
|
||||
|
@ -54,7 +54,7 @@
|
||||
</div>
|
||||
<div class="col-11">
|
||||
<div class="details-main">
|
||||
{{ media.metadata.creationDate | date: (isThisYear() ? 'MMMM d' : 'longDate') : (media.metadata.creationDateOffset ? media.metadata.creationDateOffset : 'UTC') }} <!-- //TODO: Offset: -->
|
||||
{{ media.metadata.creationDate | date: (isThisYear() ? 'MMMM d' : 'longDate') : (media.metadata.creationDateOffset ? media.metadata.creationDateOffset : 'UTC') }}
|
||||
</div>
|
||||
<div class="details-sub text-secondary row">
|
||||
<div class="col-12">{{ media.metadata.creationDate | date : (media.metadata.creationDateOffset ? 'EEEE, HH:mm:ss ZZZZZ' : 'EEEE, HH:mm:ss') : (media.metadata.creationDateOffset ? media.metadata.creationDateOffset : 'UTC') }}</div>
|
||||
|
@ -150,11 +150,7 @@ export class GallerySortingService {
|
||||
break;
|
||||
case SortByTypes.Date:
|
||||
media.sort((a: PhotoDTO, b: PhotoDTO): number => {
|
||||
if (Config.Gallery.ignoreTimestampOffset === true) {
|
||||
return Utils.getLocalTimeMS(a.metadata.creationDate, a.metadata.creationDateOffset) - Utils.getLocalTimeMS(b.metadata.creationDate, b.metadata.creationDateOffset);
|
||||
} else {
|
||||
return a.metadata.creationDate - b.metadata.creationDate;
|
||||
}
|
||||
return Utils.getTimeMS(a.metadata.creationDate, a.metadata.creationDateOffset, Config.Gallery.ignoreTimestampOffset) - Utils.getTimeMS(b.metadata.creationDate, b.metadata.creationDateOffset, Config.Gallery.ignoreTimestampOffset);
|
||||
});
|
||||
break;
|
||||
case SortByTypes.Rating:
|
||||
@ -204,7 +200,7 @@ export class GallerySortingService {
|
||||
//Datepipe used this way, converts creationDate to date in local time.
|
||||
return (m: MediaDTO) => this.datePipe.transform(m.metadata.creationDate, 'longDate', m.metadata.creationDateOffset ? m.metadata.creationDateOffset : 'UTC');
|
||||
} else {
|
||||
//Grouping with global time, requires a common timeframe. Here and now it is UTC. (Could be config option later) //TODO: Configurable Default Timezone
|
||||
//Grouping with global time, requires a common timeframe.
|
||||
return (m: MediaDTO) => this.datePipe.transform(m.metadata.creationDate, 'longDate', 'UTC');
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 70 KiB |
@ -0,0 +1,8 @@
|
||||
{
|
||||
"creationDate": 1713040680000,
|
||||
"fileSize": 71525,
|
||||
"size": {
|
||||
"height": 1080,
|
||||
"width": 1920
|
||||
}
|
||||
}
|
@ -173,7 +173,7 @@ describe('Typeorm integration', () => {
|
||||
|
||||
const photos = await pr
|
||||
.createQueryBuilder('media')
|
||||
.orderBy('media.metadata.creationDate', 'ASC') //TODO: Offset:
|
||||
.orderBy('media.metadata.creationDate', 'ASC') //TODO: Offset: Create a test where it is ".orderBy('media.metadata.creationDate + (media.metadata.creationDateOffset * 60000)', 'ASC')" instead
|
||||
.where('media.metadata.positionData.city LIKE :text COLLATE utf8_general_ci', {text: '%' + photo.metadata.positionData.city + '%'})
|
||||
.innerJoinAndSelect('media.directory', 'directory')
|
||||
.limit(10)
|
||||
@ -195,7 +195,7 @@ describe('Typeorm integration', () => {
|
||||
await pr.save(photo);
|
||||
const photos = await pr
|
||||
.createQueryBuilder('media')
|
||||
.orderBy('media.metadata.creationDate', 'ASC') //TODO: Offset:
|
||||
.orderBy('media.metadata.creationDate', 'ASC') //TODO: Offset: Create a test where it is ".orderBy('media.metadata.creationDate + (media.metadata.creationDateOffset * 60000)', 'ASC')" instead
|
||||
.where('media.metadata.positionData.city LIKE :text COLLATE utf8_general_ci', {text: '%' + city + '%'})
|
||||
.innerJoinAndSelect('media.directory', 'directory')
|
||||
.limit(10)
|
||||
|