TimeAdjust - change or copy file dates/times

Discuss and announce Total Commander plugins, addons and other useful tools here, both their usage and their development.

Moderators: white, Hacker, petermad, Stefan2

StatusQuo
Power Member
Power Member
Posts: 1524
Joined: 2007-01-17, 21:36 UTC
Location: Germany

TimeAdjust - change or copy file dates/times

Post by *StatusQuo »

If you have to synchronize files known to be binary identical but having different file dates, it's faster to copy just the date info instead of copying also the file contents.

Since TC 7.50 you can use the context menu in TC's Synchronize tool (cm_FileSync) to copy date and time of files (without having to copy their content).

If you prefer a faster/easier way, this may be what you are looking for:

Code: Select all

////////////////////////////////////////////
// TimeAdj V1.01  (C) StatusQuo 2007-2009 //
////////////////////////////////////////////
// Set, Modify, Copy file dates and times  
Download Link: Installation:
  • Just unpack the archive to a folder of your choice.
    If you use a folder that is not included in the system's "PATH" variable, the path to TimeAdj.exe has to be added in the step below in "Command" field (and "Start path").
TC integration:
  • To copy dates/times of marked files in TC's current panel to the other panel (files with the same name), use this for defining a button etc:

    Code: Select all

    Command   :  TimeAdj.exe
    Parameters:  /LST  "%L"  "%T\"
    
    To support processing selected sub-folders recursively, please use the batch caller TimeAdj_recursive.cmd, included in the archive.
    Settings for Button/Start Menu (please note the additional parameter "%P", this is important for UNC paths and Branch View):

    Code: Select all

    Command   : TimeAdj_recursive.cmd
    Parameters: /LST  "%L"  "%T"  "%P"
    Start path: (set to location of timeadj.exe, if this is not included in system PATH variable)
    
Advanced parameters:
  • Using advanced parameters TimeAdj supports relative or absolute changes of dates/times, too, also additionally to copying them. A short syntax info/explanation and examples can be found in the included file "TimeAdj_Help.txt" or by calling "TimeAdj.exe /?".
Known issues:
  • Only works on files, can not change date/time of folders.
  • Only copies/modifies "changed" dates/times, NOT creation / last access dates.
  • To support TC's branch view, please use the included batch caller (*.cmd).
License:
  • Freeware, details included in file TimeAdj_License.txt.
Last edited by StatusQuo on 2017-10-27, 16:21 UTC, edited 14 times in total.
Who the hell is General Failure, and why is he reading my disk?
-- TC starter menu: Fast yet descriptive command access!
User avatar
MVV
Power Member
Power Member
Posts: 8702
Joined: 2008-08-03, 12:51 UTC
Location: Russian Federation

Post by *MVV »

When I wrote for myself a little tool for correction dates of large ammount of photos (program shifts file modify date and EXIF timestamps), my date handling functions handled all possible cases of dates. :)
Postkutscher
Power Member
Power Member
Posts: 556
Joined: 2006-04-01, 00:11 UTC

Post by *Postkutscher »

2MVV
feel free to publish your work :)
User avatar
MVV
Power Member
Power Member
Posts: 8702
Joined: 2008-08-03, 12:51 UTC
Location: Russian Federation

Post by *MVV »

Postkutscher wrote:2MVV
feel free to publish your work :)
It has only Russian interface) and here is TimeAdj's discussion page. :)
Here my time shift functions:

Code: Select all

