Is it hotter or colder this year?

Where I live could generously be called "warm", but is usually closer to the surface of the sun, especially in late summer. That’s why when the weather is not oppressively hot, I try my best to enjoy it. We’re mid-May now and honestly, this spring has been… pleasant. Suspiciously pleasant but I’ll take what I can get.

The last few weeks I’ve been telling myself that the weather must be a good bit cooler than last year, and I finally decided to do something about it. I worked with Claude and created a little web app that:

  • Lets you enter a free form address and then use Geocoding to convert it to a proper longitude and latitude. This is a super simple geocoding API with a generous free tier. Do note though it’s North America only.
  • Uses the Pirate Weather API to get historical weather information. Date wise, I’m using this week, and then the same days over the previous four days.

As I mentioned, I worked with Claude on this and let it design the layout and write the code initially. I was kinda impressed by one part – the mapWithConcurrency function that lets you pass an array of async function with a desired max number to run at once. It handles doing the batching and returning the final result. That makes the calls for the weather data a bit more gentle on the provider.

However – I noticed it was taking a long time to finish. In theory, I’m doing 7 times 5 (this week plus four previous years) of calls which is 35 which doesn’t seem like a lot, but I did some digging. Claude had used an endpoint that was a bit old. Doing some more research I switched to the proper endpoint… which didn’t support CORS.

Oh no!

Oh – actually – I just moved to this to val.town and built a quick server side proxy. It takes in the same arguments that’s send to my client side code (lat, lng, and a timestamp), and passes it to the historical Pirate Weather endpoint. So here’s the frontend code – again – this is being driven by a concurrency function:

async function fetchDayTemperatures(lat, lng, unixSeconds) {   let req = await fetch(PIRATE_WEATHER_API_BASE, {     method: "POST",     body: JSON.stringify({       lat,       lng,       unixSeconds,     }),   });   return await req.json(); } 

And here’s the backend code:

export default async function (req: Request): Promise<Response> {   const body = await req.json();   const key = Deno.env.get("PIRATE");    const url = new URL(     `https://timemachine.pirateweather.net/forecast/$ {key}/$ {body.lat},$ {body.lng},$ {body.unixSeconds}`,   );   url.searchParams.set("units", "us");   url.searchParams.set("exclude", "minutely,hourly,alerts,flags");    const response = await fetch(url);   const payload = await response.json();    if (!response.ok) {     throw new Error(payload.error || "Weather lookup failed.");   }    const day = payload.daily?.data?.[0];   if (!day) {     throw new Error("Weather data did not include a daily summary.");   }    return Response.json({     timezone: payload.timezone,     high: day.temperatureMax,     low: day.temperatureMin,   }); } 

I barely modified this from the original client side code – only switching to an environment variable for the API (their API is free, but I might as well) and returning a proper Response object.

Here’s a screenshot of it in action:

Screenshot

You can try this yourself here: https://weathercomparison.val.run/. If you want to see the code, and possibly fork the val, you can do so here: https://www.val.town/x/raymondcamden/weather-comparison

So, was it cooler?

No. I was wrong. Last year was cooler than this year, but the three years before that were all higher, with 2022 being pure hell. I remember that year seeing the city working on a road that had literally buckled because of heat.

Photo by Peter Albanese on Unsplash

Raymond Camden

Posted in: JavaScript

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.