Zettelkasten prefixer UID option: base 36 epoch time

Use case or problem

The default (and commonly used) Zettelkasten prefixer UID format is a minutes-resolution timestamp in YYYYMMDDHHMM format (Moment.js syntax) of ten decimal digits. The when the prefixer generates a new note and detects a UID collision, it treats the ID as a base-10 number and adds 1. Some users avoid collisions by extending this to a 12-digit seconds resolution format: YYYYMMDDHHMMss. This ID format (plus collision detection) is easy to generate, assures uniqueness, and results in an ASCIIbetical sort equivalent to a chronological sort.

20220323233019 Timestamps are too long and too easy to read

There are two major disadvantages to timestamp UIDs. For one, they’re long, 10 to 12 numerals. A long ID potentially obscures the actual title in some views, and clutters link text. It’s also too human readable: it’s recognizably a timestamp. I’d prefer not to recognize it at all so my mind doesn’t try to parse it.

The UID is primarily there to avoid title collisions when similar titles mean different things in different link contexts, and to alleviate the cognitive load of having to think about such collisions. Ideally it would stay out of the way otherwise.

Proposed solution

I’d like a Zettelkasten prefixer formatting option to use a base 36 rendition of an epoch time value: a number of seconds since a fixed starting datetime. This would be similar to the Moment.js time format X, but converted from base 10 to base 36, where the digits are 0-9 a-z. This provides an obscured ID based on a timestamp with seconds resolution that retains a chronological ASCIIbetical sort and is usefully shorter than other timestamp-based formats.

15sj2b Base-36 UIDs are short and obscured

Using the Unix definition of epoch time (0 = January 1, 1970), all timestamps up to December 23, 2038 are six or fewer base-36 digits. Personally, I’d be happy with a later start year, which would postpone the final six-digit timestamp. Setting 0 = January 1, 2020 00:00:00 would make March 23, 2022 00:00:00 = 15sj00, with zzzzzz landing on December 23, 2088. Regardless of which start date is used, the prefix can just advance to seven base-36 digits at that point.

zzzzzz The future is wild, man
1000000 A new era of Zettels has dawned

Other considerations

Base 64 is another possibility, but it doesn’t actually make IDs usefully shorter. Right now in epoch time uses six base-64 digits. We’d have to specify a custom base-64 character set to replace the forward slash in RFC 4648. Mixing upper and lower case letters with numbers makes IDs less recognizable (O/0, I/1/l, etc.) if an ID ever needs to be typed or remembered.

With a resolution of seconds, collision detection would only be needed as an edge case. It’d be useful if the collision detector knows from configuration that the ID is a base-36 number and uses base-36 to increment the value, e.g. if I create a Zettel during the second 15sj2b and there is coincidentally another Zettel with that UID, the new UID would be 15sj2c.

A minute-resolution base-36 UID would be one character shorter. If users are comfortable with minute-resolution, another character in savings would be compelling. (Now from 1970 in minutes is fbpk8.)

fbpk8 If you're having more than one idea per minute, good job!

Current workaround

A format string of “X” uses base 10 epoch time, which is more obscure but not shorter (ten base-10 digits as of today):

1648091312 At least it's not a readable timestamp

There is no way to produce a usefully shorter timestamp-based UID with resolution at least as granular as minutes with the Moment.js timestamp formatting options.

Related feature requests

I poked around the forums to understand people’s preferences for generated UIDs and saw some desire for UIDs more opaque than timestamps, e.g. random strings. I also saw someone ask for a way to hide UIDs from some views, which suggests that shorter UIDs might be a useful compromise. Others do seem to like UIDs to be visible to reinforce that Zettels can be created freely without having to manage collisions.

I don’t use the default system and never understood the attraction of a prefix unless it was for an obvious timestamp and notes in timestamp sequence.

When I want a UID I use a text expander - so works in any program - and usually insert a timestamp suffix. A suffix doesn’t draw the eye or obscure the desired title.

I prefer a simple system I can use and parse in any program, so convoluted solutions aren’t for me.

While with a different app, I’ve been following a similar approach (base32-encoded timestamps with millisecond precision due to the need for automated generation on import),. However, I don’t include the ID in the title, but just in the note’s metadata (and as a suffix in the filename):

Yours would be even shorter and still sort in chronological order which may be useful to some (I prefer clean titles and sort by a dedicated “creation date” column instead).

1 Like