Rules for traveling through time

Rules for traveling through time

js Dates and coding with time

I love time travel stories. Love them. Back to the Future was the first time I really thought about how movement through time works... fictionally.... or not? And when the Booster Gold comic book came out from DC Comics it easily became one of my favorite titles because of how it dealt with time. What's this have to do with coding? Nothing. Now that I've primed the pump, coding to deal with timezones is terrible. Don't do it. It's not as much fun as Doc Brown made you think it was, and he was an eccentric genius anyway.

At my job, we work with chats and scheduling across time zones. This is challenging enough even before you consider Daylight Savings and anomaly timezones like Adelaide, Australia which is offset by an additional 30 minutes! Or should that be "by thirty fewer minutes?" Local formatting? Oh right. In Europe dates aren't written "Month Date, Year," they write "Year Month Date" from the biggest unit of time to smallest. So we should ensure the date is written according to the conventions of the user's location. Are you rolling your eyes yet? Maybe crying a little? I'm writing some tips to take some sting out of working with time.

Get thee to the library!

First and foremost: Don't try to roll the logic yourself! Use a library! Moment.js and date-fns already exist and do a lot of the heavy lifting for you. You want to add a certain amount of days to a date to make sure your 90-day warranty ends on the right date? These libraries have something for that. Dealing with timezones? So long as you have the location of the origin and user, you can figure out the time difference and use other libraries.

You could try to do it all yourself. Really, you could. But you're also pretty busy and need to get other parts of your project done. I recommend using your energy and focus on the project itself instead of dogfooding a library to handle time. Also, a word of the wise: moment.js is deprecated, so you might want to find another library or suppress all the deprecation warnings in your project.

You're looking at now, sir

So that should be it. Some library does all the data manipulations and you get to say, "boo, the end" and knock off early. Well, not quite. Javascript coders, tell me what happens when we instantiate a Date like this way:

const currentTime = new Date(Date.now())

What happens when currentTime is defined this way?

  1. Date.now() will return the number of milliseconds since January 1, 1970, Universal Time Coordinated (UTC). That's not too problematic, but it is a Number, not a Date.

// Universal truths

What's UTC? It's a time standard we base civil times zones from, not an actual timezone. Though people often interchange it with Greenwich Mean Time (GMT, an actual timezone), they aren't really the same thing. UTC uses International Atomic Time, which allows seconds to be a consistent quantity of time, whereas timezones (and sundials) are rooted in the time it takes for the Earth to rotate and revolve around the sun. You're probably thinking, like I did, "uh-huh. So?" Although I believe in physics, I didn't stop and think before about how any mass will eventually slow down. The Earth's rotation has been slowing, and that's something, even as software engineers, we end up learning about and having to account for when dealing with time.

new Date() will create a Date for the timezone you are in when you instantiate. I'm going to repeat this because I think it's an important point, "for the timezone you are in."

If you are storing data in more than one timezone, you have to do a few other computations to sync time across timezones. Instead, I like to create currentTime this way:

const currentTime = new Date(Date.now()) .toISOString().

What's that do? .toISOString() returns a formatted string for the date in UTC. There you go, you're in UTC with a date you instantiated somewhere else.

It's good to have consistent practices in how you keep your time data. All times, IMO, should be stored in UTC. Really, just pick one timezone to store all your data and be consistent. Why? It's a bit cleaner.

The backend stores the data (all in respect to the same timezone) and sends it to the user. On the front end, the time conversion should be done based on the user's location. It saves on cognitive load for the user, who may not feel like converting from their home time zone to the timezone they are in (remember when we could travel?).

Now, let's say the user inputted their location when they signed up for your app. What happens when they are out of town? If you're relying on the home address of the user to define timezone then this can be a problem. Instead, you can find the timezone of the user device and then convert time. Here's how:

const deviceTZ = () => Intl.DateTimeFormat().resolvedOptions().timeZone

That will give you the actual timezone name, "America/Los_Angeles" for example.

Testing your time and patience

Yes, you should write tests for the data conversions. Testing is how we show verisimilitude, that our code does what we say it's supposed to, and what edge cases we are defensive against. I know, testing isn't always fun to write. For me it makes me wonder if I really thought through what I wrote and how I understand what else is going on. If I'm asking myself that, I probably don't understand that well. And that's an advantage of writing tests.

I wrote tests for time function that used date-fns to help convert a Date in UTC to a user's timezone. No sweat, right? date-fns has their own tests and it shouldn't have been a big deal. Then the tests failed. It really shouldn't have been an issue. The only thing I wrote, really, was getting the user timezone. Seemed to work in my browser console. The problem was how I wrote my expected return in the tests. The server running the tests was in a different timezone, so I had to hardcode the outcome to be an ISO string. It's better to be empirical and hardcode what the expected outcome should be.

In school, one teacher had said that their favorite part about programming was how much you get to learn about the world. Had they not worked in tech, they wouldn't know as much as they do now about time zones and the exceptions around the world to account for. I have a co-worker who specializes in Machine Learning, and they're learning a lot about personality psychology for the product we're creating. I even have a former classmate that works for a pet food company (yup, in tech) and she, too, is learning more than just technology. Time is challenging, but it's fascinating to learn about as a side effect of being a programmer.