2

What I am trying to achieve is to get all entries from an array in a range of the last 30 days and push this into a new array which I can work with afterwards.

My array (this.trades) looks like this:

{
id: "95",
datum: "2020-03-11",
trade: "EUR/USD BUY",
aktion: "closed",
pips: "10"
},
{
id: "94",
datum: "2020-06-09",
trade: "GBP/USD BUY",
aktion: "TP Hit",
pips: "65"
},
{
id: "93",
datum: "2020-06-08",
trade: "NZD/USD SELL",
aktion: "SL Hit",
pips: "-57"
},

datum is the german word for date. the array is pretty long (filled with 95 entries over the past half year).

So my desired output would be:

  • to sort the Array by its date (this.trades.datum)
  • to extract all the entries within the last 30 days
  • and finally push this into a new array to work with (containing all the other keys)

I'm working in a vuejs project and have the opportunity to use computed properties for calculating, i'm also using momentjs library.

Here is my current function, where i convert datum into dateobjects: But i want to get only the entries from the last 30 days.

 chartDatumMonth() {
      let data = this.trades;
      data.forEach(d => {
        d.dateObj = moment(d.datum);
      });
      console.log(data);
      return data;
    },

console output:

(80) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, __ob__: Observer]
0:
aktion: (...)
dateObj: Moment
_d: Wed Aug 05 2020 00:00:00 GMT+0200 (Mitteleuropäische Sommerzeit) {}
_f: "YYYY-MM-DD"
_i: "2020-08-05"
_isAMomentObject: true
_isUTC: false
_isValid: true
_locale: Locale {_calendar: {…}, _longDateFormat: {…}, _invalidDate: "Invalid date", _dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/, ordinal: ƒ, …}
_pf: {empty: false, unusedTokens: Array(0), unusedInput: Array(0), overflow: -1, charsLeftOver: 0, …}
__proto__: Object
datum: "2020-08-05"
id: (...)
pips: (...)
trade: (...)
__ob__: Observer {value: {…}, dep: Dep, vmCount: 0}
get aktion: ƒ reactiveGetter()
set aktion: ƒ reactiveSetter(newVal)
get datum: ƒ reactiveGetter()
set datum: ƒ reactiveSetter(newVal)
get id: ƒ reactiveGetter()
set id: ƒ reactiveSetter(newVal)
get pips: ƒ reactiveGetter()
set pips: ƒ reactiveSetter(newVal)
get trade: ƒ reactiveGetter()
set trade: ƒ reactiveSetter(newVal)
__proto__: Object
1:
aktion: (...)
dateObj: Moment {_isAMomentObject: true, _i: "2020-08-04", _f: "YYYY-MM-DD", _isUTC: false, _pf: {…}, …}
datum: "2020-08-04"
Oliver Borner
  • 33
  • 1
  • 5
  • I tried this to convert the array into dateobjects: let data = this.trades; data.forEach(d => { d.dateObj = moment(d.datum); }); but then i have to reduce the array by its last 30 Days, that's where i stuck at the moment. Thank you! – Oliver Borner Aug 08 '20 at 10:19
  • [Edit] the question to give a [mre]. – jonrsharpe Aug 08 '20 at 10:19
  • You don't seem to have made any attempt to filter the list, maybe read https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter – jonrsharpe Aug 08 '20 at 10:40
  • Thank you, i will have a look into it. So you mean, i have to filter the list by date first. But how do i give it the range of 30 days? That's my question. – Oliver Borner Aug 08 '20 at 10:43
  • That's *not* currently what's asked in the question. Read the moment docs if you want to find out how to manipulate a date. – jonrsharpe Aug 08 '20 at 10:45
  • It is asked in the question, several times. – Oliver Borner Aug 08 '20 at 10:48
  • It's not clearly specified. I think what you're actually asking is e.g. https://stackoverflow.com/questions/8842732/how-to-get-30-days-prior-to-current-date. No [mre], no research shown; I'd recommend reading [ask]. – jonrsharpe Aug 08 '20 at 10:50

3 Answers3

5

In ECMAScript, dates in the format "YYYY-MM-DD" are parsed as UTC. When creating a date using new Date(), it is based on the local date and also has a component for the current time so when comparing values like "30 days ago" you must normalise everything to the same datum. In this case, UTC will be the simplest.

