I'm trying to understand this magic tool and I come across this code which if I'm right it selects the first date on the list and places that date into the mydate variable.
%Image::ExifTool::UserDefined = (
'Image::ExifTool::Composite' => {
MyDate => {
Desire => {
0 => 'DateTimeOriginal',
1 => 'CreateDate',
2 => 'ModifyDate',
3 => 'FileModifyDate',
},
ValueConv => '$val[0] || $val[1] || $val[2] || $val[3]',
PrintConv => '$self->ConvertDateTime($val)',
},
},
);
Now suppose what I really want is not just the first date it finds, but the earliest date it finds. How can I change this code to do that and also add any other possible dates, like ProfileDateTime? I have actually found some JPEG files that have only this profile date. What I really want is to extract the earliest date anywhere in the metadata and push that to the Create Date and the Modify Date unless the modify date is later than the pushed Create Date.
My reasoning is that given all the various dates available in photo file metadata if the Create Date is later than any other date, it must be wrong. Seems to me that the photo cannot be created after it is modified or profiled or anything else. As I have acquired tons of photos from a large number of family members and they have been copied over and over, there are a great many photos whose dates are garbage. So setting create to the earliest is the best I can do.
Try this to replace the ValueConv line in the config file you posted:
ValueConv => q{
my $earliest;
foreach (@val) {
next unless defined $_;
defined $earliest or $earliest = $_, next;
$earliest = $_ if $earliest lt $_;
}
return $earliest;
},
- Phil
How about this one:
ValueConv => q{
my ($earliest) = (sort {$a cmp $b} grep $_, @val)[0];
return $earliest;
},
I was looking for solutions on StackOverflow for the problem yesterday, but didn't get around to posting. Read your answer and realized the need to check for undefined.
Thanx to both of you. Indeed you are helping me learn exiftool. And indeed there is a bunch to learn.
Just as an aside, and to continue my education, the following commands are what I have been using in order to get the datetimeoriginal set to the earliest date:
exiftool -r '-datetimeoriginal<createdate' -P -if '($createdate le $modifydate) and ($createdate le $datetimeoriginal)' -overwrite_original_in_place .
exiftool -r '-datetimeoriginal<modifydate' -P -if '($modifydate le $datetimeoriginal) and ($modifydate le $createdate)' -overwrite_original_in_place .
exiftool -r '-alldates<filemodifydate' -P -if 'not $datetimeoriginal' -overwrite_original_in_place .
While this seems to work well, is there a way to concatenate these three commands into one command other than the config?
Quote from: Paxapunch on December 01, 2018, 02:33:05 PM
While this seems to work well, is there a way to concatenate these three commands into one command other than the config?
Is it possible, yes. But it is, IMO, messy. See this post (https://exiftool.org/forum/index.php/topic,6559.msg32749.html#msg32749). That command is only checking for the earliest of two dates. Expanding it to four or more would be very complex and lengthy.
Myself, I'm a big fan of doing things in-line rather than adding to the config file, but this is a situation in which I would add to the config file just to make it easier to use.
Thanx StarGeek... I guess I will just keep it simple.
Quote from: StarGeek on December 01, 2018, 01:35:46 PM
How about this one:
ValueConv => q{
my ($earliest) = (sort {$a cmp $b} grep $_, @val)[0];
return $earliest;
},
Sweet!
It came from a post where the question was about finding the min and max values an array. Something like my ($min, $max) = (sort {$a cmp $b} , @val)[0,-1];. I really like perl one line codes like this.
Is there a way to also include miliseconds/fractional seconds if a date has them? Above works great unless there are multiple photos made in one second - then we get %-c but the order is not ensured.
Which of the above are you referring to? The config file or the commands that Paxapunch listed?
Assuming that you know for certain that all the files contain subsecond data, then replace the timestamp tags with the equivalent composite subsecond tags (https://exiftool.org/TagNames/Composite.html) e.g. SubSecCreateDate/SubSecDateTimeOriginal/SubSecModifyDate.
If you have mixed files, some that have subsecond values and some that are completely missing, that would be more complex.
Hi,
Is it possible to mix this metadata-dates-from-file with date in file name, when available (ex: VID-20191220-WA0011.mp4) , in order to get the oldest date possible?
Yes, if you had a well defined file name pattern. But with your example, you would also have to add a time component. Additionally, when dealing with a video, you have to figure out the time zone as video time stamps are in UTC. So you can't just add 00:00:00, as that would get adjusted to the previous day if you have a time zone west of UTC. See the 4th paragraph on the Quicktime tags page (https://exiftool.org/TagNames/QuickTime.html).