A ticking clock using functional programming (JS)

A ticking clock using functional programming (JS)

in functional way

Imperative solution in non-functional way:

// Log clock time every second
setInterval(logClockTime, 1000);

function logClockTime() {
  // Get time string
  let time = getClockTime();

  // Clear the console and log the time
  console.clear();
  console.log(time);
}

function getClockTime() {
  // Get the current time
  let date = new Date();

  // Serialize clock time
  let time = {
    hours: date.getHours(),
    minutes: date.getMinutes(),
    seconds: date.getSeconds(),
    apm: 'AM'
  };

  // Convert to civilian time
  if (time.hours >= 12) time.apm = 'PM';
  if (time.hours > 12) time.hours -= 12;

  // Prepend a leading 0 on the hours/minutes/seconds to make double digits
  if (time.hours < 10) time.hours = `0${time.hours}`;
  if (time.minutes < 10) time.minutes = `0${time.minutes}`;
  if (time.seconds < 10) time.seconds = `0${time.seconds}`;

  // Format the clock time as a string 'hh:mm:ss tt'
  return `${time.hours}:${time.minutes}:${time.seconds} ${time.apm}`;
}

Now, let’s break the application logic up into smaller function parts.

In functional programs, we should use functions over values wherever possible:

const oneSecond = () => 1000;
const getCurrentTime = () => new Date();
const clear = () => console.clear();
const log = (message) => console.log(message);

// serialize date to clock time
const serializeClockTime = (date) => ({
  hours: date.getHours(),
  minutes: date.getMinutes(),
  seconds: date.getSeconds()
})

// turn clock time to civilian time
const civilianHours = (clockTime) => ({
  ...clockTime,
  hours: clockTime.hours > 12 ? clockTime.hours - 12 : clockTime.hours
})

// append AM/PM
const appendAPM = (clockTime) => ({
  ...clockTime,
  apm: clockTime.hours >= 12 ? 'PM': 'AM'
})

// here 'fn' will be console.log
const display = fn => time => fn(time);

// format clock with template string 'hh:mm:ss tt'
const formatClock = format => time => {
  return format.replace('hh', time.hours)
    .replace('mm', time.minutes)
    .replace('ss', time.seconds)
    .replace('tt', time.apm)
}

// prepend leading zero
const prependZero = key => clockTime => ({
  ...clockTime,
  [key]: clockTime[key] < 10 ? `0${clockTime[key]}` : clockTime[key]
})

// compose functional parts
const compose = (...fns) => arg => fns.reduce((composed, f) => f(composed), arg);

const convertToCivilianTime = clockTime => {
  return compose(
    appendAPM,
    civilianHours
  )(clockTime)
}

const doubleDigits = civilianTime =>
  compose(
    prependZero('hours'),
    prependZero('minutes'),
    prependZero('seconds')
  )(civilianTime)

const startTicking = () => {
  setInterval(
    compose(
      clear,
      getCurrentTime,
      serializeClockTime,
      convertToCivilianTime,
      doubleDigits,
      formatClock('hh:mm:ss tt'),
      display(log)
    ), oneSecond()
  )
}

startTicking();
Ads by Google

林宏

Frank Lin

Hey, there! This is Frank Lin (@flinhong), one of the 1.41 billion 🇨🇳. This 'inDev. Journal' site holds the exploration of my quirky thoughts and random adventures through life. Hope you enjoy reading and perusing my posts.

YOU MAY ALSO LIKE

Using Liquid in Jekyll - Live with Demos

Web Notes

2016.08.20

Using Liquid in Jekyll - Live with Demos

Liquid is a simple template language that Jekyll uses to process pages for your site. With Liquid you can output complex contents without additional plugins.

Hands on IBM Cloud Functions with CLI

Tools

2020.10.20

Hands on IBM Cloud Functions with CLI

IBM Cloud CLI allows complete management of the Cloud Functions system. You can use the Cloud Functions CLI plugin-in to manage your code snippets in actions, create triggers, and rules to enable your actions to respond to events, and bundle actions into packages.

Self-host comments in Jekyll, powered by Firebase real-time database

Tutorials

2017.03.25

Self-host comments in Jekyll, powered by Firebase real-time database

It's convenient to set up a comment system in Jekyll site with external social comment systems like Disqus or Duoshuo (多说). However, as you all know, Disqus was blocked in China and Duoshuo is going to shutdown. It's the time to rethink about the comment system (although I didn't get too many comments →_→), simple and controllable. And it becomes true with Firebase database.