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

A Beginner’s Guide to Managing React State with Hooks

Managing state can be one of the more complex aspects of working with React as beginner.

What data should be managed by state versus props, which components need to access state and where state should live are all questions I ask myself when planning a new React project.

Redux is an alternative for managing state it may be a lot to add for a small or simple project.

While building an app that queries the Spotify API for an artist, based on the user input, it made sense to store that input in state. That input value could be passed to the API, referenced in the UI (“Showing results for: adele”) or elsewhere in the app.

I learned to set up state as an object (state = { key: value}) but did not know this only works in class components! And mine were set up as functional.

Yikes.

I did not want to make the conversion right away, so I did a quick Google search for an alternative. I landed on the useState React Hook and had to give it a try.

Implementation

Hooks are a somewhat mysterious aspect of React. I had not used one until now. Similar to other features in React like componentDidMount, Hooks are built-in, modular functions of React. That’s it!

To get started using the useState Hook, it needs to be imported into your React file.

import React, { useState } from 'react';

Define State

Once useState had been imported into your file, you can create and set state values. For my app, I want to store the input from a text field in state.

Here’s what setting that up looks like:

import React, { useState } from "react";

function App() {
  const [input, setInput] = useState("");
}

What useState does is it sets up a state variable and a function that will update that variable. In my case, the variable is named input and the function that updates input is called setInput. The empty string (“”) within useState is the default value for input.

From my understanding of the Using the State Hook docs, the state variable and it’s update function can be named anything. But, it makes sense to name them what they are/what they do, especially if there are multiple state variables.

Now, we’re ready to access and manipulate state within our app!

Reference State

Since state has been set up outside of a class, we do not need this.state to reference within our app. In the return() statement for App(), input is referenced as {input}.

Given the following example:

import React, { useState } from "react";

function App() {

  const [input, setInput] = useState("")

  // TODO: Write handleOnChange function

  return (
    <main className="App">
        <h1>Search for an artist</h1>

        <form>
            <input type="text" name="input" id="input" onChange={(e) => handleOnChange(e)} />
        </form>

        <h2>Showing results for: "{input}"</h2>
        
    </main>
  );

}

If the current value of the input was “adele”, the h2 tag would render Showing results for: "adele" to the page.

Update State

To update the input variable in state, we’ll use the setState variable we set up earlier.

In the code sample above, you see that the text input field has an onChange event. Each time the value of the text field changes (the user types in the field) a handleOnChange function is fired. This function will house the update function.

setInput could be used inline, but in my case it made more since to separate it into a handleOnChange function, since that function would perform additional operations.

To update state, we call setInput() and pass in the new value that will replace the current state.

Here’s what handleOnChange looks like in my example:

 function handleOnChange(e) {
     setInput(e.target.value)
    // TODO: Perform other operations
}

That’s it. The value of input has been updated.

Recap

To recap everything we’ve done:

  1. We imported useState into our functional component.
  2. Declared state variables *and* a function to update that variable with useState.
  3. Referenced the value of our state variable input in our and rendered on to the page.
  4. Updated input using our setInput function with the new value as the argument

And here’s what our App.js file looks like now:

import React, { useState } from "react";

function App() {

  const [input, setInput] = useState("")

   function handleOnChange(e) {
        
    setInput(e.target.value)

    // TODO: Query the Spotify API with the value of "input"
    }

  return (
    <main className="App">
        <h1>Search for an artist</h1>

        <form>
            <input type="text" name="input" id="input" onChange={(e) => handleOnChange(e)} />
        </form>

        <h2>Showing results for: "{input}"</h2>

        // TODO: Render results of API call to the page
        
    </main>
  );

}

This is the very beginning of what React Hooks can do. There are some limitations, rules and take some getting used to. I highly reccomend reading through their docs on Using the State Hook to see how useState compares to setting state in a class component.

Resources

Switching Themes Based on the Current Month

Recently, I’ve been experimenting with Javascript Date objects. I wanted to see if I could dynamically change the theme of a webpage, based on the current date.

For example, if it was October, the spookiest month of the year, I could have an orange, purple and black theme to remind them of Halloween.

Let’s try implementing this.

Create a New Date Object

The MDN web docs describes a Javascript Date object as:

