Using the perl rename utility (not to be confused with rename from util-linux or any other rename):
$ rename -n -e 'BEGIN {use POSIX}; next unless -f $_; my $Y = strftime "%Y", localtime((stat $_)[9]); mkdir $Y unless -d $Y; s=^=$Y/=' * rename(04.dat, 2019/04.dat) rename(2018file.md, 2018/2018file.md) rename(file02.dat, 2021/file02.dat) rename(march.dat, 2020/march.dat) rename(OctReport.txt, 2021/OctReport.txt) rename(oldfile.txt, 2017/oldfile.txt) rename(somepage_files, 2019/somepage_files) rename(somepage.html, 2019/somepage.html)
The -n option makes this a dry-run. Remove it (or replace with -v for verbose output) when you're sure it's going to do what you want. e.g.
$ find . -type f -ls 864326 9 drwxr-xr-x 2 cas cas 10 Dec 22 18:08 . 863863 1 -rw-r--r-- 1 cas cas 0 Oct 11 18:03 ./OctReport.txt 863999 1 -rw-r--r-- 1 cas cas 0 Jul 21 2019 ./somepage_files 864123 1 -rw-r--r-- 1 cas cas 0 Mar 13 2020 ./march.dat 863997 1 -rw-r--r-- 1 cas cas 0 May 15 2018 ./2018file.md 864122 1 -rw-r--r-- 1 cas cas 0 Apr 14 2019 ./04.dat 863862 1 -rw-r--r-- 1 cas cas 0 Feb 12 2021 ./file02.dat 863998 1 -rw-r--r-- 1 cas cas 0 Jul 21 2019 ./somepage.html 863996 1 -rw-r--r-- 1 cas cas 0 Jun 29 2017 ./oldfile.txt $ rename -v -e 'BEGIN {use POSIX}; next unless -f $_; my $Y = strftime "%Y", localtime((stat $_)[9]); mkdir $Y unless -d $Y; s=^=$Y/=' * 04.dat renamed as 2019/04.dat 2018file.md renamed as 2018/2018file.md file02.dat renamed as 2021/file02.dat march.dat renamed as 2020/march.dat OctReport.txt renamed as 2021/OctReport.txt oldfile.txt renamed as 2017/oldfile.txt somepage_files renamed as 2019/somepage_files somepage.html renamed as 2019/somepage.html $ find . -type f -ls 863996 1 -rw-r--r-- 1 cas cas 0 Jun 29 2017 ./2017/oldfile.txt 863862 1 -rw-r--r-- 1 cas cas 0 Feb 12 2021 ./2021/file02.dat 863863 1 -rw-r--r-- 1 cas cas 0 Oct 11 18:03 ./2021/OctReport.txt 863999 1 -rw-r--r-- 1 cas cas 0 Jul 21 2019 ./2019/somepage_files 864122 1 -rw-r--r-- 1 cas cas 0 Apr 14 2019 ./2019/04.dat 863998 1 -rw-r--r-- 1 cas cas 0 Jul 21 2019 ./2019/somepage.html 864123 1 -rw-r--r-- 1 cas cas 0 Mar 13 2020 ./2020/march.dat 863997 1 -rw-r--r-- 1 cas cas 0 May 15 2018 ./2018/2018file.md
see perldoc -f stat and perldoc -f localtime for details on those perl functions. Details on strftime() can be found in perldoc POSIX.
BTW, rename can take filenames as args on the command line, or from stdin (even NUL-separated filenames if you use rename's -0 option, which is useful when dealing with filenames containing newlines and other annoying characters). See man rename.