Skip to content

Commit 21ed1fd

Browse files
committed
1.1.0
1 parent 09b3139 commit 21ed1fd

5 files changed

Lines changed: 124 additions & 2 deletions

File tree

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@vtfk/utilities",
3-
"version": "1.0.0",
3+
"version": "1.1.0",
44
"description": "A collection of uncategorized javascript functionality used in multiple projects",
55
"main": "index.js",
66
"scripts": {
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
const { formatRelativeDate } = require('../../util/relative-date-format')
2+
3+
/* formatRelativeDate(new Date(), new Date(), 'en', {
4+
5+
}) */
6+
7+
describe('formatRelativeDate', () => {
8+
test('no arguments passed - should throw error', () => {
9+
expect(() => formatRelativeDate()).toThrow()
10+
})
11+
12+
describe('toDate passed as seven days ahead', () => {
13+
test('and locale default as "en" - should return "in 7 days"', () => {
14+
const futureDate = new Date(new Date().setDate(new Date().getDate() + 7))
15+
const formatted = formatRelativeDate(futureDate)
16+
expect(formatted).toBe('in 7 days' || 'in 1 week')
17+
})
18+
19+
test('and locale passed as "no" - should return "om 1 uke"', () => {
20+
const futureDate = new Date(new Date().setDate(new Date().getDate() + 7))
21+
const formatted = formatRelativeDate(futureDate, new Date(), 'no')
22+
expect(formatted).toBe('om 1 uke' || 'om 7 døgn')
23+
})
24+
25+
describe('numeric passed as', () => {
26+
test('"auto" - should return "next week" or "in 7 days"', () => {
27+
const futureDate = new Date(new Date().setDate(new Date().getDate() + 7))
28+
const formatted = formatRelativeDate(futureDate, new Date(), 'en', { numeric: 'auto' })
29+
expect(formatted).toBe('next week' || 'in 7 days')
30+
})
31+
32+
test('"always" - should return "in 1 week"', () => {
33+
const futureDate = new Date(new Date().setDate(new Date().getDate() + 7))
34+
const formatted = formatRelativeDate(futureDate, new Date(), 'en', { numeric: 'always' })
35+
expect(formatted).toBe('in 1 week')
36+
})
37+
})
38+
39+
describe('style passed as', () => {
40+
test('"long" - should return "in 1 week"', () => {
41+
const futureDate = new Date(new Date().setDate(new Date().getDate() + 7))
42+
const formatted = formatRelativeDate(futureDate, new Date(), 'en', { style: 'long' })
43+
expect(formatted).toBe('in 1 week')
44+
})
45+
46+
test('"short" - should return "in 1 wk."', () => {
47+
const futureDate = new Date(new Date().setDate(new Date().getDate() + 7))
48+
const formatted = formatRelativeDate(futureDate, new Date(), 'en', { style: 'short' })
49+
expect(formatted).toBe('in 1 wk.')
50+
})
51+
52+
test('"narrow" - should return "in 1 wk." or "in 7 days"', () => {
53+
const futureDate = new Date(new Date().setDate(new Date().getDate() + 7))
54+
const formatted = formatRelativeDate(futureDate, new Date(), 'en', { style: 'narrow' })
55+
expect(formatted).toBe('in 1 wk.' || 'in 7 days')
56+
})
57+
})
58+
})
59+
})

util/relative-date-format.d.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
export function formatRelativeDate(toDate: Date, fromDate?: Date, locale?: string, options?: any): string;
2+
/**
3+
* RelativeTimeFormat options
4+
*/
5+
export type RelativeTimeFormatOptions = {
6+
/**
7+
* "Always" use numeric values or "auto" choose value
8+
*/
9+
numeric?: "always" | "auto";
10+
/**
11+
* "long" time style, "short" time style or "narrow" time style
12+
*/
13+
style?: "long" | "short" | "narrow";
14+
};

util/relative-date-format.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
const DIVISIONS = [
2+
{ amount: 60, name: 'seconds' },
3+
{ amount: 60, name: 'minutes' },
4+
{ amount: 24, name: 'hours' },
5+
{ amount: 7, name: 'days' },
6+
{ amount: 4.34524, name: 'weeks' },
7+
{ amount: 12, name: 'months' },
8+
{ amount: Number.POSITIVE_INFINITY, name: 'years' }
9+
]
10+
11+
/**
12+
* RelativeTimeFormat options
13+
* @typedef {Object} RelativeTimeFormatOptions
14+
* @property {"always"|"auto"} [numeric] "Always" use numeric values or "auto" choose value
15+
* @property {"long"|"short"|"narrow"} [style] "long" time style, "short" time style or "narrow" time style
16+
*/
17+
18+
/**
19+
* Format number into relative time
20+
* @param {String} locale Locale to format into - (Default = en)
21+
* @param {RelativeTimeFormatOptions} options RelativeTimeFormat options
22+
* @returns Formatted string
23+
*/
24+
const getRelativeTimeFormatter = (locale, options) => {
25+
return new Intl.RelativeTimeFormat(locale, options)
26+
}
27+
28+
/**
29+
* Formats the duratio between two dates into a relative time
30+
* @param {Date} toDate Date object to format relative date from
31+
* @param {Date} fromDate (optional) Date object to be starting point (Default = new Date())
32+
* @param {String} locale Locale to format date into
33+
* @param {Object} options RelativeTimeFormat options
34+
* @returns The formatted string
35+
*/
36+
module.exports.formatRelativeDate = (toDate, fromDate = new Date(), locale = 'en', options = undefined) => {
37+
if (toDate === null || toDate === undefined) throw new Error('Pass at least "toDate"')
38+
39+
const FORMATTER = getRelativeTimeFormatter(locale, options)
40+
let duration = (toDate - fromDate) / 1000
41+
42+
for (let i = 0; i < DIVISIONS.length; i++) {
43+
const division = DIVISIONS[i]
44+
if (Math.abs(duration) < division.amount) {
45+
return FORMATTER.format(Math.round(duration), division.name)
46+
}
47+
duration /= division.amount
48+
}
49+
}

0 commit comments

Comments
 (0)