Skip to content

Commit

Permalink
feat: Set DateTimeOriginal using DateTimeDigitized only when the firs…
Browse files Browse the repository at this point in the history
…t one is empty and no other date is found.
  • Loading branch information
javierbrea committed Feb 15, 2022
1 parent a27a1ac commit cd82410
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 14 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- feat: Add `--no-modifyTime` option, allowing to modify date but keeping original time information.

### Changed
- feat: Set `DateTimeOriginal` using `DateTimeDigitized` only when the first one is empty and no other date is found.

### Fixed
- fix: Fix report when dryRun option is enabled
- chore: Add execution permissions to husky precommit file
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ exif-assistant set-dates ./photos --dateFormat dd-MM --dateFormat yyyy --dateReg
The default priority for determining the date to be set into a file is the next one, but it can be modified using the command options:

* Date from the `date` option, if defined.
* Date in the `DateTimeDigitized` exif info.
* Date found in the file name.
* Date found in the parent folder. Searches recursively in parent folders until the input folder.
* Date from the `dateFallback` option.
* Date from the `DateTimeDigitized` exif info, only in case `DateTimeOriginal` is empty.

Dates found could be partial depending on the provided `dateFormat` option (for example, a file name could contain info only about a day or a month). If such is the case, then it uses the next priority to determine the date used to complete it:

