Explore global weather conditions with local time conversion and map integration
My weather app is called WeatherNOW+
In this post, I discuss the thought processes behind the development process.
Any questions, leave a comment or email me.
First, we need weather data!
We can’t have a weather app without weather data to feed into it.
There are lots of free and paid third-party APIs out there and my filters were simple – I wanted free data without having to share my credit card details to get it.
Free data comes with limitations, but that’s okay because limitations inspire creativity!
I settled on the free weather API from openweathermap.com which provides eight pieces of weather information at three hourly intervals per day for five days. 40 datapoints in total.
This option allows 60 lookups a minute and locks out for a day if you exceed this. Since this is a personal project and I’m not expecting a lot of traffic to my app, this limitation is an acceptable risk.
Bird’s-eye planning for the weather app
I want to allow users to search for weather at their current location and also worldwide by typing a location or by entering a postcode.
Also, I want to display five days of weather data as follows:
- The Current day will start from the current moment using the opening timestamp from the API data, and then display weather data for the next three 3-hour intervals.
- The Rest of the week will display weather data for the fixed times of 9am, midday, 6pm and 9pm. These timestamps are all conveniently provided in the API data results.
Finally, I want the weather app to be engaging as well as useful. I’m not sure how to achieve this but I trust an idea will come to me when I start building.
It’s best practice to store API keys server-side so they’re not readable from the front-end.
But mine is just weather data from a service that’s already rate-limited, secure and available to anyone for free if they want it.
Nobody can do anything nefarious with my key so in this instance, I’m happy to leave it unhidden in my front-end code.
So, on with the build.
Hurdle #1 – UTC Timestamps
I quickly discover that the timestamps in the API data are not that convenient after all.
When I call up my desired datapoints of 9am, midday, 6pm and 9pm, they work as expected for any location in the UK. It’s only when I look up Sydney, Australia that I notice the weather is showing the night sky for these daytime timestamps. That’s not good.
OpenWeatherMap timestamps are provided in Coordinated Universal Time (UTC) which is a standard timekeeping system used to eliminate time zones, daylight saving, leap years and ensure uniform time representation across the globe.
Basically, UTC counts the seconds that have elapsed since the starting point known as the “Unix epoch” which is 00:00:00 on January 1, 1970 GMT.
Every UTC timestamp is the count of the number of seconds from the Unix epoch up to the requested “clock” time.
UTC time doesn’t care about timezones
Every place in the world has the same number of seconds between Unix epoch and “now” or whatever time we’re interested in (eg 9am, midday, 6pm and 9pm in my case.)
Remember, UTC timestamps are based on a GMT foundation and if two people are pulling this data at the exact same moment, one from London, one from Sydney, they’ll both get a dataset with the same exact UTC numbers on it even though they’re both sitting in different timezones.
The reading against the 9am label makes sense for Mr London since he’s at GMT already but Mr Sydney is shown an evening weather display because 9am GMT is 7pm in Sydney.
In fact, if Mr London does a search for Sydney, he also sees evening data for the 9am UTC timestamp.
Why is this? Let’s break it down step by step:
- Mr. London performs a search for Sydney on the weather app
- The weather app sends a request to OpenWeatherMap API, specifying Sydney as the location to retrieve weather data
- OpenWeatherMap API responds with weather data, including UTC timestamps for different weather readings (e.g., 9:00 AM, 12:00 PM, 6:00 PM, 9:00 PM)
- The weather app displays the weather data to Mr. London
Here’s why Mr. London sees evening data for the 9:00 AM slot:
- The UTC timestamp “9:00 AM” represents 9:00 AM GMT/UTC time.
- In Sydney, at that moment, it’s 7:00 PM local time because Sydney is 10 hours ahead of GMT/UTC.
- Since there is no timezone conversion being done in the app, the weather data is displayed as it is, and Mr. London sees the evening data against the 9:00 AM label because the UTC timestamp corresponds to 7:00 PM in Sydney.
This makes no sense to the user. And it makes no sense to me – I want to show daytime data no matter which city is being searched.
I obviously need to handle time zone conversion in my weather app.
Accounting for dataset limitations
However, the problem is that the free data from OpenWeatherMap only returns eight timestamps per day. Such a small number of datapoints means it’s unlikely the converted time will return my desired timeslots of 9:00, 12:00, 18:00, 21:00 in the city I’m searching.
So I come up with a compromise.
I call the data for my desired city and convert all forty timestamps into the local timezone of that city, accounting for daylight saving too.
Then I go through it and return my desired timeslots if they exist, otherwise I return the closest time that’s within 90 minutes of it. 90 seems like a good number to catch all the timezone variances but I can change it if I need to.
Now the data makes sense.
Now we can call up the weather for Sydney and see daytime weather. The timeslots aren’t 9:00, 12:00, 18:00, 21:00 anymore because these timeslots weren’t available in the converted data. Instead, the weather app returns the closest matches, in this instance, 10:00, 13:00, 19:00 and 22:00.
The weather app now works as expected for every city in the world:
- Current day returns the weather at the current moment plus the next three intervals in my dataset.
- Rest of the week returns four slots of data per day in the local timezone as close to 9:00, 12:00, 18:00, 21:00 as the API data allows.
Hurdle #2 – Unexpected Placenames
As users type into the search box, a real-time lookup populates the dropdown with place names that match the input. The user can then click on their desired placename.
These place names come directly from the OpenWeatherMap geographical database and sometimes give confusing results.
In the screenshots below, you can see three lots of Paris, Ile-de-France, FR. Canberra has an undefined state and there are two Delhi’s in New York which doesn’t feel right.
I examine the data carefully and discover these are all database anomalies.
- Paris has been entered into the database multiple times with different latitudes and longitudes that are mere streets away from each other
- The two New York Delhi’s both have the same lat and lon but their names have been entered differently.
- Canberra doesn’t have an entry in its state field. Interestingly, London returns England in its state field even though England is not a state.
If I had it my way, I’d clean up that database but I don’t have any control over the data returned by the API and, at this point, I don’t really want to search for another weather API that returns cleaner data. Maybe the paid version would provide clean data? I don’t know, too many uncertainties.
Luckily, what I can control is the user experience and in doing so, I’ve thought of a way to make my weather app fun and engaging at the same time!
I’ll add map integration so people can see what they’re looking up and perhaps use these anomalies to discover new places.
Hurdle #3 – Map integration
The GoogleMaps API is free to use but they want a credit card before they let you in. I’m averse to that so I decide to embed the map in an iframe.
When a user calls up a location, the latitude and longitude are passed to the GoogleMaps embed and I have a seamless user experience – the map updates itself to whichever location the user is searching, whether it be by placename or postcode.
It all works exceedingly well in Chrome and Opera, but long story short, adblocker extensions in Firefox block the iframe from communicating with GoogleMaps and prevent my weather app from working.
The moral of the story here is to test along in Chrome, Opera and Firefox during build so there are no unpleasant surprises just as you’re ready to deploy. Later, you might find that other browsers need tweaks too, but you want these tweaks to be cosmetic tweaks, not functionality tweaks.
So, I’m on the hunt for another map solution.
Mapbox looks good but they want a credit card too so that’s out.
I go for the open source OpenStreetMap and, having learned my lesson, don’t use an iframe this time. Instead, I integrate it using the no-credit-card-required Leaflet library and am glad to report that Firefox approves.
Now a user can look up Dubai, find it in Uganda and ease their confusion by seeing where it is on the map.
GoogleMaps did have a more engaging advantage in that they have StreetView and an inbuilt “view larger map” link that opens up in a new window. Never mind. If I develop this app further, maybe I’ll dig the credit card out of my pocket.
My Wednesday Genius site runs on WordPress but I’m hosting the weather app on a subdomain outside WordPress. I want it to blend in with the main site so I create a header and footer in line with the existing branding.
A logo for my weather app would be a nice touch too so I create one in Canva and position it in the header alongside the Wednesday Genius logo.
Finally, the app needs to work on mobiles, tablets and desktops so I add CSS customisation for the various breakpoints modifying the interface for various screen sizes.
There are a few things to do if I go on to develop this app further:
- Adjust some CSS. I’ve added breakpoints for mobile and tablets but the search criteria section could be better on some sizes of mobile landscape.
- Separate the front-end. It’s not ideal that my App ID key is visible so I’d separate that and keep it out of sight.
- Handle the postcode identification more robustly. It would be better to use a data validation library like Joi. Currently, I simply treat anything with a number in it as a postcode and ignore that there might be a city somewhere with a number in the name. If one doesn’t exist now, it certainly will in the dystopian 15-minute city type of future they’re all talking about on Twitter where we’re herded into zones called Manchester1, Manchester2 etc.
- Add a “…loading” placeholder on the map. When a user enters the WeatherNOW+ site, there’s occasionally just a big empty space where the map should be. GoogleMaps doesn’t have this problem but OpenStreetMap seems to need a few seconds to hook up sometimes. A loading placeholder would improve the user experience.
- Add two-way map connectivity. Currently we search for a location and it displays on the map. I think it would be nice to show the weather by clicking on the map and showing the weather for where the user clicks.
So, this is a top level of how I developed my weather app. If you’d like to see the code, it’s here on my GitHub.
Share on Pinterest: