You are not logged in.
Pages: 1
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
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
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
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
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
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.
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
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
Pages: 1