Calculate time difference

Started by Amihai, March 06, 2011, 02:19:01 PM

Previous topic - Next topic

Amihai

Can anybody help with base script?

How to:
calculate date/time difference
round results to years/monthes/day/hours/minutes
format result strings

Phil Harvey

If you want me to write the script for you, you will have to be much more specific about the input tags and their formats, and the desired output format.  This is fairly easy if the input dates are standard EXIF format, depending on the specifics of how you want the output formatted.

- 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 ($).

Amihai

CHILD AGE CALCULATION
exif.date_time_original = 19-02-2011 23:44:21 //input tag
birth_day = 12-11-2010 //stored in the script
name = "John" //stored in the script

datediff formats::
A. age:
1. monthes-days (age < 1year) : "Xm Xd" // examples: "3m 7d"/"1m 5d"/"11m 0d"
2. years-monthes (age > 1year) : "Xy Xm // examples "1y 0m"/"2y 3m"/"3y 11m"
3. years (age > 5years) : "Xy" //examples

if keywords contain [name] then iptc.model_age = datediff

B. trip:
exif.date_time_original = 19-02-2011 23:44:21 //input tag
iptc.headline = "Fishing 2011/Feb" //input tag
iptc.caption = "Pike catched." //input tag
trip_start = 18-02-2011 //stored in the script or passed as arg
trip_length = 4 //stored in the script or passed as arg

datediff format
"day X/Y" //"day 1/4", "day 3/4"
if (iptc.caption!=NULL) then iptc.caption = iptc.caption + " (" + iptc.headline + ", " + datediff + ")" //Pike catched. (Fishing 2011/Feb, day 2/4)

Phil Harvey

The config file below will give you 2 tags (MyAges and MyTrip) that you can copy to other tags as you wish with a command like this:

exiftool "-comment<myages" "-caption-abstract<mytrip" ...

Notes:

1) See the sample config file for details about how to install the config file.

2) I haven't written MyAges to ModelAge as you specified because ModelAge is a simple integer and you want a different format.

3) I have used IPTC tags here, but you may actually want to use the XMP equivalents.

4) The MyAges tag will only be generated if names corresponding to the definitions in the %people lookup are found in the IPTC:Keywords.  Ages for all matching people are returned, in alphabetical order by name.

5) The config file would have been MUCH more complicated if I didn't assume a fixed number of days per month (30) and per year (365).  Of course, this is not accurate, but it is too much work to do this properly.

6) Have fun. :)

- Phil

my %people = (
    'John' => '2010:11:12 00:00:00',
    'Bob'  => '2009:02:03 00:00:00',
);

my $trip_start = "2011:03:04 00:00:00";
my $trip_length = 4;

%Image::ExifTool::UserDefined = (
    'Image::ExifTool::Composite' => {
        MyAges => {
            Require => {
                0 => 'EXIF:DateTimeOriginal',
                1 => 'IPTC:Keywords',
            },
            ValueConv => sub {
                my $val = shift;
                my $kw = $$val[1];
                $kw = "@$kw" if ref $kw eq 'ARRAY';
                my ($name, @ages);
                foreach $name (sort keys %people) {
                    next unless $kw =~ /$name/;
                    require Time::Local;
                    my $t = TimeLocal(reverse split /[ :]/, $$val[0]);
                    my $b = TimeLocal(reverse split /[ :]/, $people{$name});
                    my $d = ($t - $b) / (24 * 60 * 60);
                    if ($d < 365) {
                        my $mon = int($d / 30);
                        my $day = int($d - 30 * $mon);
                        push @ages, $mon ? "${mon}m ${day}d" : "${day}d";
                    } elsif ($d < 5 * 365) {
                        my $yr = int($d / 365);
                        my $mon = int(($d - 365 * $yr) / 30);
                        push @ages, "${yr}y ${mon}m";
                    } else {
                        push @ages, int($d/365) . 'y';
                    }
                }
                return @ages ? \@ages : undef;
            },
        },
        MyTrip => {
            Require => {
                0 => 'EXIF:DateTimeOriginal',
                1 => 'IPTC:Caption-Abstract',
                2 => 'IPTC:Headline',
            },
            ValueConv => sub {
                my $val = shift;
                require Time::Local;
                my $t = TimeLocal(reverse split /[ :]/, $$val[0]);
                my $b = TimeLocal(reverse split /[ :]/, $trip_start);
                my $d = int(($t - $b) / (24 * 60 * 60)) + 1;
                return "$$val[1] ($$val[2], day $d/$trip_length)";
            },
        },
    },
);
1;  #end
...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 ($).

