Merge pull request #6333 from LenaBarinova/fix/streak-seems-broken-because-of-timezone
Fixed streak and completion dates to be showed using users timezone
This commit is contained in:
@ -18,6 +18,7 @@
|
||||
"bootstrap": "~3.3.4",
|
||||
"font-awesome": "~4.3.0",
|
||||
"moment": "~2.10.2",
|
||||
"moment-timezone": "~0.5.0",
|
||||
"jshint": "~2.9.0",
|
||||
"lightbox2": "~2.8.1",
|
||||
"rxjs": "~4.0.6",
|
||||
|
@ -1,6 +1,7 @@
|
||||
window.common = (function(global) {
|
||||
const {
|
||||
$,
|
||||
moment,
|
||||
ga = (() => {}),
|
||||
common = { init: [] }
|
||||
} = global;
|
||||
@ -51,7 +52,8 @@ window.common = (function(global) {
|
||||
name: common.challengeName,
|
||||
completedWith: didCompleteWith,
|
||||
challengeType: common.challengeType,
|
||||
solution
|
||||
solution,
|
||||
timezone: moment.tz.guess()
|
||||
};
|
||||
|
||||
$.post('/completed-challenge/', data, function(res) {
|
||||
|
@ -173,6 +173,9 @@
|
||||
},
|
||||
"tshirtVote": {
|
||||
"type": "number"
|
||||
},
|
||||
"timezone": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"validations": [],
|
||||
|
@ -99,6 +99,7 @@ var paths = {
|
||||
'public/bower_components/bootstrap/dist/js/bootstrap.min.js',
|
||||
'public/bower_components/d3/d3.min.js',
|
||||
'public/bower_components/moment/min/moment.min.js',
|
||||
'public/bower_components/moment-timezone/builds/moment-timezone-with-data.min.js',
|
||||
'public/bower_components/mousetrap/mousetrap.min.js',
|
||||
'public/bower_components/lightbox2/dist/js/lightbox.min.js',
|
||||
'public/bower_components/rxjs/dist/rx.all.min.js'
|
||||
|
@ -94,6 +94,7 @@
|
||||
"merge-stream": "^1.0.0",
|
||||
"method-override": "^2.3.0",
|
||||
"moment": "^2.10.2",
|
||||
"moment-timezone": "^0.5.0",
|
||||
"mongodb": "^2.0.33",
|
||||
"morgan": "^1.6.1",
|
||||
"node-uuid": "^1.4.3",
|
||||
|
@ -505,7 +505,8 @@ module.exports = function(app) {
|
||||
id,
|
||||
name,
|
||||
challengeType,
|
||||
solution
|
||||
solution,
|
||||
timezone
|
||||
} = req.body;
|
||||
|
||||
const { alreadyCompleted } = updateUserProgress(
|
||||
@ -521,6 +522,10 @@ module.exports = function(app) {
|
||||
}
|
||||
);
|
||||
|
||||
if (timezone && (!req.user.timezone || req.user.timezone != timezone)) {
|
||||
req.user.timezone = timezone;
|
||||
}
|
||||
|
||||
let user = req.user;
|
||||
saveUser(req.user)
|
||||
.subscribe(
|
||||
|
@ -1,6 +1,6 @@
|
||||
import _ from 'lodash';
|
||||
import dedent from 'dedent';
|
||||
import moment from 'moment';
|
||||
import moment from 'moment-timezone';
|
||||
import { Observable } from 'rx';
|
||||
import debugFactory from 'debug';
|
||||
|
||||
@ -38,6 +38,8 @@ const certText = {
|
||||
[certTypes.fullStack]: 'Full Stack Certified'
|
||||
};
|
||||
|
||||
const dateFormat = 'MMM DD, YYYY';
|
||||
|
||||
function replaceScriptTags(value) {
|
||||
return value
|
||||
.replace(/<script>/gi, 'fccss')
|
||||
@ -183,6 +185,12 @@ module.exports = function(app) {
|
||||
}
|
||||
profileUser = profileUser.toJSON();
|
||||
|
||||
// timezone of signed-in account
|
||||
// to show all date related components
|
||||
// using signed-in account's timezone
|
||||
// not of the profile she is viewing
|
||||
const timezone = req.user && req.user.timezone ? req.user.timezone : 'UTC';
|
||||
|
||||
var cals = profileUser
|
||||
.progressTimestamps
|
||||
.map(objOrNum => {
|
||||
@ -192,8 +200,8 @@ module.exports = function(app) {
|
||||
})
|
||||
.sort();
|
||||
|
||||
profileUser.currentStreak = calcCurrentStreak(cals);
|
||||
profileUser.longestStreak = calcLongestStreak(cals);
|
||||
profileUser.currentStreak = calcCurrentStreak(cals, timezone);
|
||||
profileUser.longestStreak = calcLongestStreak(cals, timezone);
|
||||
|
||||
const data = profileUser
|
||||
.progressTimestamps
|
||||
@ -223,9 +231,20 @@ module.exports = function(app) {
|
||||
+challenge.challengeType === 4;
|
||||
}
|
||||
|
||||
const completedChallenges = profileUser.completedChallenges.filter(
|
||||
({ name }) => typeof name === 'string'
|
||||
);
|
||||
const completedChallenges = profileUser.completedChallenges
|
||||
.filter(({ name }) => typeof name === 'string')
|
||||
.map(challenge => {
|
||||
challenge = { ...challenge };
|
||||
if (challenge.completedDate) {
|
||||
challenge.completedDate =
|
||||
moment.tz(challenge.completedDate, timezone).format(dateFormat);
|
||||
}
|
||||
if (challenge.lastUpdated) {
|
||||
challenge.lastUpdated =
|
||||
moment.tz(challenge.lastUpdated, timezone).format(dateFormat);
|
||||
}
|
||||
return challenge;
|
||||
});
|
||||
|
||||
const projects = completedChallenges.filter(filterProjects);
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
import moment from 'moment';
|
||||
import moment from 'moment-timezone';
|
||||
|
||||
// day count between two epochs (inclusive)
|
||||
export function dayCount([head, tail]) {
|
||||
export function dayCount([head, tail], timezone = 'UTC') {
|
||||
return Math.ceil(
|
||||
moment(moment(head).endOf('day')).diff(
|
||||
moment(tail).startOf('day'),
|
||||
moment(moment(head).tz(timezone).endOf('day')).tz(timezone).diff(
|
||||
moment(tail).tz(timezone).startOf('day'),
|
||||
'days',
|
||||
true)
|
||||
);
|
||||
|
@ -1,12 +1,12 @@
|
||||
import moment from 'moment';
|
||||
import moment from 'moment-timezone';
|
||||
import { dayCount } from '../utils/date-utils';
|
||||
|
||||
const daysBetween = 1.5;
|
||||
|
||||
export function calcCurrentStreak(cals) {
|
||||
export function calcCurrentStreak(cals, timezone = 'UTC') {
|
||||
const revCals = cals.slice().reverse();
|
||||
|
||||
if (dayCount([moment(), revCals[0]]) > daysBetween) {
|
||||
if (dayCount([moment().tz(timezone), revCals[0]], timezone) > daysBetween) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@ export function calcCurrentStreak(cals) {
|
||||
const before = revCals[index === 0 ? 0 : index - 1];
|
||||
if (
|
||||
!streakBroken &&
|
||||
moment(before).diff(cal, 'days', true) < daysBetween
|
||||
moment(before).tz(timezone).diff(cal, 'days', true) < daysBetween
|
||||
) {
|
||||
return index;
|
||||
}
|
||||
@ -25,22 +25,22 @@ export function calcCurrentStreak(cals) {
|
||||
}, 0);
|
||||
|
||||
const lastTimestamp = revCals[lastDayInStreak];
|
||||
return dayCount([moment(), lastTimestamp]);
|
||||
return dayCount([moment().tz(timezone), lastTimestamp], timezone);
|
||||
}
|
||||
|
||||
export function calcLongestStreak(cals) {
|
||||
export function calcLongestStreak(cals, timezone = 'UTC') {
|
||||
let tail = cals[0];
|
||||
const longest = cals.reduce((longest, head, index) => {
|
||||
const last = cals[index === 0 ? 0 : index - 1];
|
||||
// is streak broken
|
||||
if (moment(head).diff(last, 'days', true) > daysBetween) {
|
||||
if (moment(head).tz(timezone).diff(last, 'days', true) > daysBetween) {
|
||||
tail = head;
|
||||
}
|
||||
if (dayCount(longest) < dayCount([head, tail])) {
|
||||
if (dayCount(longest, timezone) < dayCount([head, tail], timezone)) {
|
||||
return [head, tail];
|
||||
}
|
||||
return longest;
|
||||
}, [cals[0], cals[0]]);
|
||||
|
||||
return dayCount(longest);
|
||||
return dayCount(longest, timezone);
|
||||
}
|
||||
|
@ -134,8 +134,8 @@ block content
|
||||
tr
|
||||
td.col-xs-5.hidden-xs
|
||||
a(href='/challenges/' + removeOldTerms(challenge.name), target='_blank')= removeOldTerms(challenge.name)
|
||||
td.col-xs-2.hidden-xs= challenge.completedDate ? moment(challenge.completedDate, 'x').format("MMM DD, YYYY") : 'Not Available'
|
||||
td.col-xs-2.hidden-xs= challenge.lastUpdated ? moment(challenge.lastUpdated, 'x').format("MMM DD, YYYY") : ''
|
||||
td.col-xs-2.hidden-xs= challenge.completedDate ? challenge.completedDate : 'Not Available'
|
||||
td.col-xs-2.hidden-xs= challenge.lastUpdated ? challenge.lastUpdated : ''
|
||||
td.col-xs-2.hidden-xs
|
||||
a(href=challenge.solution, target='_blank') View my project
|
||||
td.col-xs-12.visible-xs
|
||||
@ -152,8 +152,8 @@ block content
|
||||
for challenge in algos
|
||||
tr
|
||||
td.col-xs-5.hidden-xs= removeOldTerms(challenge.name)
|
||||
td.col-xs-2.hidden-xs= challenge.completedDate ? moment(challenge.completedDate, 'x').format("MMM DD, YYYY") : 'Not Available'
|
||||
td.col-xs-2.hidden-xs= challenge.lastUpdated ? moment(challenge.lastUpdated, 'x').format("MMM DD, YYYY") : ''
|
||||
td.col-xs-2.hidden-xs= challenge.completedDate ? challenge.completedDate : 'Not Available'
|
||||
td.col-xs-2.hidden-xs= challenge.lastUpdated ? challenge.lastUpdated : ''
|
||||
td.col-xs-2.hidden-xs
|
||||
if (challenge.solution)
|
||||
a(href='/challenges/' + removeOldTerms(challenge.name) + '?solution=' + encodeURIComponent(encodeFcc(challenge.solution)), target='_blank') View my solution
|
||||
@ -176,8 +176,8 @@ block content
|
||||
for challenge in challenges
|
||||
tr
|
||||
td.col-xs-5.hidden-xs= removeOldTerms(challenge.name)
|
||||
td.col-xs-2.hidden-xs= challenge.completedDate ?moment(challenge.completedDate, 'x').format("MMM DD, YYYY") : 'Not Available'
|
||||
td.col-xs-2.hidden-xs= challenge.lastUpdated ? moment(challenge.lastUpdated, 'x').format("MMM DD, YYYY") : ''
|
||||
td.col-xs-2.hidden-xs= challenge.completedDate ? challenge.completedDate : 'Not Available'
|
||||
td.col-xs-2.hidden-xs= challenge.lastUpdated ? challenge.lastUpdated : ''
|
||||
td.col-xs-2.hidden-xs
|
||||
if (challenge.solution)
|
||||
a(href='/challenges/' + removeOldTerms(challenge.name) + '?solution=' + encodeURIComponent(encodeFcc(challenge.solution)), target='_blank') View my solution
|
||||
|
@ -1,34 +1,44 @@
|
||||
import moment from 'moment';
|
||||
import moment from 'moment-timezone';
|
||||
|
||||
import { dayCount } from '../../../server/utils/date-utils';
|
||||
|
||||
let test = require('tape');
|
||||
|
||||
test('Day count between two epochs (inclusive) calculation', function (t) {
|
||||
t.plan(5);
|
||||
t.plan(7);
|
||||
|
||||
t.equal(dayCount([
|
||||
moment("8/3/2015 3:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("8/3/2015 2:00", "M/D/YYYY H:mm").valueOf()
|
||||
moment.utc("8/3/2015 3:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("8/3/2015 2:00", "M/D/YYYY H:mm").valueOf()
|
||||
]), 1, "should return 1 day given epochs of the same day");
|
||||
|
||||
t.equal(dayCount([
|
||||
moment("8/3/2015 2:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("8/3/2015 2:00", "M/D/YYYY H:mm").valueOf()
|
||||
moment.utc("8/3/2015 2:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("8/3/2015 2:00", "M/D/YYYY H:mm").valueOf()
|
||||
]), 1, "should return 1 day given same epochs");
|
||||
|
||||
t.equal(dayCount([
|
||||
moment("8/4/2015 2:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("8/3/2015 2:00", "M/D/YYYY H:mm").valueOf()
|
||||
moment.utc("8/4/2015 2:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("8/3/2015 2:00", "M/D/YYYY H:mm").valueOf()
|
||||
]), 2, "should return 2 days when there is a 24 hours difference between given dates");
|
||||
|
||||
t.equal(dayCount([
|
||||
moment("8/4/2015 1:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("8/3/2015 23:00", "M/D/YYYY H:mm").valueOf()
|
||||
]), 2, "should return 2 days when the diff is less than 24h but days of the month are different");
|
||||
moment.utc("8/4/2015 1:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("8/3/2015 23:00", "M/D/YYYY H:mm").valueOf()
|
||||
]), 2, "should return 2 days when the diff is less than 24h but days are different in default timezone UTC");
|
||||
|
||||
t.equal(dayCount([
|
||||
moment("10/27/2015 1:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("5/12/1982 1:00", "M/D/YYYY H:mm").valueOf()
|
||||
moment.utc("8/4/2015 1:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("8/3/2015 23:00", "M/D/YYYY H:mm").valueOf()
|
||||
], 'America/Los_Angeles'), 1, "should return 1 day when the diff is less than 24h and days are different in UTC, but given 'America/Los_Angeles' timezone");
|
||||
|
||||
t.equal(dayCount([
|
||||
moment.utc("10/27/2015 1:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("5/12/1982 1:00", "M/D/YYYY H:mm").valueOf()
|
||||
]), 12222, "should return correct count when there is very big period");
|
||||
|
||||
t.equal(dayCount([
|
||||
moment.utc("8/4/2015 2:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("8/3/2015 2:00", "M/D/YYYY H:mm").valueOf()
|
||||
], undefined), 2, "should return 2 days when there is a 24 hours difference between dates given 'undefined' timezone");
|
||||
});
|
||||
|
@ -1,132 +1,160 @@
|
||||
import moment from 'moment';
|
||||
import moment from 'moment-timezone';
|
||||
|
||||
import { calcCurrentStreak, calcLongestStreak } from '../../../server/utils/user-stats';
|
||||
|
||||
let test = require('tape');
|
||||
|
||||
test('Current streak calculation', function (t) {
|
||||
t.plan(7);
|
||||
t.plan(9);
|
||||
|
||||
t.equal(calcCurrentStreak([
|
||||
moment(moment().subtract(1, 'hours')).valueOf()
|
||||
moment.utc(moment.utc().subtract(1, 'hours')).valueOf()
|
||||
]), 1, "should return 1 day when today one challenge was completed");
|
||||
|
||||
t.equal(calcCurrentStreak([
|
||||
moment(moment().subtract(2, 'hours')).valueOf(),
|
||||
moment(moment().subtract(1, 'hours')).valueOf()
|
||||
]), 1, "should return 1 day when today more than one challenge were completed");
|
||||
moment.utc(moment.utc().subtract(1, 'hours')).valueOf(),
|
||||
moment.utc(moment.utc().subtract(1, 'hours')).valueOf()
|
||||
]), 1, "should return 1 day when today more than one challenge was completed");
|
||||
|
||||
t.equal(calcCurrentStreak([
|
||||
moment("9/11/2015 4:00", "M/D/YYYY H:mm").valueOf()
|
||||
moment.utc("9/11/2015 4:00", "M/D/YYYY H:mm").valueOf()
|
||||
]), 0, "should return 0 day when today 0 challenges were completed");
|
||||
|
||||
t.equal(calcCurrentStreak([
|
||||
moment(moment().subtract(1, 'days')).valueOf(),
|
||||
moment(moment().subtract(1, 'hours')).valueOf()
|
||||
moment.utc(moment.utc().subtract(1, 'days')).valueOf(),
|
||||
moment.utc(moment.utc().subtract(1, 'hours')).valueOf()
|
||||
]), 2, "should return 2 days when today and yesterday challenges were completed");
|
||||
|
||||
t.equal(calcCurrentStreak([
|
||||
moment("8/3/2015 2:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("9/11/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("9/12/2015 1:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("9/12/2015 1:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("9/12/2015 2:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("9/12/2015 3:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("9/13/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("9/14/2015 5:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment(moment().subtract(2, 'days')).valueOf(),
|
||||
moment(moment().subtract(1, 'days')).valueOf(),
|
||||
moment(moment().subtract(1, 'hours')).valueOf()
|
||||
moment.utc("8/3/2015 2:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/11/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/12/2015 1:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/12/2015 1:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/12/2015 2:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/12/2015 3:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/13/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/14/2015 5:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc(moment.utc().subtract(2, 'days')).valueOf(),
|
||||
moment.utc(moment.utc().subtract(1, 'days')).valueOf(),
|
||||
moment.utc(moment.utc().subtract(1, 'hours')).valueOf()
|
||||
]), 3, "should return 3 when today and for two days before user was activity");
|
||||
|
||||
t.equal(calcCurrentStreak([
|
||||
moment(moment().subtract(37, 'hours')).valueOf(),
|
||||
moment(moment().subtract(1, 'hours')).valueOf()
|
||||
moment.utc(moment.utc().subtract(37, 'hours')).valueOf(),
|
||||
moment.utc(moment.utc().subtract(1, 'hours')).valueOf()
|
||||
]), 1, "should return 1 when between todays challenge completion and yesterdays there is a 1.5 day (36 hours) long break");
|
||||
|
||||
t.ok(calcCurrentStreak([
|
||||
moment.utc(moment.utc().subtract(35, 'hours')).valueOf(),
|
||||
moment.utc(moment.utc().subtract(1, 'hours')).valueOf()
|
||||
]) >= 2, "should return not less than 2 days when between todays challenge completion and yesterdays there is less than 1.5 day (36 hours) long break");
|
||||
|
||||
t.equal(calcCurrentStreak([
|
||||
moment.utc(moment.utc().subtract(1, 'hours')).valueOf(),
|
||||
moment.utc(moment.utc().subtract(1, 'hours')).valueOf()
|
||||
], undefined), 1, "should return correct count in default timezone UTC given 'undefined' timezone");
|
||||
|
||||
t.equal(calcCurrentStreak([
|
||||
moment(moment().subtract(35, 'hours')).valueOf(),
|
||||
moment(moment().subtract(1, 'hours')).valueOf()
|
||||
]), 2, "should return 2 days when between todays challenge completion and yesterdays there is less than 1.5 day (36 hours) long break");
|
||||
moment.utc(moment.utc().subtract(1, 'days')).valueOf(),
|
||||
moment.utc(moment.utc().subtract(1, 'hours')).valueOf()
|
||||
], 'America/Los_Angeles'), 2, "should return 2 days when today and yesterday challenges were completed given 'America/Los_Angeles' timezone");
|
||||
|
||||
});
|
||||
|
||||
test('Longest streak calculation', function (t) {
|
||||
t.plan(9);
|
||||
t.plan(12);
|
||||
|
||||
t.equal(calcLongestStreak([
|
||||
moment("9/12/2015 4:00", "M/D/YYYY H:mm").valueOf()
|
||||
moment.utc("9/12/2015 4:00", "M/D/YYYY H:mm").valueOf()
|
||||
]), 1, "should return 1 when there is the only one one-day-long streak available");
|
||||
|
||||
t.equal(calcLongestStreak([
|
||||
moment("9/11/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("9/12/2015 2:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("9/13/2015 3:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("9/14/2015 1:00", "M/D/YYYY H:mm").valueOf()
|
||||
moment.utc("9/11/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/12/2015 2:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/13/2015 3:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/14/2015 1:00", "M/D/YYYY H:mm").valueOf()
|
||||
]), 4, "should return 4 when there is the only one more-than-one-days-long streak available");
|
||||
|
||||
t.equal(calcLongestStreak([
|
||||
moment(moment().subtract(1, 'hours')).valueOf()
|
||||
moment.utc(moment.utc().subtract(1, 'hours')).valueOf()
|
||||
]), 1, "should return 1 when there is only one one-day-long streak and it is today");
|
||||
|
||||
t.equal(calcLongestStreak([
|
||||
moment(moment().subtract(1, 'days')).valueOf(),
|
||||
moment(moment().subtract(1, 'hours')).valueOf()
|
||||
moment.utc(moment.utc().subtract(1, 'days')).valueOf(),
|
||||
moment.utc(moment.utc().subtract(1, 'hours')).valueOf()
|
||||
]), 2, "should return 2 when yesterday and today makes longest streak");
|
||||
|
||||
t.equal(calcLongestStreak([
|
||||
moment("8/3/2015 2:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("9/11/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("9/12/2015 2:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("10/4/2015 1:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("10/5/2015 5:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("10/6/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("10/7/2015 5:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("11/3/2015 2:00", "M/D/YYYY H:mm").valueOf()
|
||||
moment.utc("8/3/2015 2:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/11/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/12/2015 2:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("10/4/2015 1:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("10/5/2015 5:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("10/6/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("10/7/2015 5:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("11/3/2015 2:00", "M/D/YYYY H:mm").valueOf()
|
||||
]), 4, "should return 4 when there is a month long break");
|
||||
|
||||
t.equal(calcLongestStreak([
|
||||
moment("8/3/2015 2:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("9/11/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("9/12/2015 1:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment(moment("9/12/2015 1:00", "M/D/YYYY H:mm").add(37, 'hours')).valueOf(),
|
||||
moment("9/14/2015 22:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("9/15/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("10/3/2015 2:00", "M/D/YYYY H:mm").valueOf()
|
||||
moment.utc("8/3/2015 2:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/11/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/12/2015 1:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc(moment.utc("9/12/2015 1:00", "M/D/YYYY H:mm").add(37, 'hours')).valueOf(),
|
||||
moment.utc("9/14/2015 22:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/15/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("10/3/2015 2:00", "M/D/YYYY H:mm").valueOf()
|
||||
]), 3, "should return 3 when there is a more than 1.5 days long break of (36 hours)");
|
||||
|
||||
t.equal(calcLongestStreak([
|
||||
moment("8/3/2015 2:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("9/11/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("9/12/2015 1:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("9/12/2015 1:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("9/12/2015 2:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("9/12/2015 3:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("9/13/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("9/14/2015 5:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment(moment().subtract(2, 'days')).valueOf(),
|
||||
moment(moment().subtract(1, 'days')).valueOf(),
|
||||
moment().valueOf()
|
||||
moment.utc("8/3/2015 2:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/11/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/12/2015 1:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/12/2015 1:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/12/2015 2:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/12/2015 3:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/13/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/14/2015 5:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc(moment.utc().subtract(2, 'days')).valueOf(),
|
||||
moment.utc(moment.utc().subtract(1, 'days')).valueOf(),
|
||||
moment.utc().valueOf()
|
||||
]), 4, "should return 4 when the longest streak consist of several same day timestamps");
|
||||
|
||||
t.equal(calcLongestStreak([
|
||||
moment("8/3/2015 2:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("9/11/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("9/12/2015 1:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("9/13/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("9/14/2015 5:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("10/11/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("10/12/2015 1:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("10/13/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment("10/14/2015 5:00", "M/D/YYYY H:mm").valueOf()
|
||||
moment.utc("8/3/2015 2:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/11/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/12/2015 1:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/13/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/14/2015 5:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("10/11/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("10/12/2015 1:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("10/13/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("10/14/2015 5:00", "M/D/YYYY H:mm").valueOf()
|
||||
]), 4, "should return 4 when there are several longest streaks (same length)");
|
||||
|
||||
let cals = [];
|
||||
const n = 100;
|
||||
for (var i = 0; i < n; i++) {
|
||||
cals.push(moment(moment().subtract(i, 'days')).valueOf());
|
||||
cals.push(moment.utc(moment.utc().subtract(i, 'days')).valueOf());
|
||||
}
|
||||
cals.sort();
|
||||
t.equal(calcLongestStreak(cals), n, "should return correct longest streak when there is a very long period");
|
||||
|
||||
|
||||
t.equal(calcLongestStreak([
|
||||
moment.utc(moment.utc().subtract(1, 'days')).valueOf(),
|
||||
moment.utc(moment.utc().subtract(1, 'hours')).valueOf()
|
||||
], undefined), 2, "should return correct longest streak in default timezone UTC given 'undefined' timezone");
|
||||
|
||||
t.equal(calcLongestStreak([
|
||||
moment.utc("9/11/2015 4:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/12/2015 2:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/13/2015 3:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/14/2015 1:00", "M/D/YYYY H:mm").valueOf()
|
||||
], 'America/Los_Angeles'), 4, "should return 4 when there is the only one more-than-one-days-long streak available given 'America/Los_Angeles' timezone");
|
||||
|
||||
t.equal(calcLongestStreak([
|
||||
moment.utc("9/11/2015 23:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/12/2015 2:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/13/2015 2:00", "M/D/YYYY H:mm").valueOf(),
|
||||
moment.utc("9/14/2015 1:00", "M/D/YYYY H:mm").valueOf()
|
||||
], 'America/Los_Angeles'), 3, "should return 3 when longest streak is 3 in given 'America/Los_Angeles' timezone (but would be different in default timezone UTC)");
|
||||
});
|
||||
|
Reference in New Issue
Block a user