learnbydoing
learnbydoing

Reputation: 499

JavaScript filter data by week day and timestamps

In my personal project, users can define times when they want not to be disturbed. These times include the days of the week you selected, as well as the start and end timestamps of the interval.

Basically, on those days of the week and during these intervals stipulated by users, I cannot create tasks. That is, the "final" array should only contain the users that are readable for creating the tasks.

My current code is as follows:

const data = [
    {
        firstName: 'John',
        lastName: 'Doe',
        schedules: [
            {
                days: ['Tue', 'Wed', 'Fri'],
                start: '2022-01-07T10:50:00.859Z',
                end: '2022-01-07T11:30:00.859Z',
            },
            {
                days: ['Mon'],
                start: '2022-01-07T13:30:00.859Z',
                end: '2022-01-07T14:30:00.859Z',
            },
        ],
    },
    {
        firstName: 'Aaron',
        lastName: 'Park',
        schedules: [
            {
                days: ['Wed', 'Fri'],
                start: '2022-01-07T13:30:00.859Z',
                end: '2022-01-07T14:30:00.859Z',
            },
            {
                days: ['Mon'],
                start: '2022-01-07T13:30:00.859Z',
                end: '2022-01-07T14:30:00.859Z',
            },
        ],
    },
];

const todayWeekDay = new Date().toLocaleString('en-us', { weekday: 'short' });
const currentTime = new Date();

const filteredData = data.filter((user) => {
    const filteredSchedules = user.schedules.filter((schedule) => {
        const days = schedule.days;
        if (days.includes(todayWeekDay)) {
            const startTime = new Date(schedule.start);
            const endTime = new Date(schedule.end);
            if (currentTime >= startTime && currentTime <= endTime) {
                return false;
            }
            return true;
        }
        return false;
    });
    if (filteredSchedules.length) {
        return true;
    }
    return false;
});

console.log(filteredData)

I haven't tested many edge cases yet, but I've noticed that sometimes when I "play" with the days of the week, sometimes the user should appear in the "final" array, but it doesn't.

In the final result, the user must be returned under the following circumstances:

The output I expect may change depending on the current day of the week and the hours.But for example, if today were the 21st of January 2022, which corresponds to a Friday. Between 10:50 am and 11:30 am, the result should be as follows:

[{
  "firstName": "Aaron",
  "lastName": "Park",
  "schedules": [
    {
      "days": [
        "Wed",
        "Fri"
      ],
      "start": "2022-01-07T13:30:00.859Z",
      "end": "2022-01-07T14:30:00.859Z"
    },
    {
      "days": [
        "Mon"
      ],
      "start": "2022-01-10T13:30:00.859Z",
      "end": "2022-01-12T14:30:00.859Z"
    }
  ]
}] 

While outside those hours the result should be this:

[{
  "firstName": "John",
  "lastName": "Doe",
  "schedules": [
    {
      "days": [
        "Tue",
        "Wed",
        "Fri"
      ],
      "start": "2022-01-07T10:50:00.859Z",
      "end": "2022-01-07T11:30:00.859Z"
    },
    {
      "days": [
        "Mon"
      ],
      "start": "2022-01-10T13:30:00.859Z",
      "end": "2022-01-12T14:30:00.859Z"
    }
  ]
}, {
  "firstName": "Aaron",
  "lastName": "Park",
  "schedules": [
    {
      "days": [
        "Wed",
        "Fri"
      ],
      "start": "2022-01-07T13:30:00.859Z",
      "end": "2022-01-07T14:30:00.859Z"
    },
    {
      "days": [
        "Mon"
      ],
      "start": "2022-01-10T13:30:00.859Z",
      "end": "2022-01-12T14:30:00.859Z"
    }
  ]
}] 

Upvotes: 0

Views: 765

Answers (1)

cyberpirate92
cyberpirate92

Reputation: 3166

You can use a method like this to ignore the date and just compare the times.

function fallsInInterval(start, end, date) {
    const now = new Date();
    const s = new Date(now.getFullYear(), now.getMonth(), now.getDate(), start.getHours(), start.getMinutes(), start.getSeconds());
    const e = new Date(now.getFullYear(), now.getMonth(), now.getDate(), end.getHours(), end.getMinutes(), end.getSeconds());
    const d = new Date(now.getFullYear(), now.getMonth(), now.getDate(), date.getHours(), date.getMinutes(), date.getSeconds());
    return d >= s && d <= e;
}

All the above method does is to create new date objects where the date component is the same for all but the original time is preserved, which makes the comparison easier.

So, instead of

if (currentTime >= startTime && currentTime <= endTime) {
    return false;
}

you will use

if (fallsInInterval(startTime, endTime, currentTime)) {
    return false;
}

Upvotes: 1

Related Questions