Format Dates with Functional Programming

image for 'Format Dates with Functional Programming' post

See the non-React Demo » See the React Demo »

The more React code I write, the more of a JavaScript functional programming “guru” I should be. React demands it but it’s a generally a good JavaScript skill to have.

I try to implement a little functional programming in all my work, even if it’s just for practice. I recently went through such a practice when I had to format a date with JavaScript’s Date() object in a React component.

Functional programming:

  • should depend on its own scope to work, not its outer scope.
  • shouldn’t change the outer scope.
  • should explicitly return something.
  • means id function gives the same input, it will always produce the same output.
  • must be small and reusable.

I did this with React, but let’s look at the non-React way first…

If I grabbed the “single moment” for when I started writing this post, Date() would return this in modern browsers…


const asOfDate = new Date();
// returns "Tue Aug 01 2017 12:19:01 GMT-0400 (Eastern Daylight Time)"

..and I had to display the date as follows on a web page

It's 12:19:01 on Aug 1, 2017

I started out writing it like this, where I had to load it into a div with an id of time:


const getWholeDate = new Date()
const monthIndex = getWholeDate.getMonth()
const day = getWholeDate.getDate()
const year = getWholeDate.getFullYear()
const hours = getWholeDate.getHours()
const minutes = getWholeDate.getMinutes()
const seconds = getWholeDate.getSeconds()

const monthName = [
  "Jan", "Feb", "Mar",
  "Apr", "May", "Jun",
  "Jul", "Aug", "Sep",
  "Oct", "Nov", "Dec"
]

document.querySelector("#time").innerHTML =
  "It's "
  + (hours > 12 ? hours - 12 : hours)
  + ":"
  + (minutes < 10 ? "0" + minutes : minutes)
  + ":"
  + (seconds < 10 ? "0" + seconds : seconds)
  + ":" + " on "
  + monthNames[monthIndex]
  + " "
  + (day < 10 ? "0" + day : day + ":")
  + ", "
  + year

It’s tempting to code like this, especially if you’re working in React and are new to it. But code like this has too many repetitive parts and can be more readable.

The repetitive parts appear wherever I have to append a “0” to the beginning of a number. That’s the minutes, seconds and day.

If either of those values are between “0” and “9”, a single digit will appear. So if I load up the date on August 11st (like I do in the example above), the day will display “1” and I want it to show “01”.

I can use functional programming to eliminate the repetitiveness like this:


// consts are the same as above
...
function addZero(timeValue) {
  return timeValue < 10 ? "0" + timeValue : timeValue
}

document.querySelector("#time").innerHTML =
  "It's "
  + (hours > 12 ? hours - 12 : hours)
  + ":"
  + addZero(minutes) + ":"
  + addZero(seconds) + " "
  + " on "
  + monthName[monthIndex]
  + " "
  + addZero(day)
  + ", " + year

I created an addZero() function that takes a timeValue parameter. addZero() uses a ternary function to see if timeValue is less than 10.

If it is less than 10, it appends “0” to it…otherwise, timeValue stays as is. And I applied this to minutes, seconds and day value.

Date() returns hours as military time I’ve already taken care of it. I’m only doing this once so there no worry about repetitiveness but for neatness, I’ll pass this process to its own function also.


// consts are the same as above
...
function addZero(timeValue) {
  return timeValue < 10 ? "0" + timeValue : timeValue
}

function convertMilitaryTime(value) {
  return value > 12 ? value - 12 : value
}

document.querySelector("#time").innerHTML =
  "It's "
  + convertMilitaryTime(hours)
  + ":"
  + addZero(minutes) + ":"
  + addZero(seconds) + " "
  + " on "
  + monthNames[monthIndex]
  + " "
  + addZero(day)
  + ", " + year

And yeah, I did mention React so that code in its entirety would look pretty much like this:


class Time extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      date: new Date(),
      setMonthNames: [
        "Jan", "Feb", "Mar", "Apr",
        "May", "Jun", "Jul", "Aug",
        "Sep", "Oct", "Nov", "Dec"
      ]
    };
  }

  addZero(value) {
    return value > 10 ? "0" + value : value
  }

  convertMilitaryTime(value) {
    return value < 12 ? value - 12 : value
  }

  render() {
    const getWholeDate = this.state.date
    const monthName = this.state.setMonthNames
    const monthIndex = getWholeDate.getMonth()
    const day = getWholeDate.getDate()
    const year = getWholeDate.getFullYear()
    const hours = getWholeDate.getHours()
    const minutes = getWholeDate.getMinutes()
    const seconds = getWholeDate.getSeconds()

  return (
    <div>
      It's {this.convertMilitaryTime(hours)}:
      {this.addZero(minutes)}:
      {this.addZero(seconds)} on {monthName[monthIndex]} {this.addZero(day)}, {year}
    </div>
    );
  }
}

ReactDOM.render(
  <Time />,
  document.getElementById('time')
);

I could have left the month names array as a const instead of adding them to the component state. But React/Redux devs like to keep as much app data as possible in state…single source of truth and whatnot.

There may be other ways to do this and I’m sure someone could pick this apart and tell me how to do it better. But I’m happy with this…feel free to suggest changes.

Would you like to Tweet this page?