Otherwise, you'll get errors if the code is run near the start or end of the local day due to timezone offset differences where the UTC date is behind or ahead of the local date. The time component also should be set to zero.

The following creates a date for n days ago, then filters the dataset and sorts it. Since the supplied data is a few months old, I've made daysAgo a parameter that is passed to the function. Also, the sort uses localCompare as it's more efficient than creating and comparing Date objects, and works well with ISO 8601 formatted dates.

let data = [{
    id: "95",
    datum: "2020-03-11",
    trade: "EUR/USD BUY",
    aktion: "closed",
    pips: "10"
  },
  {
    id: "94",
    datum: "2020-06-09",
    trade: "GBP/USD BUY",
    aktion: "TP Hit",
    pips: "65"
  }, {
    id: "93",
    datum: "2020-06-08",
    trade: "NZD/USD SELL",
    aktion: "SL Hit",
    pips: "-57"
  }];
  
function getDaysAgoData(data, daysAgo) {
  // Get current date
  let t = new Date();
  // Create UTC date for daysAgo
  let d = new Date(Date.UTC(t.getFullYear(), t.getMonth(), t.getDate() - daysAgo));
  // Filter and sort data
  return data.filter(item => new Date(item.datum) >= d)
             .sort((a, b) => a.datum.localeCompare(b.datum));
}

console.log(getDaysAgoData(data, 90));
RobG
  • 142,382
  • 31
  • 172
  • 209
0

This should get you going

const list = [{
    id: "95",
    datum: "2020-03-11",
    trade: "EUR/USD BUY",
    aktion: "closed",
    pips: "10"
  },
  {
    id: "94",
    datum: "2020-06-09",
    trade: "GBP/USD BUY",
    aktion: "TP Hit",
    pips: "65"
  },
  {
    id: "93",
    datum: "2020-08-01",
    trade: "NZD/USD SELL",
    aktion: "SL Hit",
    pips: "-57"
  },
]


const currentDate = new Date();
const currentDateTime = currentDate.getTime();
const last30DaysDate = new Date(currentDate.setDate(currentDate.getDate() - 30));
const last30DaysDateTime = last30DaysDate.getTime();

const last30DaysList = list.filter(x => {
  const elementDateTime = new Date(x.datum).getTime();
  if (elementDateTime <= currentDateTime && elementDateTime > last30DaysDateTime) {
    return true;
  }
  return false
}).sort((a, b) => {
  return new Date(b.datum) - new Date(a.datum);
});

console.log(last30DaysList)
EugenSunic
  • 13,162
  • 13
  • 64
  • 86
  • 1
    Note that this uses the current local date and time whereas the timestamps will be parsed as UTC. It will differ from UTC dates for a period of at least the local timezone offset plus the local time at either end of the 30 day period. – RobG Aug 08 '20 at 21:25
  • 2
    Oh, also the sort should use `b.datum` and `a.datum`. :-) – RobG Aug 09 '20 at 01:40
  • @RobG tnx for pointing out the issues. +1 on your answer – EugenSunic Aug 09 '20 at 08:03
-1

Edit: Now the array is sorted (in first version I forgot this);

let arr = [{
id: "95",
datum: "2020-03-11",
trade: "EUR/USD BUY",
aktion: "closed",
pips: "10"
},
{
id: "94",
datum: "2020-07-20",
trade: "GBP/USD BUY",
aktion: "TP Hit",
pips: "65"
},
{
id: "93",
datum: "2020-06-18",
trade: "NZD/USD SELL",
aktion: "SL Hit",
pips: "-57"
},
{
id: "92",
datum: "2020-07-15",
trade: "GBP/USD BUY",
aktion: "TP Hit",
pips: "65"
},];

const today = new Date ();
result = arr.filter(obj => {
    const date = new Date(obj.datum);
    const diffTime = Math.abs(today - date);
    const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); 
    return (diffDays <=30);
});

result.sort((a,b) => {
    a = new Date(a.datum);
  b= new Date(b.datum);
  return (a<b) ? -1 : (a>b) ? 1 : 0; 
})
console.log(result);
Sascha
  • 4,576
  • 3
  • 13
  • 34