OpenStreetMap logo OpenStreetMap

Recently, someone asked me to create a custom MapCSS style for JOSM that visually indicates how “fresh” OSM objects are—essentially, a way to distinguish recently updated or created objects from older ones at a glance.

Digging into the JOSM MapCSS implementation, especially the eval expression support, I realized this was very doable.

The Basic Idea

The approach is pretty straightforward. Each OSM object has a timestamp field (typically stored as a Unix timestamp). By comparing this timestamp to a reference timestamp (say, representing the current year—2025 in this case), we can calculate how “old” an object is.

So I hardcoded a reference timestamp for 2025, subtracted the OSM timestamp from it, and divided the result by the number of seconds in a year (ignoring leap years for simplicity). This gives us a rough “age” of the object in years.

For example, if the result is around 6.0, that means the object was last updated approximately six years ago—relative to 2025. Since the reference year is hardcoded, you’d either need to mentally adjust this value when viewing it in future years or update the style file annually. A bit of a hack, but functional.

Improving the Approach

Instead of using a shifting reference year like 2025, I thought: why not use a fixed one, like 2000? Since OpenStreetMap started in 2004, anything before that is irrelevant for most use cases.

Using 2000 as a base year gives a clean shorthand: subtract the object’s timestamp from the year 2000, and you get a simple year offset. For example, a result of 25 means the object was last updated in 2025.

I shared this version with the person who originally requested the feature. He liked it but suggested a further improvement: instead of displaying just 25, why not show the full year 2025?

Good idea.

To implement that, I simply concatenated "20" in front of the calculated value.

way {
  text: auto;
  text: eval(concat("20",substring(divided_by(osm_timestamp()-946692127,31556952),0,4)));
  text-halo-color: white;
  font-size:20px;
  text-anchor-horizontal:center;
  text-anchor-vertical:center;
  text-position:center;
}

Done. Clearer, easier to read, and more intuitive.

He was happy with it—and so was I.

Publishing the Style

With the style working well, it was time to share it with the broader community. This was my first time publishing a style to JOSM, so I was a bit nervous.

I started by registering a new JOSM wiki account, then created a new wiki page to host the style. Thanks to some prior experience with wikis, setting up the page was smooth. I referenced existing style pages, copied over relevant templates, and filled in the necessary details.

Once everything was in place, I anxiously opened JOSM, navigated to Preferences → Map Paint Styles, and refreshed the list.

And there it was—LastUpdated, my very first published style.

One last test: I installed it directly from the style list.

It worked! :D


Note :

  • The decimal number after the year is not the actual month in base-12. Instead, it roughly represents the progress of the year in base-10.
  • It only calculates the last update time of ways. Individual nodes and relations are not included.
Email icon Bluesky Icon Facebook Icon LinkedIn Icon Mastodon Icon Telegram Icon X Icon

Discussion

Comment from watmildon on 27 May 2025 at 00:29

Very cool!! I look forward to whatever fun things you come up with next.

Comment from Lumikeiju on 27 May 2025 at 01:51

Thanks for sharing this (the style and the process) - I need to make a few of my own!

Comment from FajrAl on 27 May 2025 at 08:17

Simple yet powerful style!

Comment from Koreller on 28 May 2025 at 19:55

Great improvement ! You’ve got style 😎 !

Comment from BarryMyles on 1 June 2025 at 16:20

Just installed this and it works really well.

Comment from tordans on 2 June 2025 at 05:59

I remember this right, don’t I: the object.timestamp and .version only changes when tags are changed. Geometric only changes don’t show up. So in order to update eg a house it’s not enough to just move it you also have to add a ‚check_date‘ or similar.

Comment from tordans on 2 June 2025 at 06:01

PS: for bike infra in Germany there is also https://radinfra.de/kampagnen/currentness_too_old/ which highlights „old“ data in OSM

Comment from SColchester on 2 June 2025 at 09:00

This is wonderful! Just pulled it into JOSM and working great. One tweak that would make it even more useful - at the moment the decimal figure after the year maxes out at 10 for December. So it takes a bit of quick reasoning to estimate the month. Do you think there is any way of adjusting that so that the figure after the date matches the month, e.g. 2023.11 would represent – ‘some point in November 2023’?

Comment from srvbhattarai on 2 June 2025 at 10:58

Nice one!

Comment from KingVik on 2 June 2025 at 19:25

This is really great! However, I suggest an improvement that would display the year and month in the format ‘2025.06’ representing the year 2025 and the month of June. This would enhance clarity. Additionally, the second edits that have yet to be uploaded display ‘20-29,’ which I can’t fully explain.

Comment from JohnW11 on 3 June 2025 at 09:01

Great idea, will be very useful

Log in to leave a comment