Expand Down Expand Up @@ -78,7 +78,7 @@ Dates found could be partial depending on the provided `dateFormat` option (for
| `-b, --baseDateFallback`| - | If the base date for a file is not found anywhere else, use this one as base date. Note that the base date for a file is calculated using its parent folder names. Must have [ISO 8601 format](https://en.wikipedia.org/wiki/ISO_8601), or match with any of the formats provided in the `dateFormat` option | `--baseDateFallback 2022-05` |
| `-f, --dateFormat` | [ISO 8601 format](https://en.wikipedia.org/wiki/ISO_8601) | Formats used to parse dates from file or folder names or date options. [Multiple values can be provided](https://github.com/tj/commander.js#variadic-option). The dates will be parsed using the first matching format. Check the [`date-fns` docs](https://github.com/date-fns/date-fns) to learn more about defining date formats | `--dateFormat dd-MM-yyyy yyyy` |
| `-r, --dateRegex` | - | Regex used to extract dates from file or folder names. Regexs with a capturing group must be provided. [Multiple values can be provided](https://github.com/tj/commander.js#variadic-option) | `--dateRegex "^year-(\S*)$"` |
| `--no-fromDigitized` | `false` | Do not set `DateTimeOriginal` property using the value from the `DateTimeDigitized` property. By default, if the program found the `DateTimeDigitized` property, it uses it to set `DateTimeOriginal`. This option disables that feature. Implicit when `--date` option is used | `--no-fromDigitized` |
| `--no-fromDigitized` | `false` | Do not set `DateTimeOriginal` property using the value from the `DateTimeDigitized` property. By default, if the program found the `DateTimeDigitized` property and `DateTimeOriginal` is empty, it fills it with the same value. This option disables that feature. Implicit when `--date` option is used | `--no-fromDigitized` |
| `--no-fromFileName` | `false` | Do not set dates based on dates found in file names. Implicit when `--date` option is used | `--no-fromFileName` |
| `--no-fromFolderNames` | `false` | Do not set dates based on dates found in folder names. Implicit when `--date` option is used | `--no-fromFolderNames` |
| `--no-baseDatefromFolderNames` | `false` | Do not set base dates based on dates found in parent folder names. The program tries to complete partial dates for a file or folder using its parent folder names. This option disables that feature. Implicit when `--baseDate` option is used | `--no-baseDatefromFolderNames` |
Expand Down
22 changes: 13 additions & 9 deletions src/assistant/setDateToFile.js
Original file line number Diff line number Diff line change
Expand Up @@ -336,15 +336,6 @@ async function setDateToFile(
return setDates(formatForExif(date), "date option", fileDates);
}

// Copy DateTimeDigitized to DateTimeOriginal if present
if (fromDigitized && fileDates[HUMAN_DATE_TIME_DIGITIZED_PROPERTY]) {
return setDates(
fileDates[HUMAN_DATE_TIME_DIGITIZED_PROPERTY],
HUMAN_DATE_TIME_DIGITIZED_PROPERTY,
fileDates
);
}

// Set date from file name
const fileNameWithoutExtension = removeExtension(fileName);
if (fromFileName && isDate(fileNameWithoutExtension)) {
Expand All @@ -366,6 +357,19 @@ async function setDateToFile(
);
}

// Copy DateTimeDigitized to DateTimeOriginal if it is empty
if (
fromDigitized &&
fileDates[HUMAN_DATE_TIME_DIGITIZED_PROPERTY] &&
!fileDates[HUMAN_DATE_TIME_ORIGINAL_PROPERTY]
) {
return setDates(
fileDates[HUMAN_DATE_TIME_DIGITIZED_PROPERTY],
HUMAN_DATE_TIME_DIGITIZED_PROPERTY,
{}
);
}

tracer.debug(`${fileName}: No date was found to set`);
await handleUnresolved();
}
Expand Down
100 changes: 100 additions & 0 deletions test/unit/assistant/setDate.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,22 @@ describe("setDate", () => {

describe("when file has only DateTimeDigitized", () => {
describe("when no fromDigitized option is provided", () => {
it("should not add DateTimeOriginal from DateTimeDigitized if date is found in file", async () => {
const fileName = "sphinx-no-date-original.jpg";
const newFileName = "2022-02-15.jpg";
await copyAssetToTempPath(fileName, newFileName);
const result = await expectModifiedDate({
inputPath: TEMP_PATH,
fileName: newFileName,
setDateOptions: {},
newDateExpected: "2022:02:15 00:00:00",
expectedLog: "from file name",
});
expect(result.totals.before.withDate).toEqual(0);
expect(result.totals.after.withDate).toEqual(1);
expect(result.totals.after.modified).toEqual(1);
});

it("should add DateTimeOriginal from DateTimeDigitized and return report", async () => {
const fileName = "sphinx-no-date-original.jpg";
const { metadata } = assetData(fileName);
Expand Down Expand Up @@ -413,6 +429,22 @@ describe("setDate", () => {
});
});

describe("when file has both DateTimeDigitized and DateTimeOriginal", () => {
it("should not add DateTimeOriginal from DateTimeDigitized", async () => {
const spy = spyTracer("debug");
const fileName = "caryatids.jpeg";
await copyAssetToTempPath(fileName);
const fileOrigin = tempPath(fileName);
const result = await setDate(fileOrigin, {
modify: true,
});
expectLog(`No date was found to set`, spy);
expect(result.totals.before.withDate).toEqual(1);
expect(result.totals.after.withDate).toEqual(1);
expect(result.totals.after.modified).toEqual(0);
});
});

describe("when date is not found", () => {
describe("when moveToIfUnresolved option is provided", () => {
it("should copy the file to a subfolder if outputFolder is not the same in which the file is", async () => {
Expand Down Expand Up @@ -679,6 +711,74 @@ describe("setDate", () => {
});
});

describe("when modifyTime option is not provided", () => {
it("should add date to exif, setting time to first day second if file name has not time info", async () => {
const fileName = "caryatids.jpeg";
const newFileName = "2012-02-15.jpg";
const date = "2012:02:15 00:00:00";
await copyAssetToTempPath(fileName, newFileName);

const result = await expectModifiedDate({
inputPath: TEMP_PATH,
fileName: newFileName,
newDateExpected: date,
dateTimeDigitedExpected: date,
setDateOptions: {
modify: true,
},
expectedLog: "from file name",
});
expect(result.totals.before.withDate).toEqual(1);
expect(result.totals.after.withDate).toEqual(1);
expect(result.totals.after.modified).toEqual(1);
});

it("should add date to exif, setting time from file name info", async () => {
const fileName = "caryatids.jpeg";
const newFileName = "2012-02-15T15:23:54.jpg";
const date = "2012:02:15 15:23:54";
await copyAssetToTempPath(fileName, newFileName);

const result = await expectModifiedDate({
inputPath: TEMP_PATH,
fileName: newFileName,
newDateExpected: date,
dateTimeDigitedExpected: date,
setDateOptions: {
modify: true,
},
expectedLog: "from file name",
});
expect(result.totals.before.withDate).toEqual(1);
expect(result.totals.after.withDate).toEqual(1);
expect(result.totals.after.modified).toEqual(1);
});
});

describe("when modifyTime option is false", () => {
it("should add date to exif, but keeping old time", async () => {
const fileName = "caryatids.jpeg";
const newFileName = "2012-02-15.jpg";
const date = "2012:02:15 10:24:14";
await copyAssetToTempPath(fileName, newFileName);

const result = await expectModifiedDate({
inputPath: TEMP_PATH,
fileName: newFileName,
newDateExpected: date,
dateTimeDigitedExpected: date,
setDateOptions: {
modify: true,
modifyTime: false,
},
expectedLog: "from file name",
});
expect(result.totals.before.withDate).toEqual(1);
expect(result.totals.after.withDate).toEqual(1);
expect(result.totals.after.modified).toEqual(1);
});
});

describe("When dryRun option is provided", () => {
it("should only report modifications withour modifying original file", async () => {
const spy = spyTracer("debug");
Expand Down
6 changes: 3 additions & 3 deletions test/unit/assistant/setDates.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -361,12 +361,12 @@ describe("setDates", () => {
expect(DateTimeDigitized).toEqual(`2022:02:02 00:00:00`);
});

it("should have not modified date of image with DateTimeDigited", async () => {
it("should have modified date of image with DateTimeDigitized", async () => {
const { DateTimeOriginal, DateTimeDigitized } = await readExifDates(
tempPath(NEW_IMAGE_NO_DATE_ORIGINAL)
);
expect(DateTimeOriginal).toEqual("2021:10:14 10:58:31");
expect(DateTimeDigitized).toEqual("2021:10:14 10:58:31");
expect(DateTimeOriginal).toEqual("2022:02:01 18:39:45");
expect(DateTimeDigitized).toEqual("2022:02:01 18:39:45");
});

it("should have not modified date of image with date", async () => {
Expand Down

0 comments on commit cd82410

Please sign in to comment.