A user suggested adding a timezone field to Pronouns.page. This website lets people, among other things, create a card with info about how they want to be referred – their pronouns, names, etc. But it also has some generic fields, like age or links, so the team was onboard with the idea of adding some more basic info: not just timezone, but while we're at it, why not also a location?
Well, adding a location is not as easy as it seems…
First thing that comes to mind when I think of adding a location field in a profile is my experience running #TeamLocked (NSFW). I thought I implemented it in a pretty neat way – but turns out I still couldn't avoid issues.
I wanted the data to be structured, not just a free text field – that way I could add some smaller or bigger features around it: from displaying a little emoji flag next to a country name, to allowing people to search users by country and province.
So I split it into three levels:
province (which depending on context can mean a state, a province, a województwo, etc.) and
city. First two being a selection from predefined lists, while the last one a free text input – cause I'm not going to manage a database of all cities, municipalities and villages in the world 😅 But even for countries and provinces, I didn't want to manually manage that list either – those things change constantly, and I'd rather focus on actually running the page. So I delegated the issue to the United Nations. I wrote a script that fetches the list of countries from here and the list of provinces from here, puts it into a neat JSON file, and then gets used to generate the select fields.
I thought that would be simple and unproblematic… until someone messaged me, angry that my website calls his country “Taiwan, Province of China”. Which is not something I stand for, but I checked and indeed that's how UNECE describes the country code “TW”. It's some kind of a weird compromise between recognising Taiwan's independence and pleasing China. Let's give it a separate country code while still calling it a part of another country… Ugh…
I changed my script to rename that item on the fly, but then more of similar issues kept coming. I checked if Kosovo is on a list – nope, despite having an ISO country code (XK) and an emoji flag (🇽🇰), it isn't included on UNECE's list. So I added it. The list of British provinces didn't include London for some reason. North Macedonia's name didn't get updated for a while, and Czechia's still isn't. Even though I had an automated script and was delegating responsibility to an international authority – I still ended up needing to put in manual effort into it.
On Pronouns.page it gets even more complicated
Despite unexpected issues, it ended up working really well in the end. But simply applying a similar approach (well, probably just reusing the very same script) wouldn't really fit Pronouns.page well.
First of all, unlike #TeamLocked, an adult dating website, Pronouns.page is family friendly, and a lot of its users are minors. I want to make sure that I don't create a feature that could inadvertedly cause harm. What if a 13-year-old queer kid sees a free text input field called “location” and without thinking much just puts in their full home address?
We'd also like to avoid unnecessary political conflicts. Don't get me wrong, we're quite a political team, but our mission is to tell enbies (and queers in general) that they're amazing, that they deserve respect and recognition of their identity, and that they have a right to shape their language to meet their needs; not to get tangled in endless discussions over which government has jurisdiction over which piece of land. Actually, many of us are anarchists, so we'd rather see those governments fall than start showing their flags as a location indicator and validating the notion that artificial political borders are the best way to describe where you are 😅
Then there's a question of localisation. In the database we'd of course save the country info as a simple country code, but when displaying it – on a page so heavily focused on language and localisation – we'd have to take into account wheter “DE” should get shown as “Germany”, “Deutschland”, “Duitsland”, “Niemcy”, … There's databases online that we could use for that, but it's adding another layer of complexity…
There is a way to describe one's location that's super simple and (mainly) independent from politics – just use latitude and longitude, right? Other than the prime meridian being an arbitrary choice, it literally just describes one's location on a globe using simple geometry.
There is one problem though, at least for our use case: it's way too accurate. We want to allow users to share some very basic info about themselves, to let others know whether they live nearby or across an ocean – and not to be their GPS 😅
What if we rounded it to the nearest degree, though? Or 5 degrees? That way we'd only know that someone lives within a rectangle of few hundred kilometers by few hundred kilometers, giving us a healthy dose of inaccuracy and therefore privacy.
Well, I made a little proof of concept of how selecting one's location would look like, and TBH it's not too nice or intuitive. It's just a map with some arbitrary rectangle following your mouse, it looks confusing when you live near an edge of such a rectangle, it would require some fancier projection than Mercator, it wouldn't be too easy to use on mobile, etc. etc.
All of those potential issues can be overcome, of course, but I'd rather settle for something easier, if possible.
Timezones to the rescue!
Well, the answer has been there all along! We were going to implement timezones anyway, right? We can use that for location information. After all, time and space are very closely related!
The simplest way to approach storing one's timezone would be to save the offset, like
UTC-5. But offset ≠ timezone! My timezone is UTC+1 now, but in March it will switch to UTC+2 even if I don't move anywhere – thanks DST 🙄 It's more accurate to use IANA's timezones, in my case
Europe/Amsterdam – that way a library can just calculate the proper offset itself.
But as you can see, that format already includes some location information! Why don't we just use it? Here's how those timezones look on a map:
It looks exactly like what we need! It splits the Earth into chunks that look less arbitrary and clunky than some purely geometric lat/long rectangles. Chunks that are big enough not to give away too much of someone's location, but small enough to give a pretty good understanding of how far away from you someone is. Sure, in many cases those splits follow country borders, but at least the assocciated labels focus mostly on cities and geographical names rather than political ones.
Implementing the feature
So, let's get to actually implementing the timezone field! It ended up being way simpler than I imagined. Here's how the form looks:
this.timezones = Intl.supportedValuesOf('timeZone');
I'm already using Luxon in the project, so let's leverage its timezone features to add the “Detect automatically” button:
this.timezone = DateTime.local().zone.name;
Yup, that's it. Well, setting aside all the boring stuff, like migrations, server-side handling, autocomplete component, etc. – but the timezone part itself was incredibly easy!
I also added switches to let users choose whether their continent/ocean and location field should be explicitly displayed on their card (the full timezone code needs to be published by the API anyway, in order to correctly calculate the offset, but we can decide whether to show it in an easily accessible way).
And here's how it shows up in the profile:
The clock is of course dynamic. I used Luxon's built-in localisation to be able to show for example “1:35 PM” on the English version while Polish says “13:35”. I also had to remember to include weekday, so that it's clearer if someone is a day ahead or behind you. One nice extra touch is that since FontAwesome has multiple “globe” icons, each focusing on a different continent, I could even make the icon dynamic 😉
Different use cases might require different solutions, but if yours is similar to ours – relatively low accuracy by design, hard to abuse, easy to localise, etc. – keep in mind that timezones could be super helpful.
IANA timezone encodes so much information: if you know it, you know both approximately where someone is and also what time is it there. Pretty cool, huh?
Turns out there are still problems with the IANA timezones database. Kind of expectedly, huh? I knew life can't be too easy, there's definitely gonna be controversies around city names, I'm just excpecting that there would be fewer than with countries.
So the first one we found is this: for the capital of Ukraine IANA uses… the Russian spelling 🤦 (
Kiev). We've replaced it with the more appropriate one: Kyiv.