-2

I am making a site that gets data from a speedrun.com API and puts the newest runs on the site in order of time. I recently added a feature where runs from the same day that the site is viewed will have a special icon showing that they are "NEW". This is my current solution (Javascript):

runs[i].date = "2021-12-12"; // The API does not return hours
if (new Date(new Date().getTime() - new Date().getTimezoneOffset() * 60000).toJSON().slice(0, 10) === runs[i].date) {
  alert("Today");
}

If the date was December 12th, 2021, this would alert Today.

This solution accounts for timezone differences and works well. However, I would like this to be possible for runs that happened in the last 3 days, so even if runs[i].date = "2021-12-11" (December 10th) or runs[i].date = "2021-12-11" (December 11th), it would still alert Today.

How would this be done?

derder56
  • 111
  • 1
  • 8
  • Please clarify whether you actually mean runs that happened "in the last three days" in the colloquial sense, or runs that happened within the last 3 * 24 hours. – CBroe Dec 16 '21 at 14:50
  • 3 * 24 hours is what I meant. – derder56 Dec 16 '21 at 14:57
  • So `2021-12-12` is supposed to mean that all runs happen at exactly `00:00:00`? Otherwise, what you are asking for doesn't make much sense to begin with. If your input data does not contain any time component, then how would you want to determine if it was _exactly_ 3 * 24 hours from now ...? – CBroe Dec 16 '21 at 15:03
  • `2021-12-12` is all that is given. Actually, it doesn't have to be 72 hours, just the last 3 days. I don't even care if it's 4 days at this point. – derder56 Dec 16 '21 at 15:07
  • You could create a Date instance for three days ago, and then compare them directly. https://stackoverflow.com/questions/1296358/how-to-subtract-days-from-a-plain-date (Careful with the _time_ portion of the date you are creating though.) – CBroe Dec 16 '21 at 15:14
  • Yes but I also want it to include 1/2 days ago. – derder56 Dec 16 '21 at 16:24

1 Answers1

0

Split it up into functions and compose them:

const DAY = 1000 * 60 * 60 * 24;

function datesAreInRange (date1, date2, days) {
  const ms = days * DAY;
  const diff = Math.abs(date2.getTime() - date1.getTime());
  return diff <= ms;
}

function getDateFromString (ymd) {
  const [y, m, d] = ymd.split('-').map(str => parseInt(str, 10));
  return new Date(y, m - 1, d);
}

const today = '2021-12-16';

const otherDates = [
  '2021-12-20',
  '2021-12-19',
  '2021-12-18',
  '2021-12-17',
  '2021-12-16',
  '2021-12-15',
  '2021-12-14',
  '2021-12-13',
  '2021-12-12',
];

for (const other of otherDates) {
  const inRange = datesAreInRange(...[today, other].map(getDateFromString), 3);
  console.log(`${other} is ${inRange ? '' : 'not '}in range.`)
}
jsejcksn
  • 27,667
  • 4
  • 38
  • 62
  • Not all days are 8.64e7 ms long where daylight saving is observed, see [*How to calculate number of days between two dates?*](https://stackoverflow.com/questions/542938/how-to-calculate-number-of-days-between-two-dates) Also, `.map(str => parseInt(str, 10))` is unnecessary. – RobG Dec 16 '21 at 20:47
  • @RobG True, I could have used `Date.UTC` to fix that. I have a feeling that the OP won’t mind, based on the loose criteria. – jsejcksn Dec 16 '21 at 21:12
  • @RobG Regarding parsing: yes, I could have relied on implicit type coercion, but I prefer the type correctness, and TypeScript enforces it (which is how I originally wrote this before posting). – jsejcksn Dec 16 '21 at 21:22
  • Where [2 or more arguments are passed to the constructor](https://262.ecma-international.org/#sec-date), the Type of the values is irrelevant and has no effect on processing, so unnecessary and inefficient to coerce them to any particular Type beforehand. – RobG Dec 16 '21 at 22:53