Dealing with the Javascript Date object on iOS

Originally published on 24 March, 2021 by Jacob Stordahl

Recently I was working with a REST API from a SaaS company whos product is tailored for gyms & fitness centers. I've been building a new website for a gym that includes a custom serverless API which provides authenticated requests to the REST API. The page I was working on at the time included a custom calendar listing all of the available classes for the CURRENT week beginning on Monday. The functions needed to accomplish this calendar include calculating the Monday of the current week, calculating the last day of the week, and then filtering within the template by calculating the day of the week for a given event timestamp.

Today I want to quickly explain a bug I experienced during this project & provide a solution. To provide context, all of the issues I experienced were in relation to the Javascript Date object. If you've worked with dates in Javascript before, you know they are less than friendly. Most dates are stored in a database as a timestamp sting value. This is very useful when you want to simply display the timestamp, but inorder to do any real work with this date, we need to create a date object. We do so like this

const timestamp = '2021-03-23 09:30:00.000000'
const dateObj = new Date(timestamp)

We now have a variable 'dateObj' that contains our date object. This allows us to use many handy functions provided by Javascript like the one I was trying to use, getDay(). getDay takes a date object and returns an integer in referance to the day of the week that date object falls on, where Sunday is 0 & Saturday is 6. The bug I experienced was due to the use of the date object to filter in a Svelte template.

{#each classes as c}
	{#if new Date(c.eventTimestamp).getDay() === 1}
		<!-- template -->
	{/if}
{/each}

Here, we're iterating over an array of classes using a Svelte {#each} block. Each class contains an eventTimestamp property which we can use to create a Date object. We can then return only events where getDay() is equal to one (Monday), and repeat for each day of the week. However, after pushing this code to staging, I noticed that none of the templates within these blocks were rendering on any iOS browser. No console errors, no server errors. Needless to say, I was stumped but I had a hunch that this bug was being cause by this conditional rendering, where the conditions contain a Date object.

To illustrate this point, here's a screenshot of my browser console while I was debugging.

Screenshot of JS console

With this image we can see three different Date objects being created, each with a slight adjustment to the timestamp argument. The first timestamp is what I was recieving from the REST API mentioned earlier (yyyy-mm-dd hr:min:sec.mil). You'll see that when we call this Date object in the console we get Invalid Date. The second timestamp is edited to replace the dashes with forward slashes & we see the same error. The last Date object goes one step furter to strip the .mil value off the end which then finally returns a valid Date object, hooray!

I have never worked with Dates in Javascript this extensively and had never heard about iOS being this particular about the shape of a Date objects timestamp. To fix the template above, I simply added replace & split methods on the timestamp before creating the Date object.

<script>
	const regex = /-/g
</script>

{#each classes as c}
	{#if new Date(c.eventTimestamp.replace(regex, '/').split('.')[0]).getDay() === 1}
		<!-- template -->
	{/if}
{/each}

I hope this article can eliminate some frustration if, like me, you're new to Dates in JS and run into this bug.

© 2021 Jacob Stordahl | built with Steel