jusefe

Hello Phil,

I'm very sorry that I bring this topic out of the grave, but I have situation which I want to explore using your 'MyAges' script solution but without having to depend on IPTC keywords as mentioned on step 4).

The reason behind is because I would like evoke the MyAges tagging based on the OS Mavericks tag system. From what I know, we are not able to use/read Mavericks tags in exiftool as they are managed in different way (please correct me if I am wrong!).

So I want to modify the script to force the age of whoever has been added under "my %people", without depending on IPTC keywords. Then I will evoke this config file using an automator app such as Hazel, which works with Mavericks tags and you can create conditions to run the scripts based on specific tag criteria

I have been tampering the script with the goal of getting this behaviour but without success, I am a script noob :-S

Juan

Phil Harvey

Hi Juan,

Here is an example of how this could be done for a single person ("Bob"):

my %people = (
    'John' => '2010:11:12 00:00:00',
    'Bob'  => '2009:02:03 00:00:00',
);

%Image::ExifTool::UserDefined = (
    'Image::ExifTool::Composite' => {
        MyAges => {
            Require => {
                0 => 'EXIF:DateTimeOriginal',
            },
            ValueConv => sub {
                my $val = shift;
                my ($name, @ages);
                foreach $name ('Bob') {
                    require Time::Local;
                    my $t = TimeLocal(reverse split /[ :]/, $$val[0]);
                    my $b = TimeLocal(reverse split /[ :]/, $people{$name});
                    my $d = ($t - $b) / (24 * 60 * 60);
                    if ($d < 365) {
                        my $mon = int($d / 30);
                        my $day = int($d - 30 * $mon);
                        push @ages, $mon ? "${mon}m ${day}d" : "${day}d";
                    } elsif ($d < 5 * 365) {
                        my $yr = int($d / 365);
                        my $mon = int(($d - 365 * $yr) / 30);
                        push @ages, "${yr}y ${mon}m";
                    } else {
                        push @ages, int($d/365) . 'y';
                    }
                }
                return @ages ? \@ages : undef;
            },
        },
    },
);
1;  #end


- 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 ($).

jusefe

Wow thanks for the quick help Phil!

