0

I have two JavaScript objects in Angularjs. Both of them having the same keys but different values. Which looks like this:

$scope.object1 = {
    name: 'Arpit',
    roll_no: 999, // Number
    creation_date: '2017-04-10T04:44:21.923Z', // date value but string
    joining_date: '2017-03-30T18:30:00.000Z' // date value but string
}

and the second object is:

$scope.object2 = {
    name: 'Arpit1',
    roll_no: '999', // Number but string
    creation_date: 2017-04-10T04:44:21.923Z, // date value not string
    joining_date: 2017-03-30T18:30:00.000Z // date value not string
}

Now I want to compare both this object and want to detect the different value. In comparison 999 should be equal to '999' and '2017-03-30T18:30:00.000Z' should be equal to 2017-03-30T18:30:00.000Z and so on.

Challenge

The value of date and number may be in string format so first I need to detect whether the given string is a date or number and then comparison need to be done.

My code

var data = {
     options:{
        data: $scope.object1
     },
     newData: $scope.object2
}

angular.forEach(data.options.data, function (value, key) {

    //compare fields
    if (data.newData[key] != data.options.data[key]) {

        if (filedsToSkip.indexOf(key) == -1) {

            if ((angular.isDate(data.newData[key]) || angular.isDate(data.options.data[key])) && new Date(data.newData[key]) != new Date(data.options.data[key])) {
                $ctrl.updatedFields.push({
                    field: key,
                    newValue: data.newData[key],
                    oldValue: data.options.data[key]
                });
            } 
        } else {
            console.log("Field skipped");
        }


    }
});

But this code is not working properly. Please give some suggestion.

Thanks.

EDIT

Right now when I am running this code it is showing that all the fields are different, but I want it to show only name is different.

Arpit Kumar
  • 2,179
  • 5
  • 28
  • 53
  • I am not sure if this contributes to the problem or not. In line 15 (the large if condition) , what happens when `isDate` is false for one of the values and true for the other one? It seems in this case, the first part of the condition becomes true, and the second part might also become true, because `Date` can return a valid result for a number too (e.g. `new Date("2017")`) – jrook Apr 10 '17 at 05:36
  • It would help if you specified what is not working properly, i.e. what is the expected output and how your code's output is different than that. – jrook Apr 10 '17 at 05:44
  • Also, the block you are executing for `if` and `else if` is exactly the same. – jrook Apr 10 '17 at 05:50
  • The same problem, I am facing. It is saying `2017-03-30T18:30:00.000Z` is not equal to `"2017-03-30T18:30:00.000Z"`. – Arpit Kumar Apr 10 '17 at 06:17
  • One more thing you can try is to use a regex for validating dates (specially if they are in Unix format) and move forward with the rest of your code. See [here](http://stackoverflow.com/questions/22135276/date-regular-expression-in-unix) for example. – jrook Apr 10 '17 at 06:39

3 Answers3

0

You can use !isNaN(Date.parse(v)) to evaluate whether or not the value is a date:

let possible = [999, '999', '2017-03-30T18:30:00.000Z']

possible.forEach((v) => {
  console.log("is date : ", !isNaN(Date.parse(v)));
});

If true then you can do your comparison.

Zze
  • 18,229
  • 13
  • 85
  • 118
  • @Zze_, But it will conflict in case of number comparison. It is saying `true` for number also. – Arpit Kumar Apr 10 '17 at 05:29
  • woahhhhhhhhh - so I just tested this in Chrome and indeed true for all. FF and edge is as intended. – Zze Apr 10 '17 at 05:31
0

After getting some suggestions, I modified the code:

angular.forEach(data.options.data, function (value, key) {

    //compare
    if (data.newData[key] != data.options.data[key]) {

        if (filedsToSkip.indexOf(key) == -1) {

            if ((angular.isDate(data.newData[key]) || angular.isDate(data.options.data[key])) && new Date(String(data.newData[key])) !== new Date(String(data.options.data[key]))) {
                $ctrl.updatedFields.push({
                    field: key,
                    newValue: data.newData[key],
                    oldValue: data.options.data[key]
                });
            } else if (data.newData[key] !== "" && data.options.data[key] !== "") {
                $ctrl.updatedFields.push({
                    field: key,
                    newValue: data.newData[key],
                    oldValue: data.options.data[key]
                });
            }

        } else {
            console.log("Field skipped");
        }
    }
});

And It's working fine. I am not sure it is a 100% perfect solution or not but I am fine with it. Thanks.

Arpit Kumar
  • 2,179
  • 5
  • 28
  • 53
0

As this comment demonstrates, comparison between two date objects can be tricky:

var d1 = new Date();
var d2 = new Date(d1);
d1!==d2;  //true

I do not think the OP's answer gets quite there though. Consider this example:

var x  = '2017-04-10T04:44:21.923Z';
var d1  = new Date(String(x));
var d2 = new Date(String(x));
d1!==d2; //true

I suggest using one of the solutions in this answer. Maybe use getTime() to compare the dates. In the above example:

d1.getTime()!==d2.getTime(); //false
Community
  • 1
  • 1
jrook
  • 3,459
  • 1
  • 16
  • 33