Calcing time difference between exif and filenames as a value

Started by stackfl0w, March 09, 2020, 09:17:41 PM

Previous topic - Next topic

stackfl0w

This is a great tool, pretty much lost half the time but I'm starting to pick it up I think lol. So I came across this code snippet that's very close to what I'm looking for. I want to iterate thru a directory and output any photos that have filename date discrepancies into a csv, along with another value showing the time difference.

I want to be able to grab a substring of just the date & time from the filename and then use DateTimeOriginal to calc the difference and be able to store or return it as a value. Could this config code be easily modified to suit that?

Quote from: vlad.waldhaus on August 30, 2012, 05:37:32 AM
I think I found  the solution

abs(Image::ExifTool::GetUnixTime($val[0])-Image::ExifTool::GetUnixTime($val[1]))


return different in seconds


the final solution:

%Image::ExifTool::UserDefined = (
    'Image::ExifTool::Composite' => {
        GPSDateTimeOriginalSpan => {
            Require => {
                0 => 'GPSDateTime',
                1 => 'DateTimeOriginal',
            },
            ValueConv => q{
                return abs(Image::ExifTool::GetUnixTime($val[0])-Image::ExifTool::GetUnixTime($val[1]));
            },
            PrintConv => 'Image::ExifTool::ConvertTimeSpan($val)',
        },
    },
);


I tried testing it as-is in a my.config file and using -config in-line at the prompt, but it either does nothing or returns an error about being undefined :/ Configs and scripting are a little over my head at this point.

StarGeek

Part of the problem is that the Filename is not a date/time tag, so it can't just be plugged into the equation without modification.  See FAQ #5 for details on how date/time tags are formatted.  Obviously, you can't rename the files in that format because you can't include a colon in the filename.

If you knew exactly the format the date/time is formatted in the file, it included all parts (Year, Month, Day, Hours, Minutes, Seconds), it would be possible to parse that and reformat it as a time stamp which could then be used to compare the two.
* Did you read FAQ #3 and use the command listed there?
* Please use the Code button for exiftool code/output.
 
* Please include your OS, Exiftool version, and type of file you're processing (MP4, JPG, etc).

stackfl0w

Thanks, yea all filenames are in a img_YYYYmmdd_HHmmss.xxx format, so I know what the format will be. I just need a way to store both timestamps in a way I can compare them and return an age difference. My plan was to use the difference as a condition to decide whether to rename the photo according to datetimeoriginal or to leave it named as is.

I came across this thread about needing the age compared to a given date. Phil attached and updated a similar config file in there, I'm going to delve through that and see what I can learn...

edit: is it possible to to assign a userParam with a date value? Something like userParam<TagName?

StarGeek

Given that exact format and based upon that config file, you could try this as the config file

%Image::ExifTool::UserDefined = (
    'Image::ExifTool::Composite' => {
        FileNameDateTimeOriginalSpan => {
            Require => {
                0 => 'FileName',
                1 => 'DateTimeOriginal',
            },
            ValueConv => q{
                my $filename=~s/(\d{4})(\d\d)(\d\d)_(\d\d)(\d\d)(\d\d)/$1:$2:$3 $4:$5:$6/;
                return abs(Image::ExifTool::GetUnixTime($filename)-Image::ExifTool::GetUnixTime($val[1]));
            },
            PrintConv => 'Image::ExifTool::ConvertTimeSpan($val)',
        },
    },
);
* Did you read FAQ #3 and use the command listed there?
* Please use the Code button for exiftool code/output.
 
* Please include your OS, Exiftool version, and type of file you're processing (MP4, JPG, etc).

stackfl0w

Hey thanks, this was a great start for me :) I had to change it a little, for whatever reason trying to group more than 3 patterns seems to break the expression in exiftool. So $filename wasn't getting populated on my end, and thus it'd give a bad result. Also I guess with exiftool the parser isn't as flexible with $_ so I had to specify that val[] was the target. I guess normally the default variable would carry over or something? Anyway after an afternoon on stackoverflow this is the code I put together. I ended up nesting the pattern-matching cuz it was more fun to learn than settling for multiple steps lol


%Image::ExifTool::UserDefined = (
    'Image::ExifTool::Composite' => {
        FileNameDateTimeOriginalSpan => {
            Require => {
                0 => 'FileName',
                1 => 'DateTimeOriginal',                     
            },
            ValueConv => q{
           
                my $filename = $val[0] =~ s/(_)|\D+/$1 ? ' ' : ''/egr;    #Assign filename str, trim alphas & underscore in 2 passes
                                                                                                 

                substr($filename,$_,0) = ':' for (13,11,6,4);                  #Insert colons for date format
                           
                return abs(Image::ExifTool::GetUnixTime($filename)-Image::ExifTool::GetUnixTime($val[1])); 
            },
            PrintConv => 'Image::ExifTool::ConvertTimeSpan($val)',    #spooky action so humans can read it
        },
    },
);

Phil Harvey

Quote from: stackfl0w on March 12, 2020, 08:45:36 PM
trying to group more than 3 patterns seems to break the expression in exiftool.

There must have been something wrong with one of the expressions.  We could tell if you showed it to us.

QuoteAlso I guess with exiftool the parser isn't as flexible with $_ so I had to specify that val[] was the target.

Not sure what you mean here.  ExifTool uses only one parser for expressions (Perl).  But ValueConv expressions work on different variables than advanced formatting expressions (because they access multiple tags, while formatting expressions work only on one), if that's what you mean.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

stackfl0w

I replied earlier but it accidentally posted in the middle of a draft. It turns out I was being dumb haha. The error was small and easily fixed but I didn't know any better >_>

Soo you're right it was just an expression error. The original code only needed to go from this:
my $filename =~ s/(\d{4})(\d\d)(\d\d)_(\d\d)(\d\d)(\d\d)/$1:$2:$3 $4:$5:$6/;

to this:
my $filename = $val[0] =~ s/\D+(\d{4})(\d\d)(\d\d)_(\d\d)(\d\d)(\d\d)\D+/$1:$2:$3 $4:$5:$6/r;

I guess? I thought it was breaking after 3 groupings because I didn't properly understand how grouping worked. It broke after 3 because that's when it reached the underscore I was omitting from the pattern, assuming it'd scan past it like $1 did.

But that's ok. 😅 I learned a lot bc of this lol. Thanks anyway tho, it really helped.

StarGeek

Ooops, sorry.  I was testing out both substitution and matching and got the code mixed up.

I think my original substitution was something like this
my $filename=~s/.*(\d{4})(\d\d)(\d\d)_(\d\d)(\d\d)(\d\d).*/$1:$2:$3 $4:$5:$6/
with the .* removing any extra characters from the string.  This fit better to inline and reduce code.

The other way I was trying was to avoid the creation of a tag and just inline it on the command line with something like
${Filename;m/(\d{4})(\d\d)(\d\d)_(\d\d)(\d\d)(\d\d)/;$_=\"$1:$2:$3 $4:$5:$6\"}
That needed too much extra work and I messed up when creating the config.
* Did you read FAQ #3 and use the command listed there?
* Please use the Code button for exiftool code/output.
 
* Please include your OS, Exiftool version, and type of file you're processing (MP4, JPG, etc).