Categories
JavaScript

How to Manipulate Time in JavaScript with Moment.js

There were issues with time zones with YYYY-MM-DD dates being parsed into UTC time as opposed to local time. Which creates bugs for developers who aren’t aware of this problem. See https://stackoverflow.com/questions/29174810/javascript-date-timezone-issue

Also there are difference in support for parts of Dates in different browsers. (See https://stackoverflow.com/questions/11253351/javascript-date-object-issue-in-safari-and-ie)

It is also hard to add and subtract timestamps with built in Date functions. There is no way to do this without writing a lot of code and doing a lot of checks. Also, there is no way to compare 2 times.

Formatting dates is also not available without writing your own code for using third party libraries.

Moment.js solves all of these issues by providing built in functions to do all these common operations. It provides functions for parsing and formatting dates.

The momentconstructor is where you can pass in a date string, and a moment object will be created. For example, you can pass in:

moment('2019-08-04')

and you will get back a moment which you can compare with other moment objects, and add or subtract by different time spans.

If you do not passing in anything to the moment constructor, you get the current date and time.

It also takes a second argument. If you want to make sure a date is parsed as a YYYY-MM-DD date, then write moment(‘2019–08–04’, 'YYYY-MM-DD') . If you don’t know the format of your date or time, then you can pass in an array of possible formats and Moment will pick the right one:

moment('2019–08–04', ['YYYY-MM-DD', 'DD-MM-YYYY']);

After you create a Moment object, then you can do many things like formatting dates:

const a = moment('2019–08–04', 'YYYY-MM-DD').format('MMMM Do YYYY, h:mm:ss a');  
console.log(a);// August 4th 2019, 12:00:00 am
    
const b = moment('2019–08–04', 'YYYY-MM-DD').format('dddd');  
console.log(b);
// Sunday
   
const c = moment('2019–08–04', 'YYYY-MM-DD').format("MMM Do YY");  
console.log(c);
// Aug 4th 19
    
const d = moment('2019–08–04', 'YYYY-MM-DD').format('YYYY [escaped] YYYY');      
console.log(d);
// 2019
   
const e = moment('2019–08–04', 'YYYY-MM-DD').format(); 
console.log(e);// 2019-08-04T00:00:00-07:00

From the above examples, we see that we can format dates in pretty much any way we want.

We can also tell what time span a date is relative to another date by writing:

const augDate = moment('2019–08–04', 'YYYY-MM-DD');  
const sepDate = moment('2019–09–04', 'YYYY-MM-DD');
console.log(augDate.from(sepDate)); // a month ago

We can also add or subtract Moment dates:

const augDate = moment('2019–08–04', 'YYYY-MM-DD');  
const sepDate = moment('2019–09–04', 'YYYY-MM-DD');
console.log(augDate.add(10, 'days').calendar()); 
// 08/14/2019  
console.log(augDate.subtract(10, 'days').calendar()); 
// 07/25/2019

It is easy to compare 2 dates

moment('2010-01-01').isSame('2010-01-01', 'month'); 
// true  
moment('2010-01-01').isSame('2010-05-01', 'day');   
// false, different month  
moment('2008-01-01').isSame('2011-01-01', 'month'); 
// false, different year

You can also check if a date is has Daylight Saving Time in effect or not:

const augDate = moment('2019–08–04', 'YYYY-MM-DD');  
const decDate = moment('2019–12–04', 'YYYY-MM-DD');  
console.log(augDate.isDST()) // true  
console.log(decDate.isDST()) // false

And you can convert back to JavaScript date any time by calling the toDate() function on a Moment object.

And there we have it!

Categories
JavaScript

How to Manipulate Arrays in JavaScript

Iterating Array

For Loop

The for loop is one of the most basic loops for looping through an array. It takes a starting index and then loops through to the ending index. Index must be an integer.

Example:

const array = [1,2,3];  
for (let i = 0; i < array.length; i++){  
  console.log(i);  
}

The loop above should log all the numbers in the array.

Indexes do not have to be consecutive:

const array = [1,2,3];  
for (let i = 0; i < array.length; i+=2){  
  console.log(i);  
}

The loop above will skip every second number.

While Loop

while loop will loop whenever a condition stays true.

For example, the loop below will run if the index number i is less than three:

const array = [1,2,3];
let i = 0;  
while(i < array.length){  
  console.log(i);  
}

If the condition in the parentheses is never true, then the loop content will never run.

Do While Loop

do...while loop will always execute the first iteration.

const array = [1,2,3];
let i = 0;  
do{  
  console.log(i);  
}  
while(i < array.length)

In the example above, it will at least log 0, but it will also log 1 and 2 in this case since those two numbers are less than three.

With the above loops, you can call break to stop the loop or return before the loop is completely finished.

//do while loop  
const array = [1,2,3];
let i = 0;
do{  
  console.log(i);  if (i == 1}{    break;  }}  
while(i < array.length)

//while loop  
i = 0;
while(i < array.length){  
  if (i == 1){    break;  }  
  console.log(i);  
}

//for loop  
for (let j = 0; j < array.length; j++){  
  if (j == 1){  
    break;  
  }  
  console.log(j);  
}

In the above examples, you will not see two logged.

An example of returning from within the loop:

const loop = ()=>{  
  const array = [1,2,3];    
  for (let j = 0; j < array.length; j++){         
    if (j == 1){  
      return j;  
    }  
    console.log(j);  
  }  
}  
loop() //returns 1

You can also skip iterations with continue statement:

const array = [1,2,3];  
for (let j = 0; j < array.length; j++){  
  if (j == 1){  
    continue;  
  }  
  console.log(j) // 1 will be skipped;  
}

Array.forEach

forEach will iterate through every entry of the array. You cannot break out of it or return a value from it. It takes a callback function where you can execute code.

Example:

const array = [1,2,3];  
  array.forEach(a =>{  console.log(a);  
})

In the above example, all the numbers in the array will be logged.


Find Element in Array

Array.find

Array.find will return the element in the array with the given condition. For example, if you want to get certain numbers from the array, you do:

const array = [1,2,3];  
const num = array.find(a => a == 2); // returns 2

find returns a single result.

Array.findIndex

Array.findIndex will return the index of the element in the array with the given condition. It takes a callback function that returns a given condition. For example, if you want to get the index of a certain numbers from the array, you do:

const array = [1,2,3];  
const num = array.findIndex(a => a == 2); // returns 1

Array.filter

Array.filter will return an array of items that meet the given condition. It takes a callback function that returns a given condition. filter returns a new array.

For example, if you want to get the index of a certain numbers from the array, you do:

const array = [1,2,3];  
const numArray = array.filter(a => a == 2); // returns [2]

Check if Element Exists in Array

Array.includes

Array.includes checks if an item exists in an array. It takes a number or string which the function can compare.

const array = [1,2,3];  
const includesTwo = array.includes(2); // returns true

Array.some

Array.somechecks if some items meet the condition given. It takes a callback function which returns a boolean for the condition.

const array = [1,2,3];  
const includesTwo = array.some(a => a == 2); // returns true  
const includesFive = array.some(a => a == 5); // returns false

Array.every

Array.every checks if every item meet the condition given. It takes a callback function which returns a boolean for the condition.

const array = [1,2,3];  
const everyElementIsTwo = array.every(a => a == 2); // returns false  
const everyElementIsNumber = array.every(a => typeof a == 'number'); // returns true since every item in the array is a number

Check If an Object Is an Array

Array.isArray

Array.isArray checks if an object given is an array. It is a convenient way to check if an element is an array.

const array = [1,2,3];
const notArray = {};  
let objIsArray = Array.isArray(array); // true  
objIsArray = Array.isArray(notArray); // false

Remove Duplicates in Array

Array.from(new Set(array))

Set is a object that cannot have duplicate entries. You can create a new Setfrom an array then convert it back to an array.

const array = [1,2,2,3];  
const arrayWithDups = Array.from(new Set(array)); //returns new array without duplicates, [1,2,3]

Array.slice(startIndex, endIndex)

Returns a new array from startIndex to endIndex — 1 .

Example:

const arr = [1,2,3,4,5];  
const newArr = arr.slice(0,2);  
console.log(newArr); // returns [1,2]

Array.splice(index, numberOfItems)

Remove array item in place with the given index, and then numberOfItems after it.

For example:

const arr = [1,2,3,4,5];  
arr.splice(0,2);  
console.log(arr); // returns [3, 4, 5] since we specified that we remove item located at index 0 and 2 items after that.

Array.sort(sortFunction)

Array.sort sorts array in place according to the condition you return insortFunction .

The sortFunction should be in this format:

const sortFunction = (a, b) {  
  if (a < b) {  
    return -1;  
  }  
  if (a > b) {  
    return 1;  
  }  
  // a must be equal to b  
  return 0;  
}

By default, if no sortFunction is specified, then the array items will be converted to string and will be sorted according to the Unicode value of the string.

Array.fill(newElement, startIndex, endIndex)

Array.fill will add or replace the element with the element specified from startIndex to endIndex . If no startIndex is defined then it will start from 0. If no endIndex is defined, then it will change values up to the end of the array.

For example:

let array = [1, 2, 3, 4, 5];console.log(array.fill(0, 2, 4));  
// array is now [1, 2, 0, 0, 0]console.log(array.fill(5, 1));  
// array is now [1, 5, 5, 5, 5]console.log(array.fill(6));  
// array is now [6, 6, 6, 6, 6]

Recursively Flatten Array

Array.flat function does not do a good job of recursively flatten arrays. The depth is limited and it does not flatten all kinds of nested array structures. The better way to do it is to write a recursive function to do it.

let arr1 = [1, 2, [3, 4], 5];  
let arr2 = [1, 2, [3, 4], [5, [6,[7,]]]];
const flatten = (items) => {  
  const flat = []; 
  items.forEach(item => {  
    if (Array.isArray(item)) {  
      flat.push(...flatten(item));  
    } else {  
      flat.push(item);  
    }  
  }); 
  return flat;  
}
console.log(flatten(arr1));  
console.log(flatten(arr2));

Array.join(separator)

Array.join will return a string by concatenating the entries after they are converted to string with separator between each entry. Works best with string and number arrays.

Example:

const arr = [1,2,3];  
console.log(arr.join(',')) // get '1,2,3'
const arr = ['1',2,3];  
console.log(arr.join(',')) // get '1,2,3'

Array.indexOf(elementToFind)

Array.indexOfwill return the first index of the elementToFind in the array. Works best with string and number arrays. If you want to find a non-string or number object, use Array.findIndex . Returns -1 is element is not found.

Example:

const arr = [1,2,3];  
console.log(arr.indexOf(1)); // returns 0const arr2 = [1,1,2,3];  
console.log(arr2.indexOf(1)) // still 0

Array.lastIndexOf()

Array.lastIndexOfwill return the last index of the elementToFind in the array. Works best with string and number arrays. Returns -1 is element is not found. The function also takes a starting index to start searching backwards as a second parameter

Example:

const arr = [1,2,3];  
console.log(arr.indexOf(1)); // returns 0const arr2 = [1,1,2,3];  
console.log(arr2.indexOf(1)) // returns 1const arr3 = [3,1,2,3]  
console.log(arr3.lastIndexOf(3, 2)) // returns 0, start searching backwards from index 2

Array.push(newElement)

Array.push adds a new element to an array.

Example:

let arr = [1,2,3];  
arr.push(4);  
console.log(arr) // [1,2,3,4]

Array.pop()

Array.pop removes the last element of the array.

Example:

let arr = [1,2,3,4];  
arr.pop();  
console.log(arr) // [1,2,3]

Array.map(mapFunction)

Array.map returns a new array which transforms the existing array’s element by calling the mapFunction . mapFunction takes one argument, which is the array element.

Example:

let arr = [1,2,3,4];  
const newArr = arr.map(a=>a*2)  
console.log(newArr) // [2,4,6,8]

Array.reduce(reduceFunction)

Array.reduce combines elements of an array to return a value by calling the reduceFunction on all the elements to combine them. reduceFunction takes 2 arguments, which is the current and next element in the array.

Example:

const arr = [1,2,3,4];  
const sum = arr.reduce((a,b)=>a+b);  
console.log(sum); // returns 10

Array.reverse()

Array.reverse returns a new array with the existing array’s elements in reverse order.

Example:

const arr = [1,2,3,4];  
console.log(arr.reverse()) // [4,3,2,1]
Categories
JavaScript Nodejs

How to Deploy Node.js Web App to Heroku from Bitbucket

Note that the Git command is pushing a subfolder to Heroku, but you can push the root folder as well.

Then we to make a Procfile in the root folder of the back end app.\

release: npx sequelize db:migrate  
release: npm install -g sequelize-cli forever  
release: npm i  
web: node app.js

In this example, migrations are run, then packages are installed and the app is restarted.

Once you push your code in the branch you specified in the BITBUCKET_BRANCH variable, then all the commands you specified in the Procfile will run. The build steps are specified in the release: lines and the line running the web app is specified in the web: line of the Procfile .

Once the Procfile commands finished running, your app will be running.

Categories
JavaScript Nodejs

How to Use Sequelize to Manipulate Databases

Sequelize is a Node.js ORM with which has one of the most comprehensive features sets available.

It is similar to other ORMs like ActiveRecord, in that they are based on creating migrations with the Sequelize CLI, allowing you to write code to modify your database’s structure.

However, there are a few catches which someone has to be aware of. The migration functionality is not as smart as ActiveRecord. You cannot roll back database migration withour creating a down migration.

Also, migrations are not transactions, which means it may fail with a partially run migration where some parts of it failed to execute, leaving you with some changes made, but others not.

Sequelize CLI has to be installed separately from the library. You can run npm run --save-dev sequelize-cli to install it. After that, run npx sequelize model:generate to create your first model with its associated migration.

Add Model with Migration

For example, to create a User model with a Users table, run:

$ npx sequelize-cli model:generate --name User --attributes firstName:string,lastName:string,email:string

You may have to have administrator privileges in Windows to run this. This will create a firstName field, a lastName field, and an email field in the User model and when npx sequelize-cli migration is run, then a Users table will be created with the columns firstName , lastName and email .

The migration file should have this code:

'use strict';

module.exports = {  
  up: (queryInterface, Sequelize) => {  
    return queryInterface.createTable('Users', {  
      id: {   
        allowNull: false,  
        autoIncrement: true,  
        primaryKey: true,  
        type: Sequelize.INTEGER  
      },  
      firstName: {  
        type: Sequelize.STRING  
      },  
      email: {  
        type: Sequelize.STRING  
      },  
    });  
   }, down: (queryInterface, Sequelize) => {  
     return queryInterface.dropTable('Users');  
   }  
};

Note the id column is created automatically, and there is a down migration in the down function where the reverse of the up migration is included. If the code in the down function is not included, then you cannot run npx sequelize-cli db:migrate:undo to undo your migration.

You can also create migration and model files separately. They will be linked together if they are named in the correct pattern. Table name should be plural of the model name. For example Users table will map to the User model. To create migration without its associated mode, run npx sequelize migration:generate .

If you have multiple operations, you have to wrap them in an array and pass the array of operations into Promise.all and return that, since the return value of the up and down functions is a promise.

Adding Constraints

Adding constraints is simple. To do this, put the following in the up function of your migration file.

queryInterface.addConstraint(  
  "Users",  
  \["email"\],  
  {  
    type: "unique",  
    name: "emailUnique"  
})

To drop this, put:

queryInterface.removeConstraint(  
  'Users',  
  'emailUnique'  
)

Associations

To make has one, has many or many to many relations between tables, you can specify that using the Model.associate function. For example, if you have a Tweets table where multiple Tweets belong to one User , you can do:

Tweet.associate = function (models) { Tweet.belongsTo(models.User, {  
    foreignKey: 'userId',  
    targetKey: 'id'  
  });  
};

foreignKey is the ID referencing the external table and targetKey is the ID column of the table you’re referencing.

And in the User model:

User.associate = function (models) {  
  User.hasMany(models.Tweet, {  
    foreignKey: 'userId',  
    sourceKey: 'id'  
  });  
};

foreignKey is the ID referencing the current table in this case and sourceKey is the ID column of the table you’re referencing.

This specifies that each User has many Tweets.

Similarly, you can replace hasMany with hasOne to specifiy one to one relationship.

To make a many to many relationship, you need a join table between the 2 tables that you want to create relationship with, then you can use belongsToMany function of your model to create the relationship. You need this in both of your tables that you are creating the relationship with.

For example if multiple Users can belong in multiple ChatRooms , then do:

User.associate = function(models) {        
  User.belongsToMany(models.ChatRoom, {      
    through: 'UserChatRooms',      
    as: 'chatrooms',      
    foreignKey: 'userId',      
    otherKey: 'chatRoomId'    
  });  
};

And for the ChatRoom model:

ChatRoom.associate = function(models) {        
  ChatRoom.belongsToMany(models.User, {      
    through: 'UserChatRooms',      
    as: 'users',      
    foreignKey: 'chatRoomId',      
    otherKey: 'userId'    
  });  
};

foreingKey is the ID that the other table references, otherKey is the key that is in the current table.

Changing Columns

You can rename a column like this:

queryInterface.renameColumn('Tweets', 'content', 'contents')

The first argument is the table name, second is the original column, third one is the new column name.

Changing data type is simple:

queryInterface.changeColumn(   
  'Tweets',  
  'scheduleDate', {  
    type: Sequelize.STRING  
  }  
)

If you want to change string to date or time, do:

queryInterface.changeColumn(  
  'Tweets',   
  'scheduleDate', {  
    type: 'DATE USING CAST("scheduleDate" as DATE)'  
  }  
)queryInterface.changeColumn(  
  'Tweets',  
  'scheduleTime', {  
     type: 'TIME USING CAST("scheduleTime" as TIME)'  
  }  
)

To run migrations, run npx sequelize db:migrate .

And there we have it — a brief look into how to use Sequelize to manipulate databases! 🎉

Categories
JavaScript JavaScript Basics

How to Round Numbers in JavaScript

JavaScript has multiple ways to round a number. Some choices are the Math.round , number.toFixed , andnumber.toPrecision . You can also write your own function to round a number up or down to the nearest increment.

Math.round

Math.round rounds a number to the nearest integer. If the decimal part of the number is less than 0.5, it is rounded down. Otherwise, if the decimal part of the number of 0.5 or higher then it will be rounded up. The function returns the rounded number as the value.

For example:

Math.round(12.5); // 13  
Math.round(12.49); // 12

Number.toFixed

You can set the number of digits that appears after the decimal place with toFixed function. The function returns the string representation of the number as the value. It can be used like this:

const a = 12.8888888888;  
const b = a.toFixed(2); // 12.88

Number.toPrecision

Number.toPrecision is similar to toFixed . It returns the string representation of a number, but you can round it to the specified number of significant digits which you can specify or let it automatically round to the correct number of significant digits.

const a = 12.8888888888;  
const b = a.toPrecision(2); // 13, since 2 significant digits is specified  
const c = a.toPrecision(); // 12.8888888888, since all digits are significant in the original number

Round to the nearest Increment

You can round to the nearest increment up or down you specify:

const roundNumberUp = (num, increment) => {   
  return Math.ceil(num / increment) \* increment;  
}  
console.log(roundNumberUp(12.2, 0.5)) // 12.5

What this does is take the original number, divide by the increment you want to round up to, then take the ceiling of that, then multiply by the increment. This means the number should always round up.

Similarly, you can round down to the nearest increment with floor.

const roundNumberUp = (num, increment) => {   
  return Math.floor(num / increment) \* increment;  
}  
console.log(roundNumberUp(12.2, 0.5)) // 12.5

What this does is take the original number, divide by the increment you want to round up to, then take the floor of that, then multiply by the increment. This means the number should always round down.