MRI80
MRI80

Reputation: 35

Dates in array lose formatting after 1st iteration of looping over the array

I'm pulling CSV data from a URL. I've parsed this into a variable called 'data'. It looks like this:

[
[ID, Sometext (dd-MM-YYYY), Othertext (dd-MM-YYYY), Whatevertext (dd-MM-YYYY)],
[1, yes, no, no],
[2, yes, yes, no],  
[3, no, yes, no],
etc...
]

If a certain text is present in the 1st array (the csv headers), it should be assigned another text. The dates aren't ordered chronologically, but they should be.

I've made a loop to go over the headers, extracted the date, changed it to Date type, and replaced the text as required. Put both values into an array and used a sort function to order the arrays by date.

[
[Thu Aug 27 00:00:00 GMT+02:00 2020, Text1], [Fri Aug 28 09:00:00 GMT+02:00 2020, Text2], [Sat Aug 29 09:00:00 GMT+02:00 2020, Text3]
etc.
]

Next I am looping over the following rows, if a value equals yes, I'm adding the new header value to an array for that ID. At the end of the iteration, I want to convert back the Date types to dd-MM-YYYY format.

In the first iteration, this works fine. But in the 2nd iteration, it gives an error since the dates are not Date types anymore.

Now I know this is pretty ugly with multiple nested loops, but for as far as I can tell, the changing of the values in data[0] is done before the next set of loops starts. And the new values are present in the 1st iteration but not in the 2nd. I don't understand why?

var response = UrlFetchApp.fetch(url);

var data = Utilities.parseCsv(response, ";")

for (var i = 7; i < data[0].length; i++) {
  
    var type;
    
if (/text1/.test(data[0][i]) === true) {
        type = "Text 1";
    } else if 
      (/text2/.test(data[0][i]) === true) { 
      type = "Text 2";
      } else if 
        (/text3/.test(data[0][i]) === true) {
      type = "Text 3";
        } else if 
          (/text4/.test(data[0][i]) === true) {
      type = "Text 4";
          } else if 
      (/text5/.test(data[0][i]) === true) { 
      type = "Text5";
      };
                
    data[0][i] = data[0][i].match(/\(([^)]+)\)/)[1]
    
    var dateParts = data[0][i].split("-");
data[0][i] = [new Date(+ dateParts[2], dateParts[1] - 1, + dateParts[0], 9, 0 ,0)];

    data[0][i].push(type)
    }; 
  
   
  var idsArray = [];
  
  for (var j = 1; j < data.length; j++) {

   var id = [];

    for (var k = 7; k < data[j].length; k++) {
      if (data[j][k] === "yes") {
        id.push(data[0][k])
      };
           
      };
        

    id.sort(sortFunction);   
  
  
    
for (var m = 0; m < id.length; m++) {
 id[m][0] = Utilities.formatDate(id[m][0], "Europe/Amsterdam", "dd-MM-yyyy");
  }

     id.unshift(data[j][3]);
      idsArray.push(id);
   
    }

Upvotes: 0

Views: 41

Answers (1)

dwmorrin
dwmorrin

Reputation: 2734

When you use Utilities.formatDate() in the statement

id[m][0] = Utilities.formatDate(id[m][0], "Europe/Amsterdam", "dd-MM-yyyy");

you are changing the data type of the data stored in id[m][0] from Date to string.

What is the data stored in id[m][0]? You put data[0][k] in there:

id.push(data[0][k])

Now the question is, did it copy the Date from data and give you a new Date for the id array? No, JavaScript doesn't copy objects; you just have a reference to the original Date object, stored in the data array.

So you have indirectly mutated the values in data by updating some other array (id) that you thought was independent.

Update your mutating statement so you don't overwrite the existing object.

var dateString = Utilities.formatDate(id[m][0], "Europe/Amsterdam", "dd-MM-yyyy");

Upvotes: 2

Related Questions