Commit f9c28dc2 authored by Kushal Pandya's avatar Kushal Pandya

Add pretty_time methods

Adds methods from `app/assets/javascripts/lib/utils/pretty_time.js`
and deletes the file
parent 886e5d47
import $ from 'jquery'; import $ from 'jquery';
import _ from 'underscore';
import timeago from 'timeago.js'; import timeago from 'timeago.js';
import dateFormat from 'dateformat'; import dateFormat from 'dateformat';
import { pluralize } from './text_utility'; import { pluralize } from './text_utility';
...@@ -417,3 +418,55 @@ export const pikadayToString = date => { ...@@ -417,3 +418,55 @@ export const pikadayToString = date => {
return `${year}-${month}-${day}`; return `${year}-${month}-${day}`;
}; };
/**
* Accepts seconds and returns a timeObject { weeks: #, days: #, hours: #, minutes: # }
* Seconds can be negative or positive, zero or non-zero. Can be configured for any day
* or week length.
*/
export const parseSeconds = (seconds, { daysPerWeek = 5, hoursPerDay = 8 } = {}) => {
const DAYS_PER_WEEK = daysPerWeek;
const HOURS_PER_DAY = hoursPerDay;
const MINUTES_PER_HOUR = 60;
const MINUTES_PER_WEEK = DAYS_PER_WEEK * HOURS_PER_DAY * MINUTES_PER_HOUR;
const MINUTES_PER_DAY = HOURS_PER_DAY * MINUTES_PER_HOUR;
const timePeriodConstraints = {
weeks: MINUTES_PER_WEEK,
days: MINUTES_PER_DAY,
hours: MINUTES_PER_HOUR,
minutes: 1,
};
let unorderedMinutes = Math.abs(seconds / MINUTES_PER_HOUR);
return _.mapObject(timePeriodConstraints, minutesPerPeriod => {
const periodCount = Math.floor(unorderedMinutes / minutesPerPeriod);
unorderedMinutes -= periodCount * minutesPerPeriod;
return periodCount;
});
}
/**
* Accepts a timeObject (see parseSeconds) and returns a condensed string representation of it
* (e.g. '1w 2d 3h 1m' or '1h 30m'). Zero value units are not included.
*/
export const stringifyTime = (timeObject) => {
const reducedTime = _.reduce(
timeObject,
(memo, unitValue, unitName) => {
const isNonZero = !!unitValue;
return isNonZero ? `${memo} ${unitValue}${unitName.charAt(0)}` : memo;
},
'',
).trim();
return reducedTime.length ? reducedTime : '0m';
}
/**
* Accepts a time string of any size (e.g. '1w 2d 3h 5m' or '1w 2d') and returns
* the first non-zero unit/value pair.
*/
export const abbreviateTime = (timeStr) => timeStr.split(' ').filter(unitStr => unitStr.charAt(0) !== '0')[0];
import _ from 'underscore';
/*
* TODO: Make these methods more configurable (e.g. stringifyTime condensed or
* non-condensed, abbreviateTimelengths)
* */
/*
* Accepts seconds and returns a timeObject { weeks: #, days: #, hours: #, minutes: # }
* Seconds can be negative or positive, zero or non-zero. Can be configured for any day
* or week length.
*/
export function parseSeconds(seconds, { daysPerWeek = 5, hoursPerDay = 8 } = {}) {
const DAYS_PER_WEEK = daysPerWeek;
const HOURS_PER_DAY = hoursPerDay;
const MINUTES_PER_HOUR = 60;
const MINUTES_PER_WEEK = DAYS_PER_WEEK * HOURS_PER_DAY * MINUTES_PER_HOUR;
const MINUTES_PER_DAY = HOURS_PER_DAY * MINUTES_PER_HOUR;
const timePeriodConstraints = {
weeks: MINUTES_PER_WEEK,
days: MINUTES_PER_DAY,
hours: MINUTES_PER_HOUR,
minutes: 1,
};
let unorderedMinutes = Math.abs(seconds / MINUTES_PER_HOUR);
return _.mapObject(timePeriodConstraints, minutesPerPeriod => {
const periodCount = Math.floor(unorderedMinutes / minutesPerPeriod);
unorderedMinutes -= periodCount * minutesPerPeriod;
return periodCount;
});
}
/*
* Accepts a timeObject (see parseSeconds) and returns a condensed string representation of it
* (e.g. '1w 2d 3h 1m' or '1h 30m'). Zero value units are not included.
*/
export function stringifyTime(timeObject) {
const reducedTime = _.reduce(
timeObject,
(memo, unitValue, unitName) => {
const isNonZero = !!unitValue;
return isNonZero ? `${memo} ${unitValue}${unitName.charAt(0)}` : memo;
},
'',
).trim();
return reducedTime.length ? reducedTime : '0m';
}
/*
* Accepts a time string of any size (e.g. '1w 2d 3h 5m' or '1w 2d') and returns
* the first non-zero unit/value pair.
*/
export function abbreviateTime(timeStr) {
return timeStr.split(' ').filter(unitStr => unitStr.charAt(0) !== '0')[0];
}
...@@ -218,3 +218,137 @@ describe('datefix', () => { ...@@ -218,3 +218,137 @@ describe('datefix', () => {
}); });
}); });
}); });
describe('prettyTime methods', () => {
const assertTimeUnits = (obj, minutes, hours, days, weeks) => {
expect(obj.minutes).toBe(minutes);
expect(obj.hours).toBe(hours);
expect(obj.days).toBe(days);
expect(obj.weeks).toBe(weeks);
}
describe('parseSeconds', () => {
it('should correctly parse a negative value', () => {
const zeroSeconds = datetimeUtility.parseSeconds(-1000);
assertTimeUnits(zeroSeconds, 16, 0, 0, 0);
});
it('should correctly parse a zero value', () => {
const zeroSeconds = datetimeUtility.parseSeconds(0);
assertTimeUnits(zeroSeconds, 0, 0, 0, 0);
});
it('should correctly parse a small non-zero second values', () => {
const subOneMinute = datetimeUtility.parseSeconds(10);
const aboveOneMinute = datetimeUtility.parseSeconds(100);
const manyMinutes = datetimeUtility.parseSeconds(1000);
assertTimeUnits(subOneMinute, 0, 0, 0, 0);
assertTimeUnits(aboveOneMinute, 1, 0, 0, 0);
assertTimeUnits(manyMinutes, 16, 0, 0, 0);
});
it('should correctly parse large second values', () => {
const aboveOneHour = datetimeUtility.parseSeconds(4800);
const aboveOneDay = datetimeUtility.parseSeconds(110000);
const aboveOneWeek = datetimeUtility.parseSeconds(25000000);
assertTimeUnits(aboveOneHour, 20, 1, 0, 0);
assertTimeUnits(aboveOneDay, 33, 6, 3, 0);
assertTimeUnits(aboveOneWeek, 26, 0, 3, 173);
});
it('should correctly accept a custom param for hoursPerDay', () => {
const config = { hoursPerDay: 24 };
const aboveOneHour = datetimeUtility.parseSeconds(4800, config);
const aboveOneDay = datetimeUtility.parseSeconds(110000, config);
const aboveOneWeek = datetimeUtility.parseSeconds(25000000, config);
assertTimeUnits(aboveOneHour, 20, 1, 0, 0);
assertTimeUnits(aboveOneDay, 33, 6, 1, 0);
assertTimeUnits(aboveOneWeek, 26, 8, 4, 57);
});
it('should correctly accept a custom param for daysPerWeek', () => {
const config = { daysPerWeek: 7 };
const aboveOneHour = datetimeUtility.parseSeconds(4800, config);
const aboveOneDay = datetimeUtility.parseSeconds(110000, config);
const aboveOneWeek = datetimeUtility.parseSeconds(25000000, config);
assertTimeUnits(aboveOneHour, 20, 1, 0, 0);
assertTimeUnits(aboveOneDay, 33, 6, 3, 0);
assertTimeUnits(aboveOneWeek, 26, 0, 0, 124);
});
it('should correctly accept custom params for daysPerWeek and hoursPerDay', () => {
const config = { daysPerWeek: 55, hoursPerDay: 14 };
const aboveOneHour = datetimeUtility.parseSeconds(4800, config);
const aboveOneDay = datetimeUtility.parseSeconds(110000, config);
const aboveOneWeek = datetimeUtility.parseSeconds(25000000, config);
assertTimeUnits(aboveOneHour, 20, 1, 0, 0);
assertTimeUnits(aboveOneDay, 33, 2, 2, 0);
assertTimeUnits(aboveOneWeek, 26, 0, 1, 9);
});
});
describe('stringifyTime', () => {
it('should stringify values with all non-zero units', () => {
const timeObject = {
weeks: 1,
days: 4,
hours: 7,
minutes: 20,
};
const timeString = datetimeUtility.stringifyTime(timeObject);
expect(timeString).toBe('1w 4d 7h 20m');
});
it('should stringify values with some non-zero units', () => {
const timeObject = {
weeks: 0,
days: 4,
hours: 0,
minutes: 20,
};
const timeString = datetimeUtility.stringifyTime(timeObject);
expect(timeString).toBe('4d 20m');
});
it('should stringify values with no non-zero units', () => {
const timeObject = {
weeks: 0,
days: 0,
hours: 0,
minutes: 0,
};
const timeString = datetimeUtility.stringifyTime(timeObject);
expect(timeString).toBe('0m');
});
});
describe('abbreviateTime', () => {
it('should abbreviate stringified times for weeks', () => {
const fullTimeString = '1w 3d 4h 5m';
expect(datetimeUtility.abbreviateTime(fullTimeString)).toBe('1w');
});
it('should abbreviate stringified times for non-weeks', () => {
const fullTimeString = '0w 3d 4h 5m';
expect(datetimeUtility.abbreviateTime(fullTimeString)).toBe('3d');
});
});
});
import { parseSeconds, abbreviateTime, stringifyTime } from '~/lib/utils/pretty_time';
function assertTimeUnits(obj, minutes, hours, days, weeks) {
expect(obj.minutes).toBe(minutes);
expect(obj.hours).toBe(hours);
expect(obj.days).toBe(days);
expect(obj.weeks).toBe(weeks);
}
describe('prettyTime methods', () => {
describe('parseSeconds', () => {
it('should correctly parse a negative value', () => {
const zeroSeconds = parseSeconds(-1000);
assertTimeUnits(zeroSeconds, 16, 0, 0, 0);
});
it('should correctly parse a zero value', () => {
const zeroSeconds = parseSeconds(0);
assertTimeUnits(zeroSeconds, 0, 0, 0, 0);
});
it('should correctly parse a small non-zero second values', () => {
const subOneMinute = parseSeconds(10);
const aboveOneMinute = parseSeconds(100);
const manyMinutes = parseSeconds(1000);
assertTimeUnits(subOneMinute, 0, 0, 0, 0);
assertTimeUnits(aboveOneMinute, 1, 0, 0, 0);
assertTimeUnits(manyMinutes, 16, 0, 0, 0);
});
it('should correctly parse large second values', () => {
const aboveOneHour = parseSeconds(4800);
const aboveOneDay = parseSeconds(110000);
const aboveOneWeek = parseSeconds(25000000);
assertTimeUnits(aboveOneHour, 20, 1, 0, 0);
assertTimeUnits(aboveOneDay, 33, 6, 3, 0);
assertTimeUnits(aboveOneWeek, 26, 0, 3, 173);
});
it('should correctly accept a custom param for hoursPerDay', () => {
const config = { hoursPerDay: 24 };
const aboveOneHour = parseSeconds(4800, config);
const aboveOneDay = parseSeconds(110000, config);
const aboveOneWeek = parseSeconds(25000000, config);
assertTimeUnits(aboveOneHour, 20, 1, 0, 0);
assertTimeUnits(aboveOneDay, 33, 6, 1, 0);
assertTimeUnits(aboveOneWeek, 26, 8, 4, 57);
});
it('should correctly accept a custom param for daysPerWeek', () => {
const config = { daysPerWeek: 7 };
const aboveOneHour = parseSeconds(4800, config);
const aboveOneDay = parseSeconds(110000, config);
const aboveOneWeek = parseSeconds(25000000, config);
assertTimeUnits(aboveOneHour, 20, 1, 0, 0);
assertTimeUnits(aboveOneDay, 33, 6, 3, 0);
assertTimeUnits(aboveOneWeek, 26, 0, 0, 124);
});
it('should correctly accept custom params for daysPerWeek and hoursPerDay', () => {
const config = { daysPerWeek: 55, hoursPerDay: 14 };
const aboveOneHour = parseSeconds(4800, config);
const aboveOneDay = parseSeconds(110000, config);
const aboveOneWeek = parseSeconds(25000000, config);
assertTimeUnits(aboveOneHour, 20, 1, 0, 0);
assertTimeUnits(aboveOneDay, 33, 2, 2, 0);
assertTimeUnits(aboveOneWeek, 26, 0, 1, 9);
});
});
describe('stringifyTime', () => {
it('should stringify values with all non-zero units', () => {
const timeObject = {
weeks: 1,
days: 4,
hours: 7,
minutes: 20,
};
const timeString = stringifyTime(timeObject);
expect(timeString).toBe('1w 4d 7h 20m');
});
it('should stringify values with some non-zero units', () => {
const timeObject = {
weeks: 0,
days: 4,
hours: 0,
minutes: 20,
};
const timeString = stringifyTime(timeObject);
expect(timeString).toBe('4d 20m');
});
it('should stringify values with no non-zero units', () => {
const timeObject = {
weeks: 0,
days: 0,
hours: 0,
minutes: 0,
};
const timeString = stringifyTime(timeObject);
expect(timeString).toBe('0m');
});
});
describe('abbreviateTime', () => {
it('should abbreviate stringified times for weeks', () => {
const fullTimeString = '1w 3d 4h 5m';
expect(abbreviateTime(fullTimeString)).toBe('1w');
});
it('should abbreviate stringified times for non-weeks', () => {
const fullTimeString = '0w 3d 4h 5m';
expect(abbreviateTime(fullTimeString)).toBe('3d');
});
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment