Skip to content

Instantly share code, notes, and snippets.

@joseluisq
Last active February 27, 2018 08:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joseluisq/f84b1d7d08363bda943e80856f650974 to your computer and use it in GitHub Desktop.
Save joseluisq/f84b1d7d08363bda943e80856f650974 to your computer and use it in GitHub Desktop.
Date utility functions based on `node-time`, `dateFormat` and `date-fns` packages.
const time = require('time')(Date)
const dateFormat = require('dateformat')
const TIMEZONE_DEFAULT = 'UTC'
const MILLISECONDS_IN_MINUTE = 60000
const MILLISECONDS_IN_DAY = 86400000
/**
* Date utility functions based on `node-time`, `dateFormat` and `date-fns` packages.
*
* @returns {Object}
*/
function dateHelper (defaultTimezone = TIMEZONE_DEFAULT) {
return {
now,
addDays,
addMonths,
addYears,
getDaysInMonth,
subDays,
parse,
toUTC,
format,
toMySQL,
startOfDay,
startOfMonth,
differenceInCalendarDays,
differenceInCalendarMonths,
differenceInCalendarYears
}
/**
* Return the current Date object
*
* @param {String} timezone Default 'UTC'
* @returns {Date}
*/
function now (timezone = defaultTimezone) {
const now = new time.Date()
now.setTimezone(timezone)
return now
}
/**
* Return a new Date object from some string or date
*
* @param {String|Date} date
* @param {String} timezone Default 'UTC'
* @returns {Date}
*/
function parse (date, timezone = defaultTimezone) {
return new time.Date(date, timezone)
}
/**
* Add the specified number of days to the given date
*
* @param {String|Date} date
* @param {Number} days
* @param {String} timezone
* @returns {Date}
*/
function addDays (date, days = 0, timezone = defaultTimezone) {
const daten = new time.Date(date, timezone)
const amount = asNumber(days)
daten.setDate(date.getDate() + amount)
return daten
}
/**
* Subtract the specified number of days to the given date
*
* @param {String|Date} date
* @param {Number} days
* @param {String} timezone
* @returns {Date}
*/
function subDays (date, days = 0, timezone = defaultTimezone) {
const amount = asNumber(days)
return addDays(date, -amount, timezone)
}
/**
* Return a new UTC Date object from some string or date
*
* @param {String|Date} date
* @returns {Date}
*/
function toUTC (date) {
return parse(date, 'UTC')
}
/**
* Gets a format DateTime string
*
* @param {Date} date
* @param {String} format
* @returns {String}
*/
function format (date, format = 'yyyy-mm-ddTHH:MM:ss') {
return dateFormat(date, format)
}
/**
* Format a Date to MySQL DateTime format
*
* @param {Date} date
* @returns {String}
*/
function toMySQL (date) {
return format(date, 'yyyy-mm-dd HH:MM:ss')
}
/**
* Return the start of a day for the given date.
*
* @link date-fns/src/differenceInCalendarDays/index.js
* @param {Date} dateLeft
* @param {Date} dateRight
* @returns {Date}
*/
function differenceInCalendarDays (dateLeft, dateRight) {
const startOfDayLeft = startOfDay(dateLeft)
const startOfDayRight = startOfDay(dateRight)
const timestampLeft = startOfDayLeft.getTime() - startOfDayLeft.getTimezoneOffset() * MILLISECONDS_IN_MINUTE
const timestampRight = startOfDayRight.getTime() - startOfDayRight.getTimezoneOffset() * MILLISECONDS_IN_MINUTE
// Round the number of days to the nearest integer
// because the number of milliseconds in a day is not constant
// (e.g. it's different in the day of the daylight saving time clock shift)
return Math.round((timestampLeft - timestampRight) / MILLISECONDS_IN_DAY)
}
/**
* Get the number of calendar months between the given dates.
*
* @link date-fns/src/differenceInCalendarMonths/index.js
* @param {Date} dateLeft
* @param {Date} dateRight
* @returns {Date}
*/
function differenceInCalendarMonths (dateLeft, dateRight) {
const yearDiff = dateLeft.getFullYear() - dateRight.getFullYear()
const monthDiff = dateLeft.getMonth() - dateRight.getMonth()
return yearDiff * 12 + monthDiff
}
/**
* Get the number of calendar months between the given dates.
*
* @link date-fns/src/differenceInCalendarYears/index.js
* @param {Date} dateLeft
* @param {Date} dateRight
* @returns {Date}
*/
function differenceInCalendarYears (dateLeft, dateRight) {
return dateLeft.getFullYear() - dateRight.getFullYear()
}
/**
* Return the start of a day for the given date.
*
* @param {Date} date
* @returns {Date}
*/
function startOfDay (date) {
const daten = new time.Date(date)
daten.setHours(0, 0, 0, 0)
return daten
}
/**
* Return the start of a day for the given date.
*
* @param {Date} date
* @returns {Date}
*/
function startOfMonth (date) {
const daten = new time.Date(date)
daten.setDate(1)
daten.setHours(0, 0, 0, 0)
return daten
}
/**
* Get the number of days in a month of the given date.
*
* @link date-fns/src/getDaysInMonth/index.js
* @param {Date} date
* @returns {Date}
*/
function getDaysInMonth (date) {
const year = date.getFullYear()
const monthIndex = date.getMonth()
const lastDayOfMonth = new time.Date(0)
lastDayOfMonth.setFullYear(year, monthIndex + 1, 0)
lastDayOfMonth.setHours(0, 0, 0, 0)
return lastDayOfMonth.getDate()
}
/**
* Add the specified number of months to the given date.
*
* @link date-fns/src/addMonths/index.js
* @param {Date} date
* @param {Number} amount
* @param {String} timezone
* @returns {Date}
*/
function addMonths (date, amount = 0, timezone = defaultTimezone) {
const daten = new time.Date(date, timezone)
const amountn = asNumber(amount)
const months = daten.getMonth() + amountn
const dateWithDesiredMonth = new time.Date(0)
dateWithDesiredMonth.setFullYear(daten.getFullYear(), months, 1)
dateWithDesiredMonth.setHours(0, 0, 0, 0)
const daysInMonth = getDaysInMonth(dateWithDesiredMonth)
daten.setMonth(months, Math.min(daysInMonth, daten.getDate()))
return daten
}
/**
* Add the specified number of years to the given date.
*
* @link date-fns/src/addYears/index.js
* @param {Date} date
* @param {Number} amount
* @param {String} timezone
* @returns {Date}
*/
function addYears (date, amount = 0, timezone = defaultTimezone) {
const amountn = asNumber(amount)
return addMonths(date, amountn * 12, timezone)
}
}
/**
* Verify a value and return Number value
*
* @param {String|Object|Array} value
* @returns {Number}
*/
function asNumber (value = 0) {
return isNaN(Number(value)) ? 0 : Number(value)
}
module.exports = dateHelper
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment