You’ve probably heard me talk about my amazing web app, Time Shifter Clock that allows you to figure out what time it will be in multiple cities at once in order to schedule times to talk to people around the globe.
The Problem to be Solved
Last week I had a chance to see how it dealt with the US leaving Daylight Saving Time. Most of the year, Los Angeles and Dublin are 8 hours apart, but because the US is idiotic, we get on and off Daylight Saving Time at different times than the rest of the globe. That means Bart and I are 8 hours apart most of the year, then briefly for a week or two we’re 7 hours apart, then we go back to 8 hours apart, and then back to 7 hours apart for a couple of weeks. It’s a hot mess.
The night before the US got off Daylight Saving Time (November 6th), Dublin and LA were 7 hours apart according to my clock, which was correct. To test that it was working properly, I used the slider to shift time forward to November 7th when it should have showed us 8 hours apart, but sadly it did not. I was very disappointed that there was a bug I’d have to fix.
I spent some quality time with my code and figured out my mistake. I take the current time in the first city (which defaults to LA because it’s my app) and I convert that to universal time, aka UTC. It’s a bit arrogant that we think we’re in charge of declaring what the time is for the universe, but I digress.
After I change it to UTC, I round it down to the nearest hour, and then I convert any cities chosen to their offset from UTC, and then I add the time chosen with the slider to move each city forward in time. My mistake is that I should add the slider value to the UTC time before I convert it to the different cities’ times.
Once I realized my error, it was time to code the fix. I use VSCode as my code editor, and I’ve been experimenting with a plugin called GitHub Copilot that makes suggestions for what it thinks you might want to write. It’s pretty helpful to me because I often know what I want to do, but I’m unsure of the syntax. If I get a running start at a function, GitHub Copilot often will write the rest of it for me.
In this case, GitHub Copilot came through like a champ. It wrote, all by itself (after I had set up the previous line):
let UTCrdtShifted = moment(UTCrdt).add(timeShiftedVal, "h");
That may look and sound like gibberish to you but it was exactly what I needed. It says to take my rounded down time in UTC and add the value from the time shifter to create a new reference point in UTC.
Testing the Fix
While I was fairly certain that I had found the root cause of the problem, I wasn’t certain that I had implemented the fix correctly. I needed to test my fix, but there was a big problem. Time Shifter Clock only lets you shift forward 7 days, so how can I test this solution without waiting till the next Daylight Saving Time change?
I told Bart that I was pretty sure I’d fixed the bug but I was sad I couldn’t test it. He suggested that I change the date and time on my Mac to right before the previous (or next) Daylight Saving Time change and then test it.
Two things about that idea. First of all, I had no idea that Time Shifter Clock was using the time of the user’s computer to do its calculations! I thought my code was reaching out to some Time Lord to know what time it was! I thought the moment.js library I was using was in charge of the actual time.
I’m really glad I had this bug because learning you have a fundamental misunderstanding in how your code functions is a very good thing. I mean, of course it would be better if you didn’t have a fundamental misunderstanding, but if you do have one, you really want to learn about it!
Now to Bart’s idea of changing the date/time on my Mac. I was trepidatious about this suggestion because bugs in a system can be easily introduced by an incorrect system clock. In my case I know for sure that “spooky action at a distance” would occur, because I have a lot of Hazel rules that are time-based. For example, when my recorded audio files are over 2 weeks old, Hazel whisks them over to my Synology NAS for cold storage and deletes them from my internal drive.
Even if I turned off Hazel for the duration of my testing, I was still worried about what else I might have going on that was time-based that I just didn’t remember. I induce enough weirdness on my computers all by myself, I don’t need to invite spooky action at a distance into my house!
When I explained my trepidation, Bart made an even better suggestion. Why not do it in a virtual machine? I thought that sounded like great fun. I could install any flavor of Linux, change the system date within the OS, and do my experiments all without breaking anything on my Mac.
Virtual machine software such as Parallels and VMware Fusion are highly-capable and awesome pieces of software for people who need to consistently run another operating system. They’re not inexpensive, so for a tinkerer like me with needs a couple times a year, they’re not the right answer.
A hundred or so years ago Sun Microsystems came out with an open source virtual machine app called VirtualBox and when Oracle bought out Sun (and the stock I owned went to zero), they kept VirtualBox going. I have used it in the past so I downloaded it on my M1 Mac. While it was downloading, I also downloaded the Arm version of the Linux distribution CentOS Stream.
I expected that Ubuntu would work and would be easier, but what fun would that be? I wanted to try something more challenging. When you download a disk image for an operating system like Linux, it’s called an ISO, which makes it look like an old-fashioned CD to the installer software.
Unfortunately, it looks like Oracle is no longer a good steward for VirtualBox, because macOS Monterey refused to install it, saying
The Installer encountered an error that caused the installation to fail. Contact the software manufacturer for assistance.
VMs on the Synology
My next idea, since I didn’t want to pay for the commercial virtual machine apps, was to see if I could install Linux into a Docker container on my Synology NAS. I’m always looking for excuses to justify the cost of the Synology so this was a perfect opportunity.
I’m not an expert on Docker containers, but they’re essentially wholly-encapsulated environments where if you break anything, you just throw away the Docker container and start over. This is one of the reasons I love playing with software – if you break it you can start over.
On the Synology, I already have Docker installed, so I just needed to find a Docker container for Linux. I easily found one for Ubuntu and installed it. I had no problems at this point but I could not figure out how to make the Ubuntu container “go”. There was no launch, no start, no go button at all. No way to point to a downloaded ISO image of Ubuntu or anything like that that I could find.
I’m sure there is a way to run it from within Docker, or there wouldn’t have been a container. If someone knows, let me know.
Virtual Machine Manager
When I went to the googles to try to figure out how to make my virtual machine inside a Docker container go, I discovered something delightful. Synology provides a tool called Virtual Machine Manager specifically for installing and running virtual machines.
I found a fantastic video by an Australian named Emilio Aguero explaining exactly how to configure the Virtual Machine Manager on a Synology NAS with Ubuntu server. I know at this point I should have just followed his instructions, but I already had the ISO for the ARM version of CentOS downloaded, so I used that instead.
I followed his instructions to upload it from my Mac to the Synology. If you’ve been paying close attention, you’ll understand why that failed. While the ARM version made sense when I was going to install it in Virtual Box on my ARM-based Mac, of course it won’t work on the X86-based Synology.
Still wanting to test out CentOS stream, I downloaded the X86 version. it started to install, but then it asked me a whole bunch of questions for which I did not know the answer. Time to bail on CentOS Stream and switch to Ubuntu. Maybe there’s a reason why so many people like it.
Once I went down the Ubuntu path using the Virtual Machine Manager on Synology, it was relatively clean sailing. I got it installed and spent a little time figuring out how to set the screen resolution in Linux so I could see what I was doing. Technically it all worked but for some reason it thought I had caps lock on when I didn’t, and I never did figure out how to fix that particular problem. I also must say that it is really, really slow. It was usable but I definitely wouldn’t want to use the Synology for any length of time as a host for my virtual machines.
Finally, Testing Time Shifter Clock
Now what was the point of this whole experiment? Other than getting a chance to play with my Synology and learn about new tools, I needed to test my Time Shifter Clock in an environment where I could mess with time on the local machine.
In order to test Time Shifter Clock, I wanted to set the clock back to Saturday November 6th, the day before the US came off of Daylight Saving Time. On that day, Dublin and Los Angeles should have been 7 hours apart. But if I slide the time shifter into Sunday morning, it should, at some point, start to show us as 8 hours apart once Daylight Saving Time has been abandoned in the US.
My testing needed to be on the unreleased version of my code, which is in GitHub, which in turn creates a web page for me automatically.
I set the clock on the virtual machine to 10pm on November 6th and then tried to open the GitHub web page for Time Shifter Clock. Boy howdy, GitHub did it not like that at all. GitHub knew the time on my system, and yet I was asking for something from the future. I thought that was really interesting. I suspect it had to do with their very tight authentication requirements, including using a time-based authentication code.
I figured out that if I went to the GitHub web page first (with the time set correctly on the virtual machine), I could then change the time and the web page would continue to function.
Now for the big test. The Daylight Saving Time change happens either at 1am or 2am depending on how you look at it. I moved the time shifter forward until it said 1am in Los Angeles and confirmed that Dublin was still 7 hours ahead, showing 8am. I nudged it forward a half hour and saw 1:30am and 8:30am. When I nudged it forward a half hour more, Dublin moved to 9am, but Los Angeles jumped back to 1am again, finally moving us to 8 hours apart. You can imagine my squeal of glee when I was able to verify that my web app was functioning perfectly now!
I put three screenshots in the show notes showing the progression, but I also made a little video showing the success of shifting time over a Daylight Saving Time change in one country with respect to another. I’ve said it before, but I’ll say it again, programming makes me feel like I have made FIRE!
One More Thing
I bet some of you out there have realized that I could have made a virtual machine in a much easier way. Just 5 months ago I told the story of how I used the free UTM virtual machine software to install Ubuntu on my M1 Mac mini. I totally forgot I had already solved this exact problem! I was searching for a fix for that pesky caps lock problem in my VM on the Synology when I stumbled across the instructions of how to install Ubuntu on UTM that I had followed back in June.
For completion sake, I had to install it again on my M1 MacBook Pro and it worked perfectly, and was a lot faster than running on the Synology. If I remembered just half of what I’ve done over the years, I’d be brilliant. Oh well, I had fun learning about Virtual Machine Manager on Synology and I had fun experimenting with the different versions of Linux.
In any case, I made fire and Time Shifter Clock is better than ever. I’ll be pushing a release of this new feature soon!