#1 2020-05-11 10:19

skiwi
Member
Registered: 2009-06-15
Posts: 26

Extract date from a GPX file

Hi

I have a large number of GPX files.
These contain many time metadata elements, e.g.

<time>2014-04-12T05:24:21.216Z</time>]

or

<time xmlns="http://www.topografix.com/GPX/gpx_modified/0/1">2014-04-12T05:27:03.774Z</time>

Can I get Renamer to extract the date and time of the first instance of one of these elements in the file and to insert the extracted date and time in a file name?

thanks

Simon

Offline

#2 2020-05-11 20:07

den4b
Administrator
From: den4b.com
Registered: 2006-04-06
Posts: 3,440

Re: Extract date from a GPX file

Sure, it is possible with the Pascal Script rule.

The script below will extract the content of the first <time> tag, and will insert it at the beginning of the filename.

You can adjust the script for a different placement, or use other rules to reformat and reposition the extracted content.

{ Extract first <time> tag content }
var
  Content: WideString;
  Matches: TWideStringArray;
  Pos1, Pos2: Integer;
begin
  Content := FileReadText(FilePath);
  Pos1 := WidePos('<time', Content);
  if Pos1 > 0 then
  begin
    Pos2 := WidePosEx('</time>', Content, Pos1);
    if Pos2 > 0 then
    begin
      Content := WideCopy(Content, Pos1, Pos2-Pos1);
      Pos1 := WidePos('>', Content);
      if Pos1 > 0 then
      begin
        Content := WideCopy(Content, Pos1 + 1, Length(Content));
        FileName := Content + FileName;
      end;
    end;
  end
end.

Offline

#3 2020-05-12 21:22

skiwi
Member
Registered: 2009-06-15
Posts: 26

Re: Extract date from a GPX file

den4b wrote:

Sure, it is possible with the Pascal Script rule.

This is great thankyou.
I found the information about Pascal Script you provide better than any other information for it on the www.

I made a few changes in case you want to refer to it from the Scripts page.

{ Extract the first <time> element's content from GPX file
Input: GPX file with element similar to
  <time xmlns="http://www.topografix.com/GPX/gpx_modified/0/1">2014-04-12T05:27:03.774Z</time>
Output: FileName prefixed by "yyyy-mm-dd hh.mm.ss " }
var
  Content: WideString; { date time extracted from element }
  Pos1, Pos2: Integer;
const
  Space = ' ';
begin
  Content := FileReadText(FilePath);
  Pos1 := WidePos('<time', Content); { find start tag of element }
  if Pos1 > 0 then
  begin
    Pos2 := WidePosEx('</time', Content, Pos1); {find end tag of element }
    if Pos2 > 0 then
    begin
      Content := WideCopy(Content, Pos1, Pos2-Pos1); { remove rest of line }
      Pos1 := WidePos('>', Content); { find end of start tag }
      if Pos1 > 0 then
      begin { reformat datetime }
        Content := WideCopy(Content, Pos1 + 1, Length(Content)); { extract timestamp }
        Content := WideReplaceStr(Content, ':', '.'); { replace ":" with "." }
        Content := WideReplaceStr(Content, 'T', Space); { replace T with space }
        Content := WideReplaceStr(Content, 'Z', Space); { replace Z with space }
        FileName := Content + Space + FileName; {prefix filename with datetime and a space }
      end;
    end;
  end
end.

Last edited by skiwi (2020-05-17 09:15)

Offline

#4 2020-05-17 09:14

skiwi
Member
Registered: 2009-06-15
Posts: 26

Re: Extract date from a GPX file

PascalScript question:

I want to check in the above script that the extracted "Content" does actually contain a Date and Time string.
RegEx springs to mind, and I had a look at the useful Delphi Basics site, but I can't see any string operations that allow RegEx.

How could I go about checking that a string variable contains, say, a date?

Thanks in advance for any help

Offline

#5 2020-05-17 11:09

Stefan
Moderator
From: Germany, EU
Registered: 2007-10-23
Posts: 1,161

Re: Extract date from a GPX file

skiwi wrote:

PascalScript question:

I want to check in the above script that the extracted "Content" does actually contain a Date and Time string.
RegEx springs to mind, and I had a look at the useful Delphi Basics site, but I can't see any string operations that allow RegEx.

How could I go about checking that a string variable contains, say, a date?

Thanks in advance for any help


See the wiki for PascalScript functions to use within ReNamer.

wiki > ReNamer > Pascal_Script:Functions > Date_and_Time

http://www.den4b.com/wiki/ReNamer:Pasca … e_and_Time




Me think that functions could be of some use:

function TryEncodeDate(Year, Month, Day: Word; var Date: TDateTime): Boolean;
function TryEncodeTime(Hour, Min, Sec, MSec: Word; var Time: TDateTime): Boolean;
function TryEncodeDateTime(Year, Month, Day, Hour, Minute, Second, MilliSecond: Word; out ADateTime: TDateTime): Boolean;
function TryScanDateTime(const Pattern, Subject: String; out DateTime: TDateTime): Boolean;

this function returns TRUE or FALSE depending on the success of the operation



But I don't get it completely:

TryScanDateTime() returns an Boolean value as result, but why there is ALSO an "out DateTime" part?
Silly me would think """function TryScanDateTime(const Pattern, Subject: String): Boolean;""" would be enough for an Boolean result, no?

