Count How Many Days Until Halloween with Javascript Date Objects

I’ve had fun making updates to my Halloweenti.me project this October.

I made the decision not to make it an open source or Hacktoberfest eligible project this year. But, I’ve enjoyed making upgrades and trying new things.

When I refreshed this project in early October, I knew that my current logic did not account for if Halloween had already passed for that calendar year. In the afternoon of the spookiest day of the year, I’ve found a solution that works!

Here’s how I did it.

What is the Problem?

I’ve previously written about date objects in Javascript, but as a refresher, here’s the code that I started with.

const now = new Date()
const halloween = new Date(`October 31, ${now.getFullYear()} 00:00:00`)
const timeUntil = halloween.getTime() - now.getTime()
const daysUntil = Math.abs(Math.ceil(timeUntil / (1000 * 60 * 60 * 24)))

Here’s a line by line breakdown of what’s happening.

  1. A new date object is being created based off the current date and time.
  2. A second date object is created with the value of October 31st, of the current year (which is referenced from the first date object).
  3. The time of the first object, is subtracted from the time of the second object. The result is is milliseconds.
  4. The milliseconds from the above line is converted into days by
    1. Dividing it by 1000 * 60 * 60 * 24.
    2. Rounding the result down to the nearest integer
    3. Returning the absolute value (meaning, removing the negative, if the result if a negative number)

If today’s date was October 1st, 2020, this is what each line would return.

const now = new Date() // Thu Oct 01 2020 00:00:00 GMT-0400 (Eastern Daylight Time)
const halloween = new Date(`October 31, ${now.getFullYear()} 00:00:00`) // Sat Oct 31 2020 00:00:00 GMT-0400 (Eastern Daylight Time)
const timeUntil = halloween.getTime() - now.getTime() // 2592000000
const daysUntil = Math.abs(Math.ceil(timeUntil / (1000 * 60 * 60 * 24))) // 30

Counting on our fingers, from the 1st of October to the 31st, 30 days to Halloween would be correct.

Where it gets weird is when Halloween has passed for this calendar year.

Let’s pretend it’s the day after Halloween (November 1st, 2020).

const now = new Date() // Sun Nov 01 2020 00:00:00 GMT-0400 (Eastern Daylight Time)
const halloween = new Date(`October 31, ${now.getFullYear()} 00:00:00`) // Sat Oct 31 2020 00:00:00 GMT-0400 (Eastern Daylight Time)
const timeUntil = halloween.getTime() - now.getTime() // -86400000
const daysUntil = Math.abs(Math.ceil(timeUntil / (1000 * 60 * 60 * 24))) // 1

Our daysUntil variable returns 1, as in “There is 1 day until Halloween” which is not right. Better wording would be “It’s been 1 day since Halloween” but not what I am going for. This is meant to be countdown to Halloween, so I needed to find another way.

Solution

I tried reworking the timeUntil and daysUntil functions, when really I needed to think about the relation between the now date object and the halloween date object.

If I was always referencing the current year to create the halloween date object it would never look ahead to next year. So, I needed to increment the year that I pass into the date object by 1 (as in, next year) only if Halloween had already happened in this calendar year.

How can I do that?

Well, after Halloween there are only two months left in the calendar year. So, if the current month—the month in the now date object—was greater than the month that Halloween falls in, create a halloween object using next calendar year.

Date objects have a built in getMonth() function, which return an integer. Since the months of the year are zero indexed, January would return a 0, February would return 1 and October would return 9.

If it’s November or December, the result of getMonth() on the now object would be 10 and 11 respectively.

Knowing that, I can add some conditional logic before the halloween object is created.

...
const now = new Date()
let year = now.getFullYear()

if (now.getMonth() > 9) { year += 1 }

const halloween = new Date(`October 31, ${year} 00:00:00`)
...

Let’s pretend it’s November 1st again. Here’s what our updated code would return.

const now = new Date(`November 1, 2020, 00:00:00`) // Sun Nov 01 2020 00:00:00 GMT-0400 (Eastern Daylight Time)
let year = now.getFullYear() // 2020
if (now.getMonth() > 9) { year += 1 }
const halloween = new Date(`October 31, ${year} 00:00:00`) // Sun Oct 31 2021 00:00:00 GMT-0400 (Eastern Daylight Time)
const timeUntil = halloween.getTime() - now.getTime() // 31449600000
const daysUntil = Math.abs(Math.ceil(timeUntil / (1000 * 60 * 60 * 24))) // 364


364 days until next Halloween is right! I can double check that my logic works by pretending it’s the the first of the year.

const now = new Date(`January 1, 2021, 00:00:00`) // Fri Jan 01 2021 00:00:00 GMT-0500 (Eastern Standard Time)
let year = now.getFullYear() // 2021
if (now.getMonth() > 9) { year += 1 }
const halloween = new Date(`October 31, ${year} 00:00:00`) // Sun Oct 31 2021 00:00:00 GMT-0400 (Eastern Daylight Time)
const timeUntil = halloween.getTime() - now.getTime() // 26175600000
const daysUntil = Math.abs(Math.ceil(timeUntil / (1000 * 60 * 60 * 24))) // 303

A Google search of how many days between January 1 2021 and October 31 2021. confirms this too.

Google search result showing 303 days between January 1st and October 31st 2021

The Finished Product

Ahhhhh! The working code for the Halloween countdown can be seen at Halloweenti.me.

As of right now, October 31st, 2020, you’ll see a gentle reminder to have fun and celebrate safely.

Halloweenti.me website with the text “Today is Halloween! Eat, drink and be scary!”

With the value of the current date object (now) in relation to Halloween, the text displayed on the webpage is updated. It will reflect how many days until Halloween and specific messaging if Halloween is today or tomorrow.

Resources

Leave a comment

Leave a Reply

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