Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

[PLAY-986] dateTime Rounding Bug #2728

Merged
merged 6 commits into from
Sep 12, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 54 additions & 23 deletions playbook/app/pb_kits/playbook/pb_kit/dateTime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,30 +121,61 @@ export const toIso = (newDate: Date | string): string => {
}

export const fromNow = (newDate: Date | string): string => {
const startDate = formatDate(newDate).getTime()
const endDate = new Date().getTime()
const today = new Date()
const formattedDate = formatDate(newDate)

const startDate = formattedDate.getTime()
const endDate = today.getTime()
const elapsedTime = endDate - startDate
let elapsedTimeString = `${Math.round(elapsedTime / (365.25 * 24 * 60 * 60 * 1000))} years ago`; // 730+ days

const MILLISECONDS_IN_A_MONTH = 30.44 * 24 * 60 * 60 * 1000

const elapsedTimeData = [
{ min: 0, max: 44999, value: "a few seconds ago" }, // 0-44 seconds
{ min: 45000, max: 89999, value: "a minute ago" }, // 45-89 seconds
{ min: 90000, max: 2649999, value: `${Math.round(elapsedTime / 60000)} minutes ago`}, // 90s-44 minutes
{ min: 2650000, max: 7299999, value: "an hour ago" }, // 45-120 minutes
{ min: 7300000, max: 75699999, value: `${Math.round(elapsedTime / 3600000)} hours ago`}, // 2-21 hours
{ min: 75700000, max: 172899999, value: "a day ago" }, // 22-48 hours
{ min: 172900000, max: 2169999999, value: `${Math.round(elapsedTime / 86400000)} days ago`}, // 2-25 days
{ min: 2170000000, max: 5184999999, value: "a month ago"}, // 26-60 days
{ min: 5185000000, max: 27561699999, value: `${Math.round(elapsedTime / MILLISECONDS_IN_A_MONTH)} months ago`}, // 60-319 days
{ min: 27561700000, max: 63072999999, value: "a year ago"}, // 320-730 days
];

for (const timeDate of elapsedTimeData) {
if (elapsedTime >= timeDate.min && elapsedTime <= timeDate.max) {
elapsedTimeString = timeDate.value;
break;

// For years/months, don't use elapsedTime due to rounding
const differenceInYears = today.getFullYear() - formattedDate.getFullYear()
const differenceInMonths = () => {
let months = differenceInYears * 12
months -= formattedDate.getMonth()
months += today.getMonth()
return months
}

const FORTY_FIVE_SECONDS = 45000
const NINETY_SECONDS = 90000

const FORTY_FIVE_MINUTES = 2670000
const NINETY_MINUTES = 5400000

const TWENTY_TWO_HOURS = 77400000
const THIRTY_SIX_HOURS = 129600000

const TWENTY_SIX_DAYS = 2203200000
const FORTY_FIVE_DAYS = 3888000000

const TEN_AND_A_HALF_MONTHS = 27560000000

const MILLISECONDS_IN_A_MINUTE = 60000
const MILLISECONDS_IN_A_HOUR = 3600000
const MILLISECONDS_IN_A_DAY = 86400000

let elapsedTimeString = differenceInYears === 1 ? `${differenceInYears} year ago` : `${differenceInYears} years ago` // 320 days to 1+ year: "x year(s) ago"

// Inspiration: https://momentjs.com/docs/#/displaying/fromnow/
const intervals = [
{ min: 0, max: FORTY_FIVE_SECONDS, value: "a few seconds ago" }, // 0-44.99 seconds
{ min: FORTY_FIVE_SECONDS, max: NINETY_SECONDS, value: "a minute ago" }, // 45-89.99 seconds
{ min: NINETY_SECONDS, max: FORTY_FIVE_MINUTES, value: `${Math.round(elapsedTime / MILLISECONDS_IN_A_MINUTE)} minutes ago` }, // 90s-44.49 minutes: "2 minutes ago ... 44 minutes ago"
{ min: FORTY_FIVE_MINUTES, max: NINETY_MINUTES, value: "an hour ago" }, // 44.5-89.99 minutes
{ min: NINETY_MINUTES, max: TWENTY_TWO_HOURS, value: `${Math.round(elapsedTime / MILLISECONDS_IN_A_HOUR)} hours ago` }, // 90m-21.49 hours: "2 hours ago ... 21 hours ago"
{ min: TWENTY_TWO_HOURS, max: THIRTY_SIX_HOURS, value: "a day ago" }, // 21.5-35.99 hours
{ min: THIRTY_SIX_HOURS, max: TWENTY_SIX_DAYS, value: `${Math.round(elapsedTime / MILLISECONDS_IN_A_DAY)} days ago` }, // 36h-25.49 days: "2 days ago ... 25 days ago"
{ min: TWENTY_SIX_DAYS, max: FORTY_FIVE_DAYS, value: "a month ago" }, // 25.5-44.99 days
{ min: FORTY_FIVE_DAYS, max: TEN_AND_A_HALF_MONTHS, value: `${differenceInMonths()} months ago` }, // 45 days to 319 days: "2 months ago ... 10 months ago"
]

for (const interval of intervals) {
const { min, max, value } = interval

if (elapsedTime >= min && elapsedTime < max) {
elapsedTimeString = value
break
}
}

Expand Down