GNU find -[cma]time option and daylight saving time

findtime

In the GNU find man, you can read this about the -atime option:

-atime n

File was last accessed n*24 hours ago. When find figures out how many 24-hour periods ago the file was last accessed, any fractional part is ignored, so to match -atime +1, a file has to have been accessed at least two days ago.

Note the use of "n*24 hours ago" instead of "n days ago".

Now this is getting me worried about what happens when switching to winter time on that day that is 25 hours long (and there are occasionally days that are 24 hours and 1 second long when there is a leap second).

If I have a daily cron job using find -daystart -atime +1, is it potentially missing files accessed during that repeated hour?

Best Answer

For -daystart the manual says:

-- Option: -daystart

Measure times from the beginning of today rather than from 24 hours ago. So, to list the regular files in your home directory that were modified yesterday, do

find ~/ -daystart -type f -mtime 1

The '-daystart' option is unlike most other options in that it has an effect on the way that other tests are performed. The affected tests are '-amin', '-cmin', '-mmin', '-atime', '-ctime' and '-mtime'. The '-daystart' option only affects the behaviour of any tests which appear after it on the command line.

What that means that if you run:

find . -daystart -mtime 1

on the day after the winter changing time (2015-10-25 in Europe this year), that should give you the files last modified between 2015-10-25 01:00 (the first occurrence of that time) and 2015-10-25 23:59:59.999....

If run as

find . -daystart -mtime 0

on 2015-10-25, you'd expect it to get you the files modified between 00:00 and 22:59:59, but doing a simple test (with findutils 4.4.2) shows that it returns files modified between the first 01:00 and 23:59:59 (unless run before the time change).

$ find . -printf '%TFT%TT %p\n'
2015-09-25T14:28:25.4868761490 .
2015-10-25T00:02:00.0000000000 ./a
2015-10-25T23:43:00.0000000000 ./c
2015-10-25T12:42:00.0000000000 ./b
$ NO_FAKE_STAT=1 faketime -m '2015-10-25 12:23' find . -daystart -mtime 0
./c
./b
$ NO_FAKE_STAT=1 faketime -m '2015-10-25 00:32' find . -daystart -mtime 0
./a
./b
$ NO_FAKE_STAT=1 faketime -m '2015-10-25 12:23' find . -daystart -mtime 1
./a

In any case the statement So, to list the regular files in your home directory that were modified yesterday above is not always true.

Without -daystart, the check is for files modified in units of 24 hours. So if run at 12:43 on 2015-10-25, find . -mtime 0 would give you files modified between 2015-10-24 13:43 and now.

A more reliable way to give you the files that were last modified yesterday would be:

 find . -newermt 'yesterday 0' ! -newermt 'today 0'

Note that it includes the files that were last modified today at 00:00:00.0000000000 and not the ones at that time yesterday. Unfortunately there's no -oldermt predicate.

Note that zsh's age function to use in globs like:

$ autoload age # in ~/.zshrc
$ ls -ld -- *(age,yesterday,)

has similar issues.

Related Question