And then, also 'yyyy-mm-dd','20-12-05' return true?



My Test:

var
myDateTime:TDateTime;
myDateStr,strDateTime:String;

begin
  // Add your code here
  myDateStr :=   '2020-05-17';
  // // Note  TryScanDateTime needs ReNamer 7.2 or newer
   //TryScanDateTime(const Pattern, Subject: String; out DateTime: TDateTime): Boolean;
   IF(TryScanDateTime('yyyy-mm-dd',myDateStr,myDateTime)) THEN
   begin
   Showmessage('1: TRUE, date detected');
   end;

   IF(TryScanDateTime('yyyy-mm-dd','20-12-05',myDateTime)) THEN
   begin
   Showmessage('2: TRUE, but why?');
   end;

   IF(TryScanDateTime('yyyy-mm-dd','example wrong',myDateTime)) THEN
   begin
   Showmessage('3: TRUE');
   end
   else
   Showmessage('3: FALSE, no valid date found'); 


   //FormatDateTime(const Format: String; DateTime: TDateTime): String;
  strDateTime :=   FormatDateTime ('yyyy-mm-dd',myDateTime); //DateTimeToStr
        ShowMessage( 'Found date was: ' + strDateTime );
end.                        

Perhaps I am completely on the wrong track?



- - - -


For to check results by an RegularExpression comparison try

http://www.den4b.com/wiki/ReNamer:Pasca … xpressions

var
  RegExSubPatterns: TWideStringArray;
begin
  // split the filename into parts by utilizing regular expressions:
  //SubMatchesRegEx create an array of matches from expression in () parentheses:
  //SubMatchesRegEx(const Input, Find: WideString;const CaseSensitive: Boolean): TWideStringArray;
  RegExSubPatterns := SubMatchesRegEx(FileName,'(.*?)\[(\d+) by (\d+)\]',false);
  if Length(RegExSubPatterns) <= 0 then exit;
end.

--or--

var
  RegExResult: TWideStringArray; 
begin
  //MatchesRegEx returns an array of full matches, which matched the entire expression, not the sub-patterns.
  //MatchesRegEx(const Input, Find: WideString;const CaseSensitive: Boolean): TWideStringArray;
  RegExResult:=MatchesRegEx(myDate, '\d\d\d\d-\d\d-\d\d' false);
  if Length(RegExSubPatterns) then
  begin
    //.....
  end
  else
    //.....
  end;
end.

Read the  *WIKI* for HELP + MANUAL + Tips&Tricks.
If ReNamer had helped you, please *DONATE* to Denis or buy a PRO license. (Read *Lite vs Pro*)

Offline

#6 2020-05-17 11:43

den4b
Administrator
From: den4b.com
Registered: 2006-04-06
Posts: 3,440

Re: Extract date from a GPX file

Stefan wrote:

TryScanDateTime() returns an Boolean value as result, but why there is ALSO an "out DateTime" part?

The out argument gets you the parsed date-time value, so that you can use it other functions, for example, reformat it in a different way, or adjust time. But if you only need to verify a particular format, then you don't need it.

Stefan wrote:

And then, also 'yyyy-mm-dd','20-12-05' return true?

It is a good question. What if the year is really just 20, rather than 2020? It could also be 200 and even 20000.

Should it expect 0 padding to exactly 4 digits, i.e. year "0020"? It seems a bit arbitrary.

For the reference, both FPC and PHP zero pad the year to exactly 4 digits when formatting using the long year format, but parsing does not require the 0 padding, so parsing "20" with the long year format produces year 20. Similarly, parsing day and month numbers with the long format also does not require the 0 padding.

Last edited by den4b (2020-05-17 11:57)

Offline

#7 2020-05-17 15:59

Stefan
Moderator
From: Germany, EU
Registered: 2007-10-23
Posts: 1,161

Re: Extract date from a GPX file

den4b wrote:
Stefan wrote:

TryScanDateTime() returns an Boolean value as result, but why there is ALSO an "out DateTime" part?

The out argument gets you the parsed date-time value, so that you can use it other functions, for example, reformat it in a different way, or adjust time. But if you only need to verify a particular format, then you don't need it.

Thanks for explanation. It's just confusing without mention that fact in documentation and without examples how to use.

>>"then you don't need it"
But I have to USE it, or parser will report an error. I mention this just for reference.



Stefan wrote:

And then, also 'yyyy-mm-dd','20-12-05' return true?

It is a good question. What if the year is really just 20, rather than 2020? It could also be 200 and even 20000.

Should it expect 0 padding to exactly 4 digits, i.e. year "0020"? It seems a bit arbitrary.

For the reference, both FPC and PHP zero pad the year to exactly 4 digits when formatting using the long year format, but parsing does not require the 0 padding, so parsing "20" with the long year format produces year 20. Similarly, parsing day and month numbers with the long format also does not require the 0 padding.

I just expect, if I check for _4_ digits , a _2_ digit result is not an match.
(And no, I do not expect 0 padding to exactly 4 digits!)
Me think I would rather like to use:
IF ( ('yyyy-mm-dd','20-12-05') OR ('yy-mm-dd','20-12-05') ) THEN



 


Read the  *WIKI* for HELP + MANUAL + Tips&Tricks.
If ReNamer had helped you, please *DONATE* to Denis or buy a PRO license. (Read *Lite vs Pro*)

Offline

Board footer

Powered by FluxBB