Create a Timestamp microservice with Node.js

Create a Timestamp Microservice with Node.js

This time around, we are going to be coding our own timestamp microservice using Node.js, and then, deploy it to Heroku. It’s going to be a very simple service that will return the unix time and natural date for the received input. Our API should be able to receive and properly handle the following two formats:

  • A unix timestamp is a metric used to track time by displaying the miliseconds (sometimes seconds) that have passed since January 1st, 1970 at 00:00:00 UTC. For a quick test, you can get the unix timestamp for right now, by going into the Chrome DevTools console and typing the following: Date.now();
  • The natural language date means that the date is passed in the following format: October 1, 2016.

Our timestamp microservice will accept any one of these two formats, and then, return a JSON object containing both formats. In other words:

  • If the API receives this: 1477388794872, it will output the following JSON object:
    {
      "unix": 1477388794872,
      "natural": "October 25, 2016"
    }
  • Receiving “October 25, 2016” will output the same exact JSON object.

If no unix timestamp nor natural date is present, we’ll return null for both fields:

{
  "unix": null,
  "natural": null
}

Requirements:

  • Basic Git knowledge AKA know how to initialize a GitHub repo and push to it.
  • Node.js and NPM installed in your system.
  • Some energy!

Let’s get to it shall we. We’ll start by setting up the development environment by creating a new folder for our project. Then, go ahead and register for a Heroku account by following this link.

Once that’s out of the way, download and install the Heroku Toolbelt. To make sure that the installation was successful, execute the following in the command line:

heroku version

 

Let’s really get started. Go back to your project folder and create a new file, call it index.js, then, add a new file and call it .gitignore (this is not mandatory, but good to have if you plan to push your code to GitHub etc.).

Now, open up a command line window. Now, execute npm init  and fill it in with the relevant data, make sure that index.js is used as the entry file. Once done, we’re going to install Express.js to make our life’s easier.

Express is a Node.js framework to make building APIs much easier and faster, you’ll learn to love it in time; meanwhile, execute the following command to install it:

npm install --save express

 

Open up index.js and import the express library, we are going to create a very simple Hello World app to make sure that everything is working:

var express = require('express'); // We import ExpressJS

var app = express(); // This is how we initialize an express app
var PORT = process.env.PORT || 3000;     // We set the port that the application will use

// When a GET request is made to the root path: '/' reply with Hello World
app.get('/', function(request, response) {
  response.send('Hello World');
});

// We set the app to listen on the given PORT
// It will log a message to the console once it is ready
app.listen(PORT, function() {
  console.log('Server is listening on port ' + PORT);
});

 

Let’s make sure the code works by going back to the command line and executing the following command:

node index.js

 

If everything is right, we should get a message saying something like “Server is listening on port 3000”. If you open up a web browser and navigate to http://localhost:3000, you should see the ‘Hello World’ message being printed.

Instead of typing node index.js  each time, we’re going to add a script to the package.json file:

{
  "name": "timestamp-microservice",
  "version": "1.0.0",
  "description": "A basic timestamp microservice built on Node.js",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/StrongeLeeroy/timestamp-microservice.git"
  },
  "keywords": [
    "timestamp",
    "microservice",
    "node.js"
  ],
  "author": "Gorka Hernandez <info@gorkahernandez.com> (https://www.gorkahernandez.com)",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/StrongeLeeroy/timestamp-microservice/issues"
  },
  "homepage": "https://github.com/StrongeLeeroy/timestamp-microservice#readme",
  "dependencies": {
    "express": "^4.14.0"
  }
}

 

You can now execute npm start  to get the same result as node index.js .

Let’s deploy our project to Heroku now, it’s quite easy, assuming you’ve already installed the Heroku Toolbelt.

Start by running the following command and typing your credentials to log into Heroku:

heroku login

 

Now, initialize a Git repository and commit your code:

git init
git add .
git commit -m "First commit"

 

Now, create a Heroku app by running:

heroku create

 

Once created, you’ll get the URL where your app is running:

heroku create command

 

Navigating to this URL now won’t show us much, we are not done yet, to deploy our code to Heroku, we need to execute:

git push heroku master

 

Now, make sure that Heroku runs at least once instance of the app:

heroku ps:scale web=1

 

Unfortunately, this is still not enough. Why? You ask, because Heroku has no idea about what it needs to do to run your app, that’s why we need to provide a Procfile. A Procfile is but a text file that sits in the root directory of the application and tells Heroku what to do with it.

Create a new file and call it Procfile, then, add the following content:

web: node index.js

 

Now, let’s commit our changes and push once again:

git add .
git commit -m "Add Procfile to project"
git push heroku master

 

To see the app, you can navigate to the provided URL or run heroku open  as a shortcut.

Finally guys, we can actually start doing what we were supposed to do in the first place: a timestamp microservice.


