In the Programming by Stealth podcast I do with Bart Busschots, we had an assignment a while back to create a web app that would show the time in two different cities of their choice.
I took the assignment up a notch and added a little slider you could drag to change the time in both cities at the same time. The problem this solves is how to know what time it will be in the future at two different places. Let’s say you’re trying to tell someone what time the next Apple event will be in their timezone at this future time, this would be a perfect tool to solve that problem. I enhanced my app to not just show the time, but the date as well.
Bart gave us an additional challenge and asked us to see if we could create a method for someone using our clock app to copy the times into a URL that could be sent to someone else. The idea was that the recipient could simply click the link they were sent and see the two cities with the same times in them as when the URL was sent. This sounded like a great enhancement to my Time Shifting Clock. Instead of having to write out an elaborate email with the explanation of times chosen, I could just send people a link. You can see how cool it is at podfeet.com/webapps/time-shifter-clock
I told you all about my amazing clock when I finished it, regaling you with the different technologies I used and the technical decisions I made during the design.
But as soon as I was done and officially released version 1.0, I knew that I wanted my little app to do more. The problem I wanted to solve was how to allow the user to choose more than two cities. Dr. Garry, our resident memory psychologist from New Zealand, loves my clock app because she is often trying to set up meetings with people in different time zones, but she’s often dealing with many people in multiple cities, not just two.
The first step was to figure out how to add a button allowing the user to add another city, and I accomplished that part of the code pretty quickly. I had to pick a default city for all of the additional clocks, and since Maryanne had already complained that the first two were Los Angeles and Dublin, I made all subsequent clocks show the time for Auckland, New Zealand.
The hard part has been working on modifying the URL that gets copied and sent to someone. Without the pressure of a due date for an assignment, I must admit that I haven’t worked very consistently on the app. I didn’t realize how long I’d been so occasionally doodling with it until I looked up the release date of version 1.0 and it was September of 2019! Hey, 2020 was hard, ok?
That’s a Long URL
The URL that I create then contains the name of the city chosen along with the time and date selected. The city name actually includes the region too, so it would be Europe/Dublin for example. I also have a field on the screen that says, “The time in Europe/Dublin becomes:” that needs to be in the URL too so it can be typed on screen for the recipient. Bart also told us we had to include a toggle for the user to view the time in either 12 or 24-hour format. I figured since I was letting the user send all the other info, why not let them send the time in the format they’d chosen.
I had all of this working in version 1.0 of my Time Shifter Clock app, but my method created a really long URL! I just counted, and the URL is 260 characters long to represent the time in Los Angeles and Dublin!
I was willing to live with that for version 1.0, but imagine what this URL would look like if Maryanne invited 5 people to her grant review meeting? It would be paragraphs long and no one would click it; they would assume it was spam.
When Bart was working on his clock app along with the rest of the class, he didn’t put the time of both cities in the URL. Instead, he put the absolute time chosen in Coordinated Universal Time, also known as UTC. Both clocks on the page could have their time calculated relative to UTC by using the time offset that moment.js can give us. Dorothy did her clock this way too.
I knew that using UTC would dramatically simplify my URL. I didn’t copy their code, and in fact didn’t even look at how they did it. I used the documentation to figure it out how to get moment.js to do the time offset for me. I also figured out how to put the line, “Time in Dublin becomes:” into the clocks without having to repeat it in the URL too. The URL would then simply contain the time in UTC, and then the 2+ city names. It would be ever so much more readable because you’d see that most of it was just a listing of the cities.
I wrote a little side program to prove to myself that given time in UTC, I could convert it back to any city I wanted so that was all worked out.
Regular Expressions are the Answer
Once I knew that I could conquer the time math with UTC, I figured out how to create a button for the user to add more cities, change the defaults, and to get the slider to shift all of the times. The button to copy the URL worked perfectly to copy the time in UTC and the names of all the cities. I was cooking with gas now.
But there was one big problem to be solved. When the recipient clicks the URL they’ve been sent, I had to figure out how to pull the city names and UTC time out of the URL and shove it back into the clocks. I had done this before with two clocks, but since I knew there were only two, I had hard-wired the variable names of the clocks into my code. I had named them sc1 and sc2.
Now I had to have my code check the URL and find any number of clocks. Maryanne might invite 28 people to hear her fascinating grant proposal, right? So I’m looking at this URL and trying to figure out how do I find matches for the strings when I don’t know how many there will be?
Great Scott! This is a perfect time for Regular Expressions! This was too good to be true that two weeks in a row I would get to use Regex.
Taming the Terminal Book
I got into my thinking chair (the one that won’t let me touch a keyboard) and pulled out my trusty physical copy of the Taming the Terminal book again. I didn’t know exactly what Regular Expression I was looking for so I just opened the book to Chapter 17 and started to read.
In Bart’s explanation of where Regular Expressions can help, he says:
The key point is that if you can describe a pattern as a series of elements that follow one after the other, then you should be able to write a regular expression to represent that pattern.
I certainly can describe a pattern for finding the city names:
The city names will be preceded by the letters “sc” followed by one or more digits followed by an equals sign, and then inside quotes will be the region/city name. Clearly, a Regular Expression was called for.
Just a few paragraphs in, I read the quote Bart loves to say about Regular Expressions:
The fact that many programmers don’t understand the limitations of regular expressions has led to the incorrect maxim that if you have a problem and try to solve it with regular expressions you then have two problems, your original problem, and a regular expression.
I knew it was important to relearn it properly or I would end up right where Bart said I’d be.
I kept reading and studying, and eventually had a list of different approaches to the problem. I let myself get out of the thinking chair and went to regex101.com to start testing out some of my Regular Expression ideas on a sample URL with three cities.
I did not succeed. I got frustrated and finally decided to try the googles for some help with the Regular Expressions.
Regular Expressions Are Not the Solution
Now here’s the funny part. Regular Expressions are NOT the solution to this problem after all. I tried all kinds of search terms for how I was trying to make a match in Regular Expressions, and finally, I happened to include the term “URL” in my search on Google.
Returns an iterator allowing iteration through all key/value pairs contained in this object.
It was exactly what I needed. I didn’t know how many cities would be in the URL so I needed to iterate through it to find them all. And this method already knew the pattern I was looking for because all URLs have this same pattern.
But here’s the funny part. When I looked back through my Version 1 code, I had used URLSearchParams to find information in my URL! But this is not a failure on my part, it’s a sign that I’m a real developer. Think about the progression of events here.
I knew a tool that I thought could solve my problem, so I studied the documentation to see if it was the correct tool. Instead of persisting at using a wrench to drive in a nail, I kept digging until I found the right tool. I suppose it would have been less embarrassing if I hadn’t found the tool in the bottom of my own toolbox, but even at that, I studied the documentation and discovered something new it could do that I didn’t know before.
From the very beginning, Bart has stressed that he’s teaching us to program, not teaching us a specific language. He’s also continuously stressed the importance of learning to read the documentation. He’s stressed that he looks things up all day long himself. This method of teaching means none of us feel stupid when we don’t know something. We feel mighty when we solve a problem, even if it’s by discovering something we already knew.
I haven’t got my URL query working just yet but I know I’ll solve this. A few years ago, I would bang my head against the wall of programming with no idea how to proceed. Now I inch along, fixing little things, making big discoveries, but I seem to always move forward. I’m learning and I’m having fun and I feel powerful.
It doesn’t get better than that, does it?