diff --git a/src/backend/model/fileaccess/MetadataLoader.ts b/src/backend/model/fileaccess/MetadataLoader.ts index a858282b..02a0d949 100644 --- a/src/backend/model/fileaccess/MetadataLoader.ts +++ b/src/backend/model/fileaccess/MetadataLoader.ts @@ -362,34 +362,27 @@ export class MetadataLoader { //Filesystem is the absolute last resort, and it's hard to write tests for, since file system dates are changed on e.g. git clone. if (exif.exif.DateTimeOriginal) { //DateTimeOriginal is when the camera shutter closed - if (exif.exif.OffsetTimeOriginal) { //OffsetTimeOriginal is the corresponding offset - metadata.creationDate = timestampToMS(exif.exif.DateTimeOriginal, exif.exif.OffsetTimeOriginal); - metadata.creationDateOffset = exif.exif.OffsetTimeOriginal; - } else { - const alt_offset = exif.exif.OffsetTimeDigitized || exif.exif.OffsetTime || getTimeOffsetByGPSStamp(exif.exif.DateTimeOriginal, exif.exif.GPSTimeStamp, exif.gps); - metadata.creationDate = timestampToMS(exif.exif.DateTimeOriginal, alt_offset); - metadata.creationDateOffset = alt_offset; + let offset = exif.exif.OffsetTimeOriginal; //OffsetTimeOriginal is the corresponding offset + if (!offset) { //Find offset among other options if possible + offset = exif.exif.OffsetTimeDigitized || exif.exif.OffsetTime || getTimeOffsetByGPSStamp(exif.exif.DateTimeOriginal, exif.exif.GPSTimeStamp, exif.gps); } + metadata.creationDate = timestampToMS(exif.exif.DateTimeOriginal, offset); + metadata.creationDateOffset = offset; } else if (exif.exif.CreateDate) { //using else if here, because DateTimeOriginal has preceedence //Create is when the camera wrote the file (typically within the same ms as shutter close) - if (exif.exif.OffsetTimeDigitized) { //OffsetTimeDigitized is the corresponding offset - metadata.creationDate = timestampToMS(exif.exif.CreateDate, exif.exif.OffsetTimeDigitized); - metadata.creationDateOffset = exif.exif.OffsetTimeDigitized; - } else { - const alt_offset = exif.exif.OffsetTimeOriginal || exif.exif.OffsetTime || getTimeOffsetByGPSStamp(exif.exif.DateTimeOriginal, exif.exif.GPSTimeStamp, exif.gps); - metadata.creationDate = timestampToMS(exif.exif.DateTimeOriginal, alt_offset); - metadata.creationDateOffset = alt_offset; + let offset = exif.exif.OffsetTimeDigitized; //OffsetTimeDigitized is the corresponding offset + if (!offset) { //Find offset among other options if possible + offset = exif.exif.OffsetTimeOriginal || exif.exif.OffsetTime || getTimeOffsetByGPSStamp(exif.exif.DateTimeOriginal, exif.exif.GPSTimeStamp, exif.gps); } + metadata.creationDate = timestampToMS(exif.exif.CreateDate, offset); + metadata.creationDateOffset = offset; } else if (exif.ifd0?.ModifyDate) { //using else if here, because DateTimeOriginal and CreatDate have preceedence - if (exif.exif.OffsetTime) { - //exif.Offsettime is the offset corresponding to ifd0.ModifyDate - metadata.creationDate = timestampToMS(exif.ifd0.ModifyDate, exif.exif?.OffsetTime); - metadata.creationDateOffset = exif.exif?.OffsetTime - } else { - const alt_offset = exif.exif.DateTimeOriginal || exif.exif.OffsetTimeDigitized || getTimeOffsetByGPSStamp(exif.ifd0.ModifyDate, exif.exif.GPSTimeStamp, exif.gps); - metadata.creationDate = timestampToMS(exif.ifd0.ModifyDate, alt_offset); - metadata.creationDateOffset = alt_offset; - } + let offset = exif.exif.OffsetTime; //exif.Offsettime is the offset corresponding to ifd0.ModifyDate + if (!offset) { //Find offset among other options if possible + offset = exif.exif.DateTimeOriginal || exif.exif.OffsetTimeDigitized || getTimeOffsetByGPSStamp(exif.ifd0.ModifyDate, exif.exif.GPSTimeStamp, exif.gps); + } + metadata.creationDate = timestampToMS(exif.ifd0.ModifyDate, offset); + metadata.creationDateOffset = offset } else if (exif.ihdr && exif.ihdr["Creation Time"]) {// again else if (another fallback date if the good ones aren't there) { const any_offset = exif.exif.DateTimeOriginal || exif.exif.OffsetTimeDigitized || exif.exif.OffsetTime || getTimeOffsetByGPSStamp(exif.ifd0.ModifyDate, exif.exif.GPSTimeStamp, exif.gps); metadata.creationDate = timestampToMS(exif.ihdr["Creation Time"], any_offset); diff --git a/test/backend/assets/wild-1-small.jpg b/test/backend/assets/wild-1-small.jpg new file mode 100644 index 00000000..20102203 Binary files /dev/null and b/test/backend/assets/wild-1-small.jpg differ diff --git a/test/backend/assets/wild-1-small.json b/test/backend/assets/wild-1-small.json new file mode 100644 index 00000000..1c686195 --- /dev/null +++ b/test/backend/assets/wild-1-small.json @@ -0,0 +1,20 @@ +{ + "size": { + "width": 306, + "height": 204 + }, + "creationDate": 1435910683000, + "fileSize": 59564, + "positionData": { + "country": "United States", + "state": "Arizona", + "city": "Williams" + }, + "keywords": ["Akela the wolf", "Balu the bear", "Bearizona", "Hugin the raven", "USA", "USA Road trip"], + "cameraData": { + "make": "Canon", + "model": "Canon EOS 600D", + "lens": "EF-S15-85mm f/3.5-5.6 IS USM" + }, + "creationDateOffset": "+02:00" +} \ No newline at end of file diff --git a/test/backend/unit/model/threading/MetaDataLoader.spec.ts b/test/backend/unit/model/threading/MetaDataLoader.spec.ts index 5a0e7e49..30542f2b 100644 --- a/test/backend/unit/model/threading/MetaDataLoader.spec.ts +++ b/test/backend/unit/model/threading/MetaDataLoader.spec.ts @@ -112,6 +112,11 @@ describe('MetadataLoader', () => { expect(Utils.clone(data)).to.be.deep.equal(expected); }); }); + it('should load wild-1-small image with CreateDate from 2015, but no DateTimeOriginal', async () => { + const data = await MetadataLoader.loadPhotoMetadata(path.join(__dirname, '/../../../assets/wild-1-small.jpg')); + const expected = require(path.join(__dirname, '/../../../assets/wild-1-small.json')); + expect(Utils.clone(data)).to.be.deep.equal(expected); + }); describe('should load jpg with edge case exif data', () => { const root = path.join(__dirname, '/../../../assets/edge_case_exif_data');