I got a bit lost with the use of the scripts (and it's me ignorant..). How do you run such script like MyAges to run for a particular folder? I understand that MyAges tag needs to be created in advance before it can work right?

So what I have done is:
save a txt file with the new config and load it with the below:
  exiftool -config /Users/jusefe/Documents/ExifTool_config.txt

I get a confirmed load since I added a little notice within the text file. But from there, how do you apply it to a folder with multiple images within? I was thinking something like:
exiftool <MyAges command here> /Users/jusefe/Albums/Test1

Is that the right approach?

I found a watermark software which can dynamically print watermarks based on IPTC keywords and problably xmp too.

Thanks a lot for your help Phil!



Phil Harvey

The config file creates a user-defined "MyAges" tag.  You can do whatever you want with this tag.  For example:

exiftool "-comment<myages" DIR

where DIR is the name of a directory containing images.  This example will copy the MyAges value to the JPEG Comment for all images in directory DIR.

But before you write anything, you should be sure that MyAges is giving you what you want:

exiftool -myages DIR

to show the value of MyAges for all images in directory DIR.

- 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 ($).

jusefe

I see thanks Phil!

As I am running on Mac I guess  the command to paste 'myages' into 'comment' would be
exiftool '-comment<$MyAges' DIR

However the Myages.config doesn't seem to trigger correctly for some reason, my command is
exiftool -config /Users/jusefe/Documents/MyAges3.config


It loads and it doesn't show any errors. It shows the print text 'Loaded', plus it sends me to the "User Contributed Perl Documentation" of exiftool which I quit by using q, (not sure if that would affect the load)

After that I try to run a test and I get the below, myages tags doesn't show up:

localhost:~ jusefe$ exiftool -myages -datetimeoriginal -make /Users/jusefe/Dropbox/Album_test
======== /Users/jusefe/Dropbox/Album_test/20141030_103459.mp4
======== /Users/jusefe/Dropbox/Album_test/20141031_103431.jpg
Date/Time Original              : 2014:10:31 10:34:31
Make                            : SAMSUNG
======== /Users/jusefe/Dropbox/Album_test/20141031_103512.jpg
Date/Time Original              : 2014:10:31 10:35:11
Make                            : SAMSUNG
======== /Users/jusefe/Dropbox/Album_test/20141104_231513.jpg
Date/Time Original              : 2014:11:04 23:15:13
Make                            : SAMSUNG
======== /Users/jusefe/Dropbox/Album_test/20141104_231528.jpg
Date/Time Original              : 2014:11:04 23:15:28
Make                            : SAMSUNG
======== /Users/jusefe/Dropbox/Album_test/20141104_231533.jpg
Date/Time Original              : 2014:11:04 23:15:32
Make                            : SAMSUNG
======== /Users/jusefe/Dropbox/Album_test/20141104_231552.jpg
Date/Time Original              : 2014:11:04 23:15:52
Make                            : SAMSUNG
======== /Users/jusefe/Dropbox/Album_test/20141122_095947.mp4
======== /Users/jusefe/Dropbox/Album_test/20141122_100007.jpg
Date/Time Original              : 2014:11:22 10:00:06
Make                            : SAMSUNG
======== /Users/jusefe/Dropbox/Album_test/20141122_100010.jpg
Date/Time Original              : 2014:11:22 10:00:10
Make                            : SAMSUNG
======== /Users/jusefe/Dropbox/Album_test/20141122_100037.jpg
Date/Time Original              : 2014:11:22 10:00:37
Make                            : SAMSUNG
    1 directories scanned
   11 image files read




Not sure why the Myages config doesn't work. Does something have to be different in the config file if you are in Mac compared to windows?

the code in the config file 'MyAges3.config':
my %people = (
    'John'  => '2013:02:20 00:00:00',
);

%Image::ExifTool::UserDefined = (
    'Image::ExifTool::Composite' => {
        MyAges => {
            Require => {
                0 => 'DateTimeOriginal',
            },
            ValueConv => sub {
                my $val = shift;
                my ($name, @ages);
                foreach $name ('Seb') {
                    require Time::Local;
                    my $t = TimeLocal(reverse split /[ :]/, $$val[0]);
                    my $b = TimeLocal(reverse split /[ :]/, $people{$name});
                    my $d = ($t - $b) / (24 * 60 * 60);
                    if ($d < 365) {
                        my $mon = int($d / 30);
                        my $day = int($d - 30 * $mon);
                        push @ages, $mon ? '${mon}m ${day}d' : '${day}d';
                    } elsif ($d < 5 * 365) {
                        my $yr = int($d / 365);
                        my $mon = int(($d - 365 * $yr) / 30);
                        push @ages, '${yr}y ${mon}m';
                    } else {
                        push @ages, int($d/365) . 'y';
                    }
                }
                return @ages ? \@ages : undef;
            },
        },
    },
);
1;  #end
print 'LOADED myages3 config';


I have also tried loading the attached file as per the similar topic in here, the relevant 'Myfilename' didn't work for me either :-S
https://exiftool.org/forum/index.php/topic,5708.15.html

I must be missing something very silly here!!

Phil Harvey

The command to test this is:

exiftool -config /Users/jusefe/Documents/MyAges3.config -myages DIR

- 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 ($).

jusefe

Thanks a lot Phil!! that worked great for both config files  ;D