const int MonthDays[]={0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

int DayOfYear(const SYSTEMTIME& Date) {
	int day=Date.wDay-1+(!(Date.wYear&3)&&Date.wMonth>2 ? 1 : 0);
	for (int i=1; i<Date.wMonth; ++i) day+=MonthDays[i];
	return day;
}

void AddDays(SYSTEMTIME& Date, int Days) {
	Days+=DayOfYear(Date);
	Date.wDay=Date.wMonth=1;
	while (Days<0) Date.wYear-=4, Days+=1461;
	while (Days>=365+(!(Date.wYear&3) ? 1 : 0)) Days-=365+(!(Date.wYear&3) ? 1 : 0), ++Date.wYear;
	for (int i=1; i<12&&Days>=MonthDays[i]+(i==2&&!(Date.wYear&3) ? 1 : 0); ++i) Days-=MonthDays[i]+(i==2&&!(Date.wYear&3) ? 1 : 0), ++Date.wMonth;
	Date.wDay+=Days;
}

int DaysBetween(const SYSTEMTIME& Before, const SYSTEMTIME& After) {
	int days=DayOfYear(After)-DayOfYear(Before);
	int year=Before.wYear;
	while (year>After.wYear) year-=4, days-=1461;
	while (year<After.wYear) days+=365+(!(year&3) ? 1 : 0), ++year;
	return days;
}
StatusQuo
Power Member
Power Member
Posts: 1524
Joined: 2007-01-17, 21:36 UTC
Location: Germany

Post by *StatusQuo »

2MVV
It has only Russian interface
Unfortunately I don't speak Russian. But if you find some time for translating, I'd gladly test it. ;)
my date handling functions handled all possible cases of dates.
Thanks for sharing it, interesting algorithm.
TimeAdj currently calculates directly with FILETIME values wherever possible, so the system does most of the work here.

Adding days should be no problem, but "a month" or "a year":
29.02.2008 + "1 year" = ?
29.01.2009 + "1 month" = ?
As there is no 29.02.2009, TimeAdj's result is 01.03.2009 in both cases.

Maybe instead of overlapping to the next month it would be more logical to cut down the days until they fit in the given month (28.02.2009 in the above cases).
I'll check what can be done.
Who the hell is General Failure, and why is he reading my disk?
-- TC starter menu: Fast yet descriptive command access!
User avatar
MVV
Power Member
Power Member
Posts: 8702
Joined: 2008-08-03, 12:51 UTC
Location: Russian Federation

Post by *MVV »

When I shift dates, I shifh them on DAYS NUMBER. So, if I change date of one file from 01.04.2008 to 01.04. 2009, then I'll change date of second one from 29.02.2008 to 28.02.2009 because shift value contains 365 days. The reason that the most accurate strategy is to count exact days number between dates.

StatusQuo wrote:Unfortunately I don't speak Russian. But if you find some time for translating, I'd gladly test it. ;)
I took this into acount when wrote previous post.

I added English dialog and messages, if you have 1049 locale, you'll see Russian messages, English in other case. In order to reduce size I compiled this with linked MSVCRT in VS 6.0. You may test my little tool here: http://files.wyw.ru/3875956 (CRC32: 258E859D)
StatusQuo
Power Member
Power Member
Posts: 1524
Joined: 2007-01-17, 21:36 UTC
Location: Germany

Post by *StatusQuo »

2MVV
Nice tool, thanks. Good idea to change also EXIF information.
Using number of days sure is a good idea for this purpose, as there are fixed source and target dates.

The difficulty in TimeAdj is currently that every one of multiple parameters changes the target date like
30.01.2007 /m+1 /y+1 /d-1
Currently this would result in > 28.02.2007 > 28.02.2008 > 27.02.2008 (expected IMO: 29.02.2008).
I have a solution in mind that would summarize all parameters first, find a reasonable adjustment of the target date based on the initial one and the parameters, and finally apply the target date.
This would need rewriting most of the code, so it will take some time...

For the next version I'll first implement a date correction which is executed for every parameter one by one.
This should be no big deal, I think I'll find time for this in the next few days.


BTW, initially TimeAdj was created to just copy dates. Shifting was then added to let the target files still appear "changed" in TC Sync by adding a few seconds.
This way global changes can be applied to multiple files (like server name changes in Batch files) without setting them all to current date.
Who the hell is General Failure, and why is he reading my disk?
-- TC starter menu: Fast yet descriptive command access!
Postkutscher
Power Member
Power Member
Posts: 556
Joined: 2006-04-01, 00:11 UTC