“…[an] instance that represents a single moment in time in a platform-independent format. Date objects contain a Number that represents milliseconds since 1 January 1970 UTC.”

A new date object can be created with new Date(). The value of a date object will look something like this.

Sat Oct 17 2020 22:56:11 GMT-0400 (Eastern Daylight Time)

That’s a lot of information we can play around with.

Methods for Date Objects

While it looks like a string, keep in mind that the date is an object, not a string. Running console.log(typeof new Date()); would return false.

Luckily, the date prototype comes with built-in methods. These methods allow us to focus on specific parts of the date object.

For this example, I want to focus on the current month. Instead of converting the value of the date object to a string, comparing it to calendar months (October, November, etc), we can use the getMonth() method.
getMonth() returns an integer, that corresponds to the months of the year. The months of the year are zero index, so January would be 0, February 1 and so on.

Let’s see what it returns given the new Date() referenced above.

let now = new Date() // Sat Oct 17 2020 22:56:11 GMT-0400 (Eastern Daylight Time)
now.getMonth() // 9

It is currently October 17th. October is the 10th month of the year and since January would return 0 this is returning what we need.

Theme Names

Now that I know the current month, I can use it to influence changes in the CSS. I’ll use a switch case to change the value of a themeToAdd variable that I’ll later apply to the body tag.

My switch case looks something like this.

let now = new Date() // Sat Oct 17 2020 22:56:11 GMT-0400 (Eastern Daylight Time)
now.getMonth() // 9

// Placeholder for theme name that we'll add later
let themeToAdd = ""

// Evaluates the current, zero-indexed month based off of the now date object

switch(now.getMonth()) { 
    case 9:
       themeToAdd = "dark-and-spooky" 
    break; 
    default: 
       themeToAdd = "dark"
}

The logic goes something like this.

  • If the current month is October, apply the dark-and-spooky theme.
  • If the current month is not October, apply the dark theme

A bonus to having a default case is that if a date object cannot be created, we have a fallback style.

Speaking of styles, let’s set up the CSS variables for our default, dark and dark-and-spooky themes.

:root { 
--background-color: #efefef;
--font-color: #444444; 
...
}

body[data-theme="dark"] { 
--background-color: #032b43; 
--font-color: #efefef;
...}

body[data-theme="dark-and-spooky"] {
--background-color: #010101;
--font-color: #BA4A00;
...
}

...

body {
background-color: var(--background-color); 
color: var(--font-color);
...}

Changing the Theme

Now that we know which month is it, and have a theme name, and the styles set, it’s time to implement it.

Borrowing from the data attribute demo from a few months ago, we’ll implement the theme as a checkbox.

Given an HTML file that looks like this:

<html>
    <head>
    ...
    </head>
    <body>
        <label>
            Dark Mode?
            <input type="checkbox">
        </label>
    ...
    </body>
</html>

With Javascript we can target the checkbox and wait for it to be checked. If it’s checked during the month of October, implement the dark-and-spooky data attribute. Otherwise, add dark. And, if either theme is already a set attribute on the `body` tag (it was already checked), remove the data-theme attribute entirely and show the default theme.

...
let checkbox = document.querySelector("input")
    let body = document.querySelector("body")
    
    checkbox.addEventListener('change', (event) => {
        event.target.checked ? body.setAttribute('data-theme', themeToAdd) : body.removeAttribute("data-theme")
    });

Putting everything together, we have something that looks like this.

See the Pen Switching Theme Based on the Current Month by Shannon Crabill (@scrabill) on CodePen.

Note that you’ll see specific styles of the current month is October, February, or December.

Time Travel is Fun

If you enable the checkbox during the month of October, and see a dark background with orange text, it’s working!

But, you may be wondering how you can test to see if your themes are working without waiting for the right month or resetting your computer’s clock.

What’s powerful about the date constructor is that is can take in optional parameters.

If a valid date value is passed into new Date() it “…returns a Date object whose component values (year, month, day, hour, minute, second, and millisecond) all come from the [given] parameters”.

So, if we wanted to test if a lovey-dovey theme would work in the month of February, we can create a new date object for testing, like this.

let now = new Date('February 2020') // Sat Feb 01 2020 00:00:00 GMT-0500 (Eastern Standard Time)

now.getMonth() // 1

Resources

