Skip to content

Commit

Permalink
Merge branch 'feat/nullable-dates' of https://github.com/immich-app/i…
Browse files Browse the repository at this point in the history
…mmich into feat/inline-offline-check
  • Loading branch information
etnoy committed Feb 8, 2025
2 parents 77d3111 + c3c6ba6 commit 9217757
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 62 deletions.
2 changes: 0 additions & 2 deletions server/src/services/asset-media.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,6 @@ describe(AssetMediaService.name, () => {

it('should throw an error if the requested preview file does not exist', async () => {
accessMock.asset.checkOwnerAccess.mockResolvedValue(new Set([assetStub.image.id]));

assetMock.getById.mockResolvedValue({
...assetStub.image,
files: [
Expand All @@ -563,7 +562,6 @@ describe(AssetMediaService.name, () => {

it('should fall back to preview if the requested thumbnail file does not exist', async () => {
accessMock.asset.checkOwnerAccess.mockResolvedValue(new Set([assetStub.image.id]));

assetMock.getById.mockResolvedValue({
...assetStub.image,
files: [
Expand Down
3 changes: 1 addition & 2 deletions server/src/services/library.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -574,8 +574,7 @@ export class LibraryService extends BaseService {
}

const mtime = stat.mtime;

const isTimeUpdated = asset.fileModifiedAt === null || mtime.toISOString() !== asset.fileModifiedAt.toISOString();
const isTimeUpdated = !asset.fileModifiedAt || mtime.toISOString() !== asset.fileModifiedAt.toISOString();

if (isTimeUpdated) {
this.logger.verbose(
Expand Down
20 changes: 3 additions & 17 deletions server/src/services/metadata.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BadRequestException, Injectable } from '@nestjs/common';
import { Injectable } from '@nestjs/common';
import { ContainerDirectoryItem, ExifDateTime, Maybe, Tags } from 'exiftool-vendored';
import { firstDateTime } from 'exiftool-vendored/dist/FirstDateTime';
import { Insertable } from 'kysely';
Expand Down Expand Up @@ -588,17 +588,7 @@ export class MetadataService extends BaseService {
}
}

private getDates(asset: AssetEntity, exifTags: ImmichTags): AssetDatesDto {
// We first assert that fileCreatedAt and fileModifiedAt are not null since that should be set to a non-null value before calling this function
if (asset.fileCreatedAt === null) {
this.logger.warn(`Asset ${asset.id} has no file creation date`);
throw new BadRequestException(`Asset ${asset.id} has no file creation date`);
}
if (asset.fileModifiedAt === null) {
this.logger.warn(`Asset ${asset.id} has no file modification date`);
throw new BadRequestException(`Asset ${asset.id} has no file modification date`);
}

private getDates(asset: AssetEntity, exifTags: ImmichTags) {
const dateTime = firstDateTime(exifTags as Maybe<Tags>, EXIF_DATE_TAGS);
this.logger.verbose(`Asset ${asset.id} date time is ${dateTime}`);

Expand Down Expand Up @@ -630,11 +620,7 @@ export class MetadataService extends BaseService {
localDateTime = earliestDate;
}

if (localDateTime) {
this.logger.verbose(`Asset ${asset.id} has a local time of ${localDateTime.toISOString()}`);
} else {
this.logger.verbose(`Asset ${asset.id} has no time set`);
}
this.logger.verbose(`Asset ${asset.id} has a local time of ${localDateTime.toISOString()}`);

let modifyDate = asset.fileModifiedAt;
try {
Expand Down
6 changes: 0 additions & 6 deletions server/src/services/storage-template.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -310,12 +310,6 @@ export class StorageTemplateService extends BaseService {

const systemTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
const zone = asset.exifInfo?.timeZone || systemTimeZone;

if (!asset.fileCreatedAt) {
this.logger.log(`Asset ${asset.id} is missing fileCreatedAt, skipping storage template migration`);
throw new Error(`Missing fileCreatedAt for asset ${asset.id}`);
}

const dt = DateTime.fromJSDate(asset.fileCreatedAt, { zone });

for (const token of Object.values(storageTokens).flat()) {
Expand Down
52 changes: 17 additions & 35 deletions server/test/medium/metadata.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ type TimeZoneTest = {
description: string;
serverTimeZone?: string;
exifData: Record<string, any>;
fileCreatedAt: Date;
fileModifiedAt: Date;
expected: {
localDateTime: string;
dateTimeOriginal: string;
Expand Down Expand Up @@ -60,8 +58,6 @@ describe(MetadataService.name, () => {
const timeZoneTests: TimeZoneTest[] = [
{
description: 'should handle no time zone information',
fileCreatedAt: new Date('2022-01-01T00:00:00.000Z'),
fileModifiedAt: new Date('2022-01-01T00:00:00.000Z'),
exifData: {
DateTimeOriginal: '2022:01:01 00:00:00',
},
Expand All @@ -73,8 +69,6 @@ describe(MetadataService.name, () => {
},
{
description: 'should handle no time zone information and server behind UTC',
fileCreatedAt: new Date('2022-01-01T00:00:00.000Z'),
fileModifiedAt: new Date('2022-01-01T00:00:00.000Z'),
serverTimeZone: 'America/Los_Angeles',
exifData: {
DateTimeOriginal: '2022:01:01 00:00:00',
Expand All @@ -87,8 +81,6 @@ describe(MetadataService.name, () => {
},
{
description: 'should handle no time zone information and server ahead of UTC',
fileCreatedAt: new Date('2022-01-01T00:00:00.000Z'),
fileModifiedAt: new Date('2022-01-01T00:00:00.000Z'),
serverTimeZone: 'Europe/Brussels',
exifData: {
DateTimeOriginal: '2022:01:01 00:00:00',
Expand All @@ -101,8 +93,6 @@ describe(MetadataService.name, () => {
},
{
description: 'should handle no time zone information and server ahead of UTC in the summer',
fileCreatedAt: new Date('2022-01-01T00:00:00.000Z'),
fileModifiedAt: new Date('2022-01-01T00:00:00.000Z'),
serverTimeZone: 'Europe/Brussels',
exifData: {
DateTimeOriginal: '2022:06:01 00:00:00',
Expand All @@ -115,8 +105,6 @@ describe(MetadataService.name, () => {
},
{
description: 'should handle a +13:00 time zone',
fileCreatedAt: new Date('2022-01-01T00:00:00.000Z'),
fileModifiedAt: new Date('2022-01-01T00:00:00.000Z'),
exifData: {
DateTimeOriginal: '2022:01:01 00:00:00+13:00',
},
Expand All @@ -128,32 +116,26 @@ describe(MetadataService.name, () => {
},
];

it.each(timeZoneTests)(
'$description',
async ({ exifData, serverTimeZone, expected, fileCreatedAt, fileModifiedAt }) => {
// TODO: the TZ environment variable is no longer used, remove it
process.env.TZ = serverTimeZone ?? undefined;
it.each(timeZoneTests)('$description', async ({ exifData, serverTimeZone, expected }) => {
process.env.TZ = serverTimeZone ?? undefined;

const { filePath } = await createTestFile(exifData);
assetMock.getByIds.mockResolvedValue([
{ id: 'asset-1', originalPath: filePath, fileCreatedAt, fileModifiedAt } as AssetEntity,
]);
const { filePath } = await createTestFile(exifData);
assetMock.getByIds.mockResolvedValue([{ id: 'asset-1', originalPath: filePath } as AssetEntity]);

await sut.handleMetadataExtraction({ id: 'asset-1' });
await sut.handleMetadataExtraction({ id: 'asset-1' });

expect(assetMock.upsertExif).toHaveBeenCalledWith(
expect.objectContaining({
dateTimeOriginal: new Date(expected.dateTimeOriginal),
timeZone: expected.timeZone,
}),
);
expect(assetMock.upsertExif).toHaveBeenCalledWith(
expect.objectContaining({
dateTimeOriginal: new Date(expected.dateTimeOriginal),
timeZone: expected.timeZone,
}),
);

expect(assetMock.update).toHaveBeenCalledWith(
expect.objectContaining({
localDateTime: new Date(expected.localDateTime),
}),
);
},
);
expect(assetMock.update).toHaveBeenCalledWith(
expect.objectContaining({
localDateTime: new Date(expected.localDateTime),
}),
);
});
});
});

0 comments on commit 9217757

Please sign in to comment.