The actual timestamp microservice

The groundwork has already been taken care off, now, we just need to develop and repeat the git add, commit, push cycle when we want to deploy a new version to Heroku.

Before we can start working with the actual timestamps, we need to change up the index.js file so we can receive path parameters. What’s a patch parameter? Look at this example:

https://www.gorkahernandez/blog/my-blog-post-name

In that particular case, every item after is a path parameter:

  • Blog
  • my-blog-post-name

ExpressJS can pick these up by using an specific syntax like so:

app.get('/:name', function(request, response) {
  // We can access the path parameters here:
  var name = request.params.name;
  response.send('The provided name is: ' + name);
});

 

Let’s update our routes so we can get a timestamp:

var express = require('express');

var app = express();
var PORT = process.env.PORT || 3000;

app.get('/:timestamp', function(request, response) {
  var timestamp = request.params.timestamp;
  response.send('Timestamp: ' + timestamp);
});

app.listen(PORT, function() {
  console.log('Server is listening on port ' + PORT);
});

 

Now, we need to handle the valid cases, and return null values for the invalid ones. I’m going to add a function that will create a JSON object with the output values. This way, we abstract this logic from the actual API method (app.get()), for cleaner code. I’m also going to update the returned value, so we send JSON instead of plain text.

var express = require('express');

var app = express();
var PORT = process.env.PORT || 3000;

app.get('/:timestamp', function(request, response) {
	var timestamp = request.params.timestamp;
	response.json(getTimestampJSON(timestamp));
});

app.listen(PORT, function() {
	console.log('Server is listening on port ' + PORT);
});

function getTimestampJSON(timestamp) {
	// First, we handle the unix timestamps. Path parameters come in as text
	// rather than numbers, so we'll attempt to parse them.
	var result = {
		unix: null,
		natural: null
	};

	var date;
	if (!isNaN(parseInt(timestamp))) {
		// This means that the parsed integer is NOT a
		// NaN (not a number) value, in other words: it's a valid number.
		date = new Date(parseInt(timestamp));
	} else {
		// Timestamp is not a valid number, we'll create a Date object
		// and then check if is valid before we return it
		date = new Date(timestamp);
	}

	if (!isNaN(date.getTime())) {
		// Date.getTime() returns the unix timestamp,
		// if it where an invalid date, this would be NaN
		result.unix = date.getTime();
		result.natural = 'We will get here eventually!';
	}

	// We return the value, whatever it may be.
	return result;
}

 

This is basically what the code in getTimeStampJSON does:

  • First, we create the default response, with null values assigned to both fields.
  • We check if calling parseInt on the received timestamp produces a valid number, and create a Date object using it.
  • Else, we create the Date object using the raw string.
  • Then, we check if the created Date is indeed valid, by calling getTime() on it. This method returns the unix timestamp for the Date object, and will be NaN for invalid dates. If the test is passed, we set the unix timestamp and natural language date (we’ll get to this) values.
  • We return the result object. If the date were to be invalid, we’ll simply return the null values we already set.

 

Now then, let’s create a nice natural language date string by creating a new function. Here’s the updated version:

var express = require('express');

var app = express();
var PORT = process.env.PORT || 3000;

app.get('/:timestamp', function(request, response) {
	var timestamp = request.params.timestamp;
	response.json(getTimestampJSON(timestamp));
});

app.listen(PORT, function() {
	console.log('Server is listening on port ' + PORT);
});

function getTimestampJSON(timestamp) {
	var result = {
		unix: null,
		natural: null
	};

	var date;
	if (!isNaN(parseInt(timestamp))) {
		date = new Date(parseInt(timestamp));
	} else {
		date = new Date(timestamp);
	}

	if (!isNaN(date.getTime())) {
		result.unix = date.getTime();
		result.natural = getNaturalDate(date);
	}

	return result;
}

function getNaturalDate(date) {
	var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'Obtober', 'November', 'December'];

	return months[date.getMonth()] + ' ' + date.getDate() + ', ' + date.getFullYear();
}

 

This function is pretty simple, since calling getMonth() on a Date object returns a 0 index based number (0 -> January and 11 -> December) we use a month array and get the month name from there, then, we simple add the date and year to it. Let’s commit and push this new code to Heroku:

git add .
git commit -m "Add functionality"
git push heroku master
heroku open

 

You should now be able to access the timestamp microservice endpoint running on Heroku. In my case, I can access the following 3 examples:

https://sleepy-temple-58228.herokuapp.com/1454345343977

https://sleepy-temple-58228.herokuapp.com/February%201,%202016

https://sleepy-temple-58228.herokuapp.com/this-is-an-error

Note the %20‘s that appear in the second URL, these are actually encoded space characters. All set and ready to go!

Shoot any questions you may have my way!