@qrohlf/smart-date
Advanced tools
Comparing version 1.0.1 to 1.1.0
54
es5.js
'use strict'; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; | ||
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } | ||
@@ -21,5 +23,10 @@ | ||
function applyDefaults(date, options) { | ||
// if the date being passed in is an ISO8601 string, try to sniff | ||
// whether we should include the time or not based on the presence | ||
// of the 'T' (time) parameter | ||
var includeTime = typeof date === 'string' ? date.includes(' ') || date.includes('T') : true; | ||
var defaults = { | ||
includeTime: date.includes(' ') || date.includes('T'), | ||
includeYear: moment(date).year() !== moment().year() | ||
includeTime: includeTime, | ||
includeYear: moment(date).year() !== moment().year(), | ||
relative: false | ||
}; | ||
@@ -29,2 +36,32 @@ return Object.assign({}, defaults, options); | ||
// given the specific date in question, and the value the caller has given for | ||
// options.relative, return whether the date should be displayed as relative or not | ||
function interpretRelativeOpt(m, relative) { | ||
switch (typeof relative === 'undefined' ? 'undefined' : _typeof(relative)) { | ||
case 'function': | ||
{ | ||
return relative(m); | ||
} | ||
case 'string': | ||
{ | ||
if (!['day', 'week', 'month', 'year'].includes(relative)) { | ||
throw Error('Invalid value `' + relative + '` supplied for options.relative'); | ||
} | ||
var start = moment().subtract(1, relative); | ||
var end = moment().add(1, relative); | ||
return m.isBetween(start, end); | ||
} | ||
case 'boolean': | ||
{ | ||
var _start = moment().subtract(1, 'week'); | ||
var _end = moment().add(1, 'week'); | ||
return relative && m.isBetween(_start, _end); | ||
} | ||
default: | ||
{ | ||
throw Error('Invalid value `' + relative + '` supplied for options.relative'); | ||
} | ||
} | ||
} | ||
function formatSingleDate(date, options) { | ||
@@ -35,4 +72,17 @@ var _applyDefaults = applyDefaults(date, options); | ||
var includeYear = _applyDefaults.includeYear; | ||
var relative = _applyDefaults.relative; | ||
var m = moment(date); | ||
var shouldDisplayRelative = relative && interpretRelativeOpt(m, relative); | ||
if (shouldDisplayRelative) { | ||
var relativeString = m.fromNow(); | ||
switch (relativeString) { | ||
case 'a day ago': | ||
return 'yesterday'; | ||
case 'in a day': | ||
return 'tomorrow'; | ||
default: | ||
return relativeString; | ||
} | ||
} | ||
var format = ['MMMM Do', includeTime && 'h:mm a', includeYear && 'YYYY'].filter(function (f) { | ||
@@ -39,0 +89,0 @@ return f; |
51
index.js
@@ -15,5 +15,12 @@ const moment = require('moment') | ||
function applyDefaults (date, options) { | ||
// if the date being passed in is an ISO8601 string, try to sniff | ||
// whether we should include the time or not based on the presence | ||
// of the 'T' (time) parameter | ||
const includeTime = typeof date === 'string' | ||
? date.includes(' ') || date.includes('T') | ||
: true | ||
const defaults = { | ||
includeTime: date.includes(' ') || date.includes('T'), | ||
includeYear: moment(date).year() !== moment().year() | ||
includeTime, | ||
includeYear: moment(date).year() !== moment().year(), | ||
relative: false | ||
} | ||
@@ -23,5 +30,43 @@ return Object.assign({}, defaults, options) | ||
// given the specific date in question, and the value the caller has given for | ||
// options.relative, return whether the date should be displayed as relative or not | ||
function interpretRelativeOpt (m, relative) { | ||
switch (typeof relative) { | ||
case 'function': { | ||
return relative(m) | ||
} | ||
case 'string': { | ||
if (!['day', 'week', 'month', 'year'].includes(relative)) { | ||
throw Error('Invalid value `' + relative + '` supplied for options.relative') | ||
} | ||
const start = moment().subtract(1, relative) | ||
const end = moment().add(1, relative) | ||
return m.isBetween(start, end) | ||
} | ||
case 'boolean': { | ||
const start = moment().subtract(1, 'week') | ||
const end = moment().add(1, 'week') | ||
return relative && m.isBetween(start, end) | ||
} | ||
default: { | ||
throw Error('Invalid value `' + relative + '` supplied for options.relative') | ||
} | ||
} | ||
} | ||
function formatSingleDate (date, options) { | ||
const {includeTime, includeYear} = applyDefaults(date, options) | ||
const {includeTime, includeYear, relative} = applyDefaults(date, options) | ||
const m = moment(date) | ||
const shouldDisplayRelative = relative && interpretRelativeOpt(m, relative) | ||
if (shouldDisplayRelative) { | ||
const relativeString = m.fromNow() | ||
switch (relativeString) { | ||
case 'a day ago': | ||
return 'yesterday' | ||
case 'in a day': | ||
return 'tomorrow' | ||
default: | ||
return relativeString | ||
} | ||
} | ||
const format = [ | ||
@@ -28,0 +73,0 @@ 'MMMM Do', |
{ | ||
"name": "@qrohlf/smart-date", | ||
"version": "1.0.1", | ||
"version": "1.1.0", | ||
"description": "Takes date objects. Returns sane human-readable strings.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
106
tests.js
@@ -0,7 +1,9 @@ | ||
/* eslint-env mocha */ | ||
const {expect} = require('chai') | ||
const sinon = require('sinon') | ||
const moment = require('moment') | ||
const smartDate = require('./index') | ||
const {formatSingleDate, formatDateRange} = smartDate | ||
const TODAY = '2016-06-30' // may not actually be today tomorrow | ||
const TODAY = '2016-06-30T00:00' // may not actually be today tomorrow | ||
@@ -50,5 +52,93 @@ describe('formatSingleDate', () => { | ||
}) | ||
it('accepts native Date objects', () => { | ||
expect(formatSingleDate(new Date('2016-07-04T00:00'))).to.eql('July 4th, 12:00 am') | ||
}) | ||
it('accepts Moment objects', () => { | ||
expect(formatSingleDate(moment('2016-07-04T00:00'))).to.eql('July 4th, 12:00 am') | ||
}) | ||
describe('relative option', () => { | ||
it('defaults to 1 week for {relative: true}', () => { | ||
expect(formatSingleDate('2016-06-22', {relative: true})).to.eql('June 22nd') | ||
expect(formatSingleDate('2016-06-23', {relative: true})).to.eql('June 23rd') | ||
expect(formatSingleDate('2016-06-24', {relative: true})).to.eql('6 days ago') | ||
expect(formatSingleDate('2016-06-25', {relative: true})).to.eql('5 days ago') | ||
expect(formatSingleDate('2016-06-26', {relative: true})).to.eql('4 days ago') | ||
expect(formatSingleDate('2016-06-27', {relative: true})).to.eql('3 days ago') | ||
expect(formatSingleDate('2016-06-28', {relative: true})).to.eql('2 days ago') | ||
expect(formatSingleDate('2016-06-29', {relative: true})).to.eql('yesterday') | ||
expect(formatSingleDate('2016-07-01', {relative: true})).to.eql('tomorrow') | ||
expect(formatSingleDate('2016-07-02', {relative: true})).to.eql('in 2 days') | ||
expect(formatSingleDate('2016-07-03', {relative: true})).to.eql('in 3 days') | ||
expect(formatSingleDate('2016-07-04', {relative: true})).to.eql('in 4 days') | ||
expect(formatSingleDate('2016-07-05', {relative: true})).to.eql('in 5 days') | ||
expect(formatSingleDate('2016-07-06', {relative: true})).to.eql('in 6 days') | ||
expect(formatSingleDate('2016-07-07', {relative: true})).to.eql('July 7th') | ||
}) | ||
it('supports the `day` option', () => { | ||
const relative = 'day' | ||
expect(formatSingleDate('2016-06-29', {relative})).to.eql('June 29th') | ||
expect(formatSingleDate('2016-06-29T20:50', {relative})).to.eql('3 hours ago') | ||
expect(formatSingleDate('2016-06-29T23:50', {relative})).to.eql('10 minutes ago') | ||
expect(formatSingleDate('2016-06-30T10:00', {relative})).to.eql('in 10 hours') | ||
expect(formatSingleDate('2016-07-01', {relative})).to.eql('July 1st') | ||
}) | ||
it('supports the `week` option', () => { | ||
const relative = 'week' | ||
expect(formatSingleDate('2016-06-22', {relative})).to.eql('June 22nd') | ||
expect(formatSingleDate('2016-06-23', {relative})).to.eql('June 23rd') | ||
expect(formatSingleDate('2016-06-24', {relative})).to.eql('6 days ago') | ||
expect(formatSingleDate('2016-06-25', {relative})).to.eql('5 days ago') | ||
expect(formatSingleDate('2016-06-26', {relative})).to.eql('4 days ago') | ||
expect(formatSingleDate('2016-06-27', {relative})).to.eql('3 days ago') | ||
expect(formatSingleDate('2016-06-28', {relative})).to.eql('2 days ago') | ||
expect(formatSingleDate('2016-06-29', {relative})).to.eql('yesterday') | ||
expect(formatSingleDate('2016-07-01', {relative})).to.eql('tomorrow') | ||
expect(formatSingleDate('2016-07-02', {relative})).to.eql('in 2 days') | ||
expect(formatSingleDate('2016-07-03', {relative})).to.eql('in 3 days') | ||
expect(formatSingleDate('2016-07-04', {relative})).to.eql('in 4 days') | ||
expect(formatSingleDate('2016-07-05', {relative})).to.eql('in 5 days') | ||
expect(formatSingleDate('2016-07-06', {relative})).to.eql('in 6 days') | ||
expect(formatSingleDate('2016-07-07', {relative})).to.eql('July 7th') | ||
}) | ||
it('supports the `month` option', () => { | ||
const relative = 'month' | ||
expect(formatSingleDate('2016-05-30', {relative})).to.eql('May 30th') | ||
expect(formatSingleDate('2016-05-31', {relative})).to.eql('a month ago') | ||
expect(formatSingleDate('2016-06-15', {relative})).to.eql('15 days ago') | ||
expect(formatSingleDate('2016-06-29T23:50', {relative})).to.eql('10 minutes ago') | ||
expect(formatSingleDate('2016-07-15', {relative})).to.eql('in 15 days') | ||
expect(formatSingleDate('2016-07-29', {relative})).to.eql('in a month') | ||
expect(formatSingleDate('2016-07-30', {relative})).to.eql('July 30th') | ||
}) | ||
it('supports the `year` option', () => { | ||
const relative = 'year' | ||
expect(formatSingleDate('2015-05-30', {relative})).to.eql('May 30th, 2015') | ||
expect(formatSingleDate('2016-04-30', {relative})).to.eql('2 months ago') | ||
expect(formatSingleDate('2016-06-15', {relative})).to.eql('15 days ago') | ||
expect(formatSingleDate('2016-06-29T23:50', {relative})).to.eql('10 minutes ago') | ||
expect(formatSingleDate('2016-08-15', {relative})).to.eql('in 2 months') | ||
expect(formatSingleDate('2016-12-29', {relative})).to.eql('in 6 months') | ||
expect(formatSingleDate('2017-07-30', {relative})).to.eql('July 30th, 2017') | ||
}) | ||
it('accepts a custom function {relative: () => bool}', () => { | ||
const isEven = m => (m.date() % 2) === 0 | ||
expect(formatSingleDate('2016-06-22', {relative: isEven})).to.eql('8 days ago') | ||
expect(formatSingleDate('2016-06-23', {relative: isEven})).to.eql('June 23rd') | ||
expect(formatSingleDate('2016-06-24', {relative: isEven})).to.eql('6 days ago') | ||
expect(formatSingleDate('2016-06-25', {relative: isEven})).to.eql('June 25th') | ||
}) | ||
}) | ||
}) | ||
describe('formatDateRange', () => { | ||
let clock | ||
beforeEach(() => { | ||
@@ -139,5 +229,19 @@ clock = sinon.useFakeTimers(new Date(TODAY).getTime()) | ||
}) | ||
it('accepts native Date objects', () => { | ||
expect( | ||
formatDateRange(new Date('2016-07-04T00:00'), new Date('2016-07-05T00:00')) | ||
).to.eql('July 4th, 12:00 am - July 5th, 12:00 am') | ||
}) | ||
it('accepts Moment objects', () => { | ||
expect( | ||
formatDateRange(moment('2016-07-04T00:00'), moment('2016-07-05T00:00')) | ||
).to.eql('July 4th, 12:00 am - July 5th, 12:00 am') | ||
}) | ||
}) | ||
describe('smartDate', () => { | ||
let clock | ||
beforeEach(() => { | ||
@@ -144,0 +248,0 @@ clock = sinon.useFakeTimers(new Date(TODAY).getTime()) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
Found 1 instance in 1 package
20740
427
1
22