I was recently presented with the need to rename a folder of images based on a timestamp. This way, I can keep saving new files in that folder with overlapping filenames (i.e., 01.jpg, 02.jpg, 03.jpg, etc.), and every time I run this script all images are prepended with a timestamp. I still want the files to be sorted alphabetically, which is why an alphabetical timestamp (rather than a random hash) is preferred.
- At first I considered a long date such as 2014-04-19-01.jpg, but that adds so much text!...also, it doesn't include time of day.
- If I include time of day, it becomes 2014-04-19-09-16-23-01.jpg
- If I eliminate dashes to shorten it, it becomes hard to read, but might work 140419091623-01.jpg
- If I use Unix Epoch time, it becomes 1397912944-01.jpg
The result I came up with uses base conversion and a string table of numbers and letters (in alphabetical order) to create a second-respecting timestamp hash using an arbitrary number of characters. For simplicity, I used 36 characters: 0-9, and a-z. I then wrote two functions to perform arbitrary base conversion, pulling characters from the hash. Although I could have nearly doubled my available characters by including the full ASCII table, respecting capitalization, I decided to keep it simple. The scheme goes like this:
- Determine the date / time: 19-Apr-2014 13:08:55
- Create an integer of Unix Epoch time (seconds past Jan 1, 1970): 1397912935
- Do a base conversion from a character list: n4a4iv
- My file name now becomes n4a4iv-01.jpg - I can accept this!and when I sort the folder alphabetically, they're in order by the timestamp
I can now represent any modern time, down to the second, with 6 characters. Here's some example output:
19-Apr-2014 13:08:55 <-> 1397912935 <-> n4a4iv 19-Apr-2014 13:08:56 <-> 1397912936 <-> n4a4iw 19-Apr-2014 13:08:57 <-> 1397912937 <-> n4a4ix 19-Apr-2014 13:08:58 <-> 1397912938 <-> n4a4iy 19-Apr-2014 13:08:59 <-> 1397912939 <-> n4a4iz 19-Apr-2014 13:09:00 <-> 1397912940 <-> n4a4j0 19-Apr-2014 13:09:01 <-> 1397912941 <-> n4a4j1 19-Apr-2014 13:09:02 <-> 1397912942 <-> n4a4j2 19-Apr-2014 13:09:03 <-> 1397912943 <-> n4a4j3 19-Apr-2014 13:09:04 <-> 1397912944 <-> n4a4j4
Interestingly, if I change my hash characters away from the list of 36 alphanumerics and replace it with just 0 and 1, I can encode/decode the date in binary:
19-Apr-2014 13:27:28 <-> 1397914048 <-> 1010011010100100111100111000000 19-Apr-2014 13:27:29 <-> 1397914049 <-> 1010011010100100111100111000001 19-Apr-2014 13:27:30 <-> 1397914050 <-> 1010011010100100111100111000010 19-Apr-2014 13:27:31 <-> 1397914051 <-> 1010011010100100111100111000011 19-Apr-2014 13:27:32 <-> 1397914052 <-> 1010011010100100111100111000100 19-Apr-2014 13:27:33 <-> 1397914053 <-> 1010011010100100111100111000101 19-Apr-2014 13:27:34 <-> 1397914054 <-> 1010011010100100111100111000110 19-Apr-2014 13:27:35 <-> 1397914055 <-> 1010011010100100111100111000111 19-Apr-2014 13:27:36 <-> 1397914056 <-> 1010011010100100111100111001000 19-Apr-2014 13:27:37 <-> 1397914057 <-> 1010011010100100111100111001001
Here's the code to generate / decode Unix epoch timestamps in Python:
hashchars='0123456789abcdefghijklmnopqrstuvwxyz' #hashchars='01' #for binary def epochToHash(n): hash='' while n>0: hash = hashchars[int(n % len(hashchars))] + hash n = int(n / len(hashchars)) return hash def epochFromHash(s): s=s[::-1] epoch=0 for pos in range(len(s)): epoch+=hashchars.find(s[pos])*(len(hashchars)**pos) return epoch import time t=int(time.time()) for i in range(10): t=t+1 print(time.strftime("%d-%b-%Y %H:%M:%S", time.gmtime(t)), "<->", t,"<->",epochToHash(t))