Post by *Postkutscher »

2StatusQuo
2MVV
Thank you both :)
User avatar
MVV
Power Member
Power Member
Posts: 8702
Joined: 2008-08-03, 12:51 UTC
Location: Russian Federation

Post by *MVV »

StatusQuo wrote:2MVV
Nice tool, thanks. Good idea to change also EXIF information.
EXIF info change was the main purpose of this tool because many people a bit lazy to setup date/time on their camera (as you understand, I know one of them :) - but not me).
StatusQuo
Power Member
Power Member
Posts: 1524
Joined: 2007-01-17, 21:36 UTC
Location: Germany

Post by *StatusQuo »

2MVV
Your date function seems to ignore the leap year exception every 100/400 years (although your calendar is right). This is what I use:

Code: Select all

BOOL IsLeapYear( WORD wYear )
{   return ( !(wYear % 4) && ((wYear % 100) || !(wYear % 400)) );
}
Who the hell is General Failure, and why is he reading my disk?
-- TC starter menu: Fast yet descriptive command access!
StatusQuo
Power Member
Power Member
Posts: 1524
Joined: 2007-01-17, 21:36 UTC
Location: Germany

Post by *StatusQuo »

StatusQuo wrote:For the next version I'll first implement a date correction which is executed for every parameter one by one.
Version 0.110 is ready, download link updated in initial post.
Who the hell is General Failure, and why is he reading my disk?
-- TC starter menu: Fast yet descriptive command access!
User avatar
Balderstrom
Power Member
Power Member
Posts: 2148
Joined: 2005-10-11, 10:10 UTC

Post by *Balderstrom »

Are ya'll accounting for the leap seconds ?
*BLINK* TC9 Added WM_COPYDATA and WM_USER queries for scripting.
User avatar
MVV
Power Member
Power Member
Posts: 8702
Joined: 2008-08-03, 12:51 UTC
Location: Russian Federation

Post by *MVV »

StatusQuo wrote:2MVV
Your date function seems to ignore the leap year exception every 100/400 years (although your calendar is right). This is what I use:

Code: Select all

BOOL IsLeapYear( WORD wYear )
{   return ( !(wYear % 4) && ((wYear % 100) || !(wYear % 400)) );
}
Don't understand this thing. :shock:

Wikipedia had explained this, I didn't know before that e.g. 1900 year wasn't the leap year.

But unfortunately I have no photos from last century for checking such thing. :D
Balderstrom wrote:Are ya'll accounting for the leap seconds ?
:lol:
StatusQuo
Power Member
Power Member
Posts: 1524
Joined: 2007-01-17, 21:36 UTC
Location: Germany

Post by *StatusQuo »

MVV wrote:But unfortunately I have no photos from last century for checking such thing.
Well, people probably won't be complaining before February 2100. ;-)
Balderstrom wrote:Are ya'll accounting for the leap seconds ?
Not yet. But if Wikipedia is right, it would be easier to add an additional leap day in 4000 or 8000 years.
I confess the algo may be wrong then. :D
Who the hell is General Failure, and why is he reading my disk?
-- TC starter menu: Fast yet descriptive command access!
StatusQuo
Power Member
Power Member
Posts: 1524
Joined: 2007-01-17, 21:36 UTC
Location: Germany

Post by *StatusQuo »

Good news, TimeAdj 0.200 is ready.

Re-ordering the given parameters is not (yet) implemented, so when multiple parameters are used, parameter /d has to be specified as the last one (of /y /m /d).

Using this order, every parameter combination should work now.
Who the hell is General Failure, and why is he reading my disk?
-- TC starter menu: Fast yet descriptive command access!
Post Reply