Opting Out of Hacktoberfest

For 2020, I made the decision not to opt my How Many Days Until Halloween? project in as part of Hacktoberfest.

Here’s why.

Time

I did some mental math recently. I have realized that isn’t enough time in the day to get done what I need to get done, want to get done, plus sleep, eat, etc. As I wrote about in You Don’t Have to Participate in Hacktoberfest, self-care > coding, and I need to follow my advice.

As fun as this project has over the past 3 years, it does take a lot of time and energy that I do not have to spare at this time. I’ve had ideas on how to expand on this project, what I would like to do, etc. But haven’t been able to get it to a place that I would like, that would sustain multiple, external contributions.

The Spirit of Hacktoberfest

Ha. Spirit.

Hacktoberfest is now in its 7th year. It has evolved some overtime. Recently, the idea of “quality vs quantity” has been highlighted as a core value. This year, the language reads as follows:

Quantity is fun, quality is key. Participating in Hacktoberfest leads to personal growth, professional opportunities, and community building. However, it all begins with meaningful contributions to open-source software.

And I get it. Quality is better than quantity.

This line also had me debating if a countdown timer to Halloween meets the quality criteria. It’s not a spammy project—or…is it?—but the uncertainty helped me to solidify my decision.

There Are Bigger Fish Out There

What I love about coding is that it doesn’t *have* to make a big change in the world.

But it can.

And with everything going on in the world right now, I want to make space for the open-source projects that matter.

If you are unsure what this could mean or where to start, here are some COVID-19 and climate change related projects to contribute to.

What Does This Mean?

If any questions are not covered here, please DM me on Twitter.

In the meantime, stay spooky my friend.

👻

Photo by Mathew Schwartz on Unsplash

You Don’t Have to Participate in Hacktoberfest

The first of October. The official start of spooky season. And, if you follow the tech community, the beginning of Hacktoberfest.

Hacktoberfest is an annual event that encourages participation and contribution to open source projects. Sign up during the month of October, make at least 4 valid pull requests in public repos on Github and you can receive stickers and limited edition t-shirt.

I’ve participated in Hacktoberfest for the past 3 years and it can be a lot of fun.

It can also be a lot of work.

This is especially true if you maintain a project. Tag issues with hacktoberfest for visibility and your project will gain traffic and pull requests. Most of them may be considered “spammy”.

Each year, in September (or Preptember) the “get ready for Hacktoberfest”, “who’s looking for contributors” and “101 open source projects for beginners” posts go live, the emails to sign up come in. And it can all be a little overwhelming.

Especially with everything going on in the world right now.

This is why I’ll step in as your internet friend by telling you it is ok not to participate in Hacktoberfest.

Here are two reasons why.

Spare Time is a Luxury

I have a lot of feelings about personal projects and coding outside of work. On one hand, personal projects are good for learning a new skill, or as a side hustle. Any reason that you want to code outside of your 9-5 is valid.

But. Not everyone has the privilege of spare time.

Family commitments, second jobs, whatever. Extra time at a computer isn’t realistic for everyone. And that is ok. There can be pressure, even if it’s from ourselves, to try and do all-of-the-things. But it’s not always possible.

Please be realistic about what is important to you, your career, your family, etc. Be realistic about how much time exists in a day, week, month, etc and what time you can commit to.

Which brings me to my next point.

Self-care > Coding

Coding is a big part of my life. I love it. I do it as part of my job. I code in my spare time and yet…I find myself needing and wanting to spend more time away from the computer.

Perhaps you feel the same way.

As the days get shorter and the longest year of our lives comes to an end…reflect on how you are feeling. If you feel as tired and exhausted as I do. It may be time to focus on self-care, recharging, and coming back refreshed.

Self-care is whatever you need to do to recharge. As developers, I feel like there’s pressure to always be working on something, work/life balance tends to slip and, if you aren’t careful, burnout will set in.

Trust me, time away from a computer will allow you to come back with fresh eyes, a fresh perspective, and ready to pick up where you left off.

Please Take Care of Yourself

The main point I am trying to make here is that you do not have to participate in Hacktoberfest. You are no less of a developer if you sit out this year (or next year, or never participate). Do what you feels right to you and you will not be disappointed.

Photo by Mathew Schwartz on Unsplash