2

Currently trying to filter my data array by week, I have been able to filter by day quite easily however am struggling with dates between x and y (eg by week).

I have tried setting a start date and end date (today) and then trying to return the dates less than or equal to the start and end dates but am failing.

Data array date format: dd/mm/yyyy (01/01/2000)

The user will select which filter to use (hence switch() ) case 7 being filter by 7 days.

computed: {
    appointments: function () {

      var today = new Date();
      var dd = String(today.getDate()).padStart(2, '0');
      var mm = String(today.getMonth() + 1).padStart(2, '0'); //January is 0!
      var yyyy = today.getFullYear();


      var data = this.$store.state.appointments;

      this.filter1_color = "grey";
      this.filter2_color = "grey";

      switch (this.dateFilter) {
        case 0:
        break;

        case 1:
        console.log("case1: " + today)
        return data.filter(word => word.date == today);

        case 7:

        /// WORKING /// (ex. edit)
        var week = [];

        var today = moment();
        var sevenDaysBefore = today.subtract(7, 'days');

        for (var i = 0; i < data.length; i++) {
          let momentDate = moment(data[i].date, 'DD/MM/YYYY')
          let newDate = momentDate.format("DD/MM/YYYY")
          if (momentDate.isBetween(sevenDaysBefore, moment(), null, '[]')) week.push(data[i]);
        }


        return week
        ///

      }


      return data;
    },

I need to filter the data to only show items in the array with dates equal to the dates in the last 7 days.

4
  • Can you use a library like moment js? Commented Apr 14, 2019 at 10:26
  • @f-CJ I can, I just installed it and it looks handy dandy - still need to find a solution though. Commented Apr 14, 2019 at 10:38
  • Yes it is. You need to get as result all the appointments that are in this week or just in the last 7 days? Commented Apr 14, 2019 at 10:53
  • @f-CJ Just last 7 days is what I am trying to do. Commented Apr 14, 2019 at 10:55

2 Answers 2

6

You can use method isBetween of moment js library with current date. You can subtract 7 days to current date with subtract(7, 'days').

You can check more about isBetween method in moment js library documentation. The third parameter of the method is the granularity, and it seems that in your case it should 'days'

const today = moment();
const sevenDaysBefore = moment().subtract(7, 'days');

console.log('Today is ' + today.format('MMM Do YYYY'));
console.log('Is ' + today.format('MMM Do YYYY') + ' included in the last seven days?');
console.log(today.isBetween(sevenDaysBefore, today, 'day', '[]'));

console.log('Is ' + sevenDaysBefore.format('MMM Do YYYY') + ' included in the last seven days?');
console.log(sevenDaysBefore.isBetween(sevenDaysBefore, today, 'day', '[]'));

const eightDaysBefore = moment().subtract(8, 'days');
console.log('Is ' + eightDaysBefore.format('MMM Do YYYY') + ' included in the last seven days?');
console.log(eightDaysBefore.isBetween(sevenDaysBefore, today, 'day', '[]'));

const oneDayAfter = moment().add(1, 'days');
console.log('Is ' + oneDayAfter.format('MMM Do YYYY') + ' included in the last seven days?');
console.log(oneDayAfter.isBetween(sevenDaysBefore, today, 'day', '[]'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.js"></script>

Sign up to request clarification or add additional context in comments.

6 Comments

Added another answer in case the OP cannot use moment.js. However, upvoted and recommended your answer.
@f-CJ Thanks for that. It gets essentially what I need but I am having trouble implementing it. I have set a for loop to filter them out (see my updated code between /// EDIT /// - but get TypeError: e[i].date.isBetween is not a function which is confusing as it works when putting it in its own if statement. Am I trying to do it the hard way?
@TimRowley You have to parse date to convert it to moment. isBetween is a moment method. Probably just with moment(data.date[i], 'DD/MM/YYYY') you are fine but check documentation momentjs.com/docs/#/parsing
I meant moment(data[i].date, 'DD/MM/YYYY')
@f-CJ Wonderful - thanks for that, it makes so much more sense now. I have got it to a working state now which is fantastic, sure will make life easier with Moment JS. (Added working code to OP)
|
1

If you don't want to or cannot use a library like moment.js, and also don't mind an ad-hoc implementation with certain restrictions:

Note

I recommend to use a library for working with Date objects, especially when it comes to parsing a string to a date. Too many things can go wrong when doing it by hand. If possible, use the answer of @f-CJ

These parts allow you to create a Date object from a string. However, the resulting Date is always converted to local time and the string needs to have a certain formatting (the one you showed in your question). If you need support for UTC, this won't work. Also, it cannot be used to parse a date string with ISO formatting.

const OFFSET_TO_UTC = new Date().getTimezoneOffset();

function parseDateString (dateString, sep) {
  var parts = dateString.split(sep);
  return parts.map(n => Number(n));
}

function localizeDate (pattern, parts) {
  return pattern.reduce((acc, pat, i) => {
    switch (pat) {
      case 'd':
        return Object.assign(acc, { day: parts[i] });
      case 'm':
        return Object.assign(acc, { month: parts[i] });
      case 'y':
        return Object.assign(acc, { year: parts[i] });
      default:
        return acc;
    }
  }, {});
}

function toDate (localized) {
  return new Date(
    localized.year,
    localized.month - 1,
    localized.day,
    0, 0 - OFFSET_TO_UTC, 0);
}

function parseDate (pattern, sep, dateString) {
  return toDate(localizeDate(pattern, parseDateString(dateString, sep)));
}


// try it:

const dStringUS = '04/04/2019'; // mm/dd/yyyy
const dStringDE = '04.04.2019'; // dd/mm/yyyy

const dateUS = parseDate(['m', 'd', 'y'], '/', dStringUS);
const dateDE = parseDate(['d', 'm', 'y'], '.', dStringDE);

console.log(dateUS);
console.log(dateDE);

Based on it, you can write yourself a generic filtering function:

const OFFSET_TO_UTC = new Date().getTimezoneOffset();

function parseDateString (dateString, sep) {
  var parts = dateString.split(sep);
  return parts.map(n => Number(n));
}

function localizeDate (pattern, parts) {
  return pattern.reduce((acc, pat, i) => {
    switch (pat) {
      case 'd':
        return Object.assign(acc, { day: parts[i] });
      case 'm':
        return Object.assign(acc, { month: parts[i] });
      case 'y':
        return Object.assign(acc, { year: parts[i] });
      default:
        return acc;
    }
  }, {});
}

function toDate (localized) {
  return new Date(
    localized.year,
    localized.month - 1,
    localized.day,
    0, 0 - OFFSET_TO_UTC, 0);
}

function parseDate (pattern, sep, dateString) {
  return toDate(localizeDate(pattern, parseDateString(dateString, sep)));
}



const data = [{
  value: 0,
  date: '04/05/2019'
}, {
  value: 1,
  date: '04/07/2019'
}, {
  value: 2,
  date: '03/07/2019'
}];

function filterByDatePattern (pattern, sep) {
  return function (date, list) {
    return list.filter(item => {
      var itemDate = parseDate(pattern, sep, item.date);
      return itemDate >= date;
    });
  }
}

const onlyUSUntil = filterByDatePattern(['m', 'd', 'y'], '/');
console.log(onlyUSUntil(new Date(2019, 3, 1), data));

1 Comment

Thanks David, certainly looks a lot harder to implement. Appreciate it :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.