From 3531f1e5330a9be9df63422d324353290958570e Mon Sep 17 00:00:00 2001 From: Romain Date: Fri, 31 Mar 2017 23:20:02 +1100 Subject: [PATCH] Try to infer dates from the filename if there is no "date" metadata --- src/model/media.js | 15 +++++++++++++-- test/model/media.spec.js | 30 +++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/model/media.js b/src/model/media.js index 0e29daf..f7e3fdd 100644 --- a/src/model/media.js +++ b/src/model/media.js @@ -3,6 +3,13 @@ const moment = require('moment') const path = require('path') const EXIF_DATE_FORMAT = 'YYYY:MM:DD HH:mm:ssZ' + +// infer dates from files with a date-looking filename +const FILENAME_DATE_REGEX = /\d{4}[_\-.\s]?(\d{2}[_\-.\s]?){5}\..{3,4}/ + +// moment ignores non-numeric characters when parsing +const FILENAME_DATE_FORMAT = 'YYYYMMDD HHmmss' + var index = 0 /* @@ -13,7 +20,7 @@ function Media (file) { this.file = file this.filename = path.basename(file.path) this.urls = _.mapValues(file.output, o => o.path) - this.date = exifDate(file) + this.date = getDate(file) this.caption = caption(file) this.isVideo = (file.type === 'video') this.isAnimated = animated(file) @@ -26,13 +33,17 @@ function Media (file) { // ] } -function exifDate (file) { +function getDate (file) { const date = tagValue(file, 'EXIF', 'DateTimeOriginal') || tagValue(file, 'H264', 'DateTimeOriginal') || tagValue(file, 'QuickTime', 'CreationDate') if (date) { return moment(date, EXIF_DATE_FORMAT).valueOf() } else { + if (FILENAME_DATE_REGEX.test(file.path)) { + const namedate = moment(file.path, FILENAME_DATE_FORMAT) + if (namedate.isValid()) return namedate.valueOf() + } return file.date } } diff --git a/test/model/media.spec.js b/test/model/media.spec.js index 9dd08e5..1ac852d 100644 --- a/test/model/media.spec.js +++ b/test/model/media.spec.js @@ -27,7 +27,35 @@ describe('Media', function () { should(media.date).eql(fixtures.date('2016-10-28 17:34:58').getTime()) }) - it('defaults to the file date if there is no date in the metadata', function () { + it('infers the date from the filename (Android format)', function () { + const file = fixtures.file({path: 'folder/VID_20170220_114006.mp4'}) + const media = new Media(file) + should(media.date).eql(fixtures.date('2017-02-20 11:40:06').getTime()) + }) + + it('infers the date from the filename (Dropbox format)', function () { + const file = fixtures.file({path: 'folder/2017-03-24 19.42.30.jpg'}) + const media = new Media(file) + should(media.date).eql(fixtures.date('2017-03-24 19:42:30').getTime()) + }) + + it('only infers dates from valid formats', function () { + const file = fixtures.file({ + path: 'folder/IMG_1234.jpg', + date: '2016-10-28 17:34:58' + }) + const media = new Media(file) + should(media.date).eql(fixtures.date('2016-10-28 17:34:58').getTime()) + }) + + it('does not look at the file name if it already has EXIF data', function () { + const file = fixtures.file({path: '2017-03-24 19.42.30.jpg'}) + file.meta.EXIF.DateTimeOriginal = '2016:10:28 17:34:58' + const media = new Media(file) + should(media.date).eql(fixtures.date('2016-10-28 17:34:58').getTime()) + }) + + it('defaults to the file date if there is no other date', function () { const file = fixtures.file({date: '2016-10-28 17:34:58'}) const media = new Media(file) should(media.date).eql(fixtures.date('2016-10-28 17:34:58').getTime())