From 4b71413f7cbb9543d58f02efb453cd5462f2a3bf Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Sun, 22 May 2022 00:06:44 +0300 Subject: [PATCH] Add lastCompletedVoting function --- app/core/plus.test.ts | 28 +++++++++++++++++++++++++ app/core/plus.ts | 49 +++++++++++++++++++++++++++++++++++++++++++ package-lock.json | 28 ++++++++++++++++++++++++- package.json | 5 ++++- 4 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 app/core/plus.test.ts create mode 100644 app/core/plus.ts diff --git a/app/core/plus.test.ts b/app/core/plus.test.ts new file mode 100644 index 000000000..6e047f217 --- /dev/null +++ b/app/core/plus.test.ts @@ -0,0 +1,28 @@ +import { suite } from "uvu"; +import * as assert from "uvu/assert"; +import { lastCompletedVoting } from "./plus"; + +const LastCompletedVoting = suite("lastCompletedVoting()"); + +LastCompletedVoting("Previous month if voting yet to happen", () => { + assert.equal(lastCompletedVoting(new Date(Date.UTC(2022, 4, 1))), { + month: 3, + year: 2022, + }); +}); + +LastCompletedVoting("Previous month if voting in progress", () => { + assert.equal(lastCompletedVoting(new Date(Date.UTC(2022, 4, 7))), { + month: 3, + year: 2022, + }); +}); + +LastCompletedVoting("Same month if voting over", () => { + assert.equal(lastCompletedVoting(new Date(Date.UTC(2022, 4, 15))), { + month: 4, + year: 2022, + }); +}); + +LastCompletedVoting.run(); diff --git a/app/core/plus.ts b/app/core/plus.ts new file mode 100644 index 000000000..01e9e5dfd --- /dev/null +++ b/app/core/plus.ts @@ -0,0 +1,49 @@ +interface MonthYear { + month: number; + year: number; +} + +export function lastCompletedVoting(now: Date): MonthYear { + const thisMonthsRange = monthsVotingRange({ + month: now.getMonth(), + year: now.getFullYear(), + }); + + if (thisMonthsRange.endDate.getTime() < now.getTime()) { + return { + month: thisMonthsRange.endDate.getMonth(), + year: thisMonthsRange.endDate.getFullYear(), + }; + } + + return previousMonth({ + month: thisMonthsRange.endDate.getMonth(), + year: thisMonthsRange.endDate.getFullYear(), + }); +} + +/** Range of first Friday of a month to the following Monday (this range is when voting is active) */ +function monthsVotingRange({ month, year }: MonthYear) { + const startDate = new Date(Date.UTC(year, month, 1, 10)); + + while (startDate.getDay() !== 5) { + startDate.setDate(startDate.getDate() + 1); + } + + const endDate = new Date(startDate.getTime()); + endDate.setDate(endDate.getDate() + 3); + + return { startDate, endDate }; +} + +function previousMonth(input: MonthYear): MonthYear { + let { month, year } = input; + + month--; + if (month < 0) { + month = 11; + year--; + } + + return { month, year }; +} diff --git a/package-lock.json b/package-lock.json index 821e5f8d4..48722eb2b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44,7 +44,9 @@ "stylelint-order": "^5.0.0", "ts-node": "^10.7.0", "tsconfig-paths": "^4.0.0", - "typescript": "^4.5.5" + "tsm": "^2.2.1", + "typescript": "^4.5.5", + "uvu": "^0.5.3" }, "engines": { "node": ">=14" @@ -13403,6 +13405,21 @@ "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", "dev": true }, + "node_modules/tsm": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tsm/-/tsm-2.2.1.tgz", + "integrity": "sha512-qvJB0baPnxQJolZru11mRgGTdNlx17WqgJnle7eht3Vhb+VUR4/zFA5hFl6NqRe7m8BD9w/6yu0B2XciRrdoJA==", + "dev": true, + "dependencies": { + "esbuild": "^0.14.0" + }, + "bin": { + "tsm": "bin.js" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/tsutils": { "version": "3.21.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", @@ -24231,6 +24248,15 @@ "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", "dev": true }, + "tsm": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tsm/-/tsm-2.2.1.tgz", + "integrity": "sha512-qvJB0baPnxQJolZru11mRgGTdNlx17WqgJnle7eht3Vhb+VUR4/zFA5hFl6NqRe7m8BD9w/6yu0B2XciRrdoJA==", + "dev": true, + "requires": { + "esbuild": "^0.14.0" + } + }, "tsutils": { "version": "3.21.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", diff --git a/package.json b/package.json index 44a36237e..5303c32b3 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "prettier:check": "prettier --check .", "prettier:write": "prettier --write .", "typecheck": "tsc --noEmit", + "test:unit": "uvu -r tsm -r tsconfig-paths/register -i cypress", "cy:open": "cypress open", "checks": "npm run lint:styles && npm run lint:ts && npm run prettier:check && npm run typecheck" }, @@ -58,7 +59,9 @@ "stylelint-order": "^5.0.0", "ts-node": "^10.7.0", "tsconfig-paths": "^4.0.0", - "typescript": "^4.5.5" + "tsm": "^2.2.1", + "typescript": "^4.5.5", + "uvu": "^0.5.3" }, "engines": { "node": ">=14"