Redating from date in filename

Post Reply
afabris
Posts: 14
Joined: 04 Nov 19 1:04

Redating from date in filename

Post by afabris »

Hello forum:
I have some photos and videos with metadata field DateTimeOriginal = empty. I`d like to set it to the actual photo/video date. For some of the files, I`d like to set it to the date in the "Description Date" metadata field. For other files, I`d like to set it to the date in the filename (eg "PHOTO-2018-06-16-10-34-51.jpg"). I see this may be suitable for the Scripter tool, but I cannot program Pascal. Do you know of some good resource where I may get some redate Photo Supreme scripts to get me started?
thanks!
Fabris
Hert
Posts: 7911
Joined: 13 Sep 03 6:24

Re: Redating

Post by Hert »

Here's a script that redates based on file name. The requirement is that the file name is constructed with dashes (looks like yours is also). Here's some samples that can be handled:

1. YY-MM something else.jpg
2. YY-MM-DD somethingelse.jpg
3. YY-MM-DD HH-MM-SS.jpg

Use the script at your own risk (always try it on a few copied files first) and feel free to customize it to your needs.

Code: Select all

  function DateStringToDateTime(ADateString: WideString): TDateTime;
  var
    ATokens: TTntStringList;
    ys, ms, ds, hs, ns, ss, msecs: WideString;
    y, m, d, h, n, s, msec: Word;
  begin
    result := 0.0;

    ys := ''; ms := ''; ds := ''; hs := ''; ns := ''; ss := ''; msecs := '';
    y := 1899; m := 1; d := 1; h := 0; n := 0; s := 0; msec := 0;

    ATokens := TTntStringList.Create;
    try
      Tokenize(ADateString, '-', ATokens);
      if ATokens.Count >= 1 then
      begin
        ys := ATokens.Strings[0];
        if not IsValidIntNumberString(ys, False) then
          exit;

        if Length(ys) = 2 then
        begin
          if StrToInt(ys) < 20 then
            ys := '20' + ys
          else
            ys := '19' + ys;
        end;

        y := StrToInt(ys);
      end;
      if ATokens.Count >= 2 then
      begin
        ms := ATokens.Strings[1];
        if not IsValidIntNumberString(ms, False) then
          exit;
        m := StrToInt(ms);
        if (m < 1) or (m > 12) then
          exit;
      end;
      if ATokens.Count >= 3 then
      begin
        ds := ATokens.Strings[2];
        if not IsValidIntNumberString(ds, False) then
          exit;
        d := StrToInt(ds);
        if (d < 1) or (d > DaysInMonth(m)) then
          exit;
      end;
      if ATokens.Count >= 4 then
      begin
        hs := ATokens.Strings[3];
        if not IsValidIntNumberString(hs, False) then
          exit;
        h := StrToInt(hs);
        if (h < 0) or (h > 24) then
          exit;
      end;
      if ATokens.Count >= 5 then
      begin
        ns := ATokens.Strings[4];
        if not IsValidIntNumberString(ns, False) then
          exit;
        n := StrToInt(ns);
        if (n < 0) or (n > 59) then
          exit;
      end;
      if ATokens.Count >= 6 then
      begin
        ss := ATokens.Strings[5];
        if not IsValidIntNumberString(ss, False) then
          exit;
        s := StrToInt(ss);
        if (s < 0) or (s > 59) then
          exit;
      end;

      result := EncodeDateTime(y, m, d, h, n, s, msec);
    finally
      ATokens.Free;
    end;
  end;

  function ExtractDateString(AFileName: WideString): WideString;
  var
    ATokens: TTntStringList;
    AFile: WideString;
    APos: Integer;
  begin
    result := '';
    ATokens := TTntStringList.Create;
    try
      AFile := WideExtractFileName(AFileName);
      APos := WideTextPos('.', AFile);
      if APos > 0 then
        AFile := LeftStr(AFile, APos - 1);

      Tokenize(AFile, ' ', ATokens);

      if ATokens.Count >= 1 then
        result := ATokens.Strings[0];

      if ATokens.Count >= 2 then
      begin
        if WideTextPos('-', ATokens.Strings[1]) > 0 then
          result := result + '-' + ATokens.Strings[1];
      end;
    finally
      ATokens.Free;
    end;
  end;

  procedure RedateImage(AImage: TImageItem; ADt: TDateTime);
  var
    ACatItem: TCatalogItem;
    AXMP: TXMP;
  begin
    ACatItem := TCatalogItem.Create(nil);
    AXMP := TXMP.Create(False);
    try
      if PublicCatalog.FindImageCombined(AImage, ACatItem,True, vptNone) then
      begin
        PublicCatalog.LoadXMPForItem(ACatItem, AXMP, PublicOptions.CachedXMP);
        AImage.WriteExifDateTime (ADt, [dteBase, dteOriginal, dteDigitized], TimeZoneOffset, False, AXMP);
        PublicCatalog._SaveXMPForItem(ACatItem, AXMP, PublicOptions.CachedXMP, False, True, True);
      end;
    finally
      AXMP.Free;
      ACatItem.Free;
    end;
  end;

  procedure HandleImage(AImage: TImageItem);
  var
    ADateString: WideString;
    ADt: TDateTime;
  begin
    {
       examples;

       1. YY-MM something else.jpg
       2. YY-MM-DD somethingelse.jpg
       3. YY-MM-DD HH-MM-SS.jpg

       A. find first part up to space
       B. Parse first part
       C. Redate the metadata
    }

    ADateString := ExtractDateString(AImage.FileName);
    //Say(ADateString);
    ADt := DateStringToDateTime(ADateString);
    if ADt <> 0.0 then
    begin
      //Say2(ADateString, DateTimeToStr(ADt));
      RedateImage(AImage, ADt);
      //sleep(1000);
    end;
  end;

var
  i: Integer;
  APro: TxomProgress;
begin
  APro := TxomProgress.Create(nil);
  try
    APro.Caption := 'Redate from file names';
    APro.Max := Selected.Count;
    APro.Pos := 0;
    for i := 0 to Selected.Count - 1 do
    begin
      APro.ProgressText := Selected.Items[i].FileNameOnly;
      APro.Pos := i + 1;
      HandleImage(Selected.Items[i]);
    end;
  finally
    APro.Free;
  end;
end;
This is a user-to-user forum. If you have suggestions, requests or need support then please send a message
afabris
Posts: 14
Joined: 04 Nov 19 1:04

Re: Redating from date in filename

Post by afabris »

Thank you very much, Hert. This is what I was looking for to get me on the correct way. Thanks!
afabris
Posts: 14
Joined: 04 Nov 19 1:04

Re: Redating from date in filename

Post by afabris »

In the Details tab of Photo Supreme (v4), for one jpg photo, `Date Time Original` is empty. No value in this field, and it not editable either in the app. However, if I run exiftool on the file, it shows `Date Time Original` value populated with the correct date time.
Why isn`t PS showing the metadata value that exiftool can see?

[edit] Files in this situation are all synced.

Thanks!
Fabris.
Hert
Posts: 7911
Joined: 13 Sep 03 6:24

Re: Redating from date in filename

Post by Hert »

That file most likely has inconsistency between Exif/IPTC and the higher level XMP metadata. ExifTool shows Exif metadata, and PSU shows XMP metadata. Some tools out there do a bad job keeping metadata consistent at all metadata levels and only write Exif or only write XMP or even write partial XMP.

PSU offers a feature to fix such inconsistencies. Try this;
1. Right click on the file
2. Select "Metadata -> Convert metadata to XMP"
This is a user-to-user forum. If you have suggestions, requests or need support then please send a message
afabris
Posts: 14
Joined: 04 Nov 19 1:04

Re: Redating from date in filename

Post by afabris »

Thank you again Hert! this solves the date issue and actually many other metadata fields get populated once I execute this command (eg the 'Technical' group fields). It is strange because these are photos taken with the same cameras than other photos which had no issues with metadata.

Anyways this helps me a lot, thank you once more!

Fabris.
Hert
Posts: 7911
Joined: 13 Sep 03 6:24

Re: Redating from date in filename

Post by Hert »

It’s not about the camera, but about the software you’ve used on these images.
This is a user-to-user forum. If you have suggestions, requests or need support then please send a message
afabris
Posts: 14
Joined: 04 Nov 19 1:04

Re: Redating from date in filename

Post by afabris »

I've used a few before centralizing in PSU, highlights the importance of consistency.
Thanks again for all the help here!
Post Reply