Select to view content in your preferred language

AGOL Arcade Question Date Difference

4757
19
Jump to solution
02-12-2021 09:19 AM
LukeAllen2
Occasional Contributor

Hi all,

I'm sort of new to coding in general, but I have started trying to use some arcade expressions in my web maps, currently I have a web map which has a date painted field for hydrants and with the arcade expression below I am using the current date and this field to provide a count of the years and days since a hydrant was last painted.

However, I was QC'ing the data and noticed that for hydrants painted after 2020, it is going to be a day short as 2020 was a leap year - if the web map persists beyond 2024, it will then start being 2 days short.

With my limited knowledge I believe that I need to use some type of when or if statement to be able to use 366 rather than 365 (in var d calculation) i'm just now sure how I would go about doing it - would anybody be able to provide some pointers? 

Many thanks!

var timeNow = Now();
var survey = $feature["DATE_PAINTED"];

var years = DateDiff(timeNow, survey, 'Years');
// 2.1116274159012844

var y = Floor(years, 0);
var d = (years - y) * 365;

if (IsEmpty($feature.DATE_PAINTED)){
return "-"
} else if (y >= 2) {
return "Last Painted: " + Round(y, 0) + " years and " + round(d , 0) + " days ago."
} else if (y == 1) {
return "Last Painted: " + Round(y, 0) + " year and " + round(d , 0) + " days ago."
} else if (y == 0) {
return "Last Painted: " + round(d , 0) + " days ago."
}

0 Kudos
19 Replies
LukeAllen2
Occasional Contributor

Hi Xander, if you check your PM i sent you a public web map with a snippet of the data im using that replicates the issue

0 Kudos
XanderBakker
Esri Esteemed Contributor

Hi @LukeAllen2 ,

My bad. Apparently, there is a line missing in the function. Can you try this?

function daysThisYear() {
    // https://stackoverflow.com/questions/16353211/check-if-year-is-leap-year-in-javascript
    var y = Year(Now());
    
    // check leap year
    if (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0)) {
        return 366;
    } else {
        return 365;
    }
}

var timeNow = Now();
var survey =  $feature["DATE_PAINT"];
// var survey = Date(2015, 1, 1);
var years = DateDiff(timeNow, survey, 'Years');
var y = Floor(years, 0);
var d = Round((years - y) * daysThisYear(), 0);

if (IsEmpty($feature["DATE_PAINT"])){
    return "-";
} else if (y >= 2) {
    return "Last Painted: " + y + " years and " + Floor(d , 0) + " days ago.";
} else if (y == 1) {
    return "Last Painted: 1 year and " + Floor(d , 0) + " days ago.";
} else if (y == 0 && d >= 2) {
    return "Last Painted: " + Floor(d , 0) + " days ago.";
} else if (y == 0 && d >= 1) {
    return "Last Painted: " + Floor(d , 0) + " day ago.";
} else if (y == 0 && d < 1) {
    return "Last Painted: today.";
}

 

LukeAllen2
Occasional Contributor

Xander, that worked!  Thanks again your patience and help!

0 Kudos
XanderBakker
Esri Esteemed Contributor

You're welcome @LukeAllen2 . Sorry for the error in the function. It is a bit weird that it was a valid expression in the expression builder. (I also worked with the error in Pro, when it shouldn't have worked...)

0 Kudos
LukeAllen2
Occasional Contributor

Xander, no apology necessary - thank you for your time and help -- yeah that was what threw me for a loop too

0 Kudos
XanderBakker
Esri Esteemed Contributor

Hi @LukeAllen2 ,

To reply to the private message you send, have a look at the code snippet below that will take into account the leap year in a more logical way.

 

// multiple years and days when there is a leapyear
var date1 = Date(2016, 1, 1); // February 1st 2016
var date2 = Date(2020, 2, 1); // March, 1st 2020

// calculate the years as usual
var years = Floor(DateDiff(date2, date1, 'years'));

// create a new date by adding the years to the start date
var date1a = DateAdd(date1, years, 'years');

// calculate the number of days between those date (will account for leap years)
var days = DateDiff(date2, date1a, 'days');

return years + " years and " + days + " days";

 

And to put this logic in your example, it will look like this:

var timeNow = Now();
var survey =  $feature["DATE_PAINT"];
var y = Floor(DateDiff(timeNow, survey, 'Years'));
var date1a = DateAdd(survey, y, 'years');
var d = DateDiff(timeNow, date1a, 'days');

if (IsEmpty($feature["DATE_PAINT"])){
    return "-";
} else if (y >= 2) {
    return "Last Painted: " + y + " years and " + Floor(d , 0) + " days ago.";
} else if (y == 1) {
    return "Last Painted: 1 year and " + Floor(d , 0) + " days ago.";
} else if (y == 0 && d >= 2) {
    return "Last Painted: " + Floor(d , 0) + " days ago.";
} else if (y == 0 && d >= 1) {
    return "Last Painted: " + Floor(d , 0) + " day ago.";
} else if (y == 0 && d < 1) {
    return "Last Painted: today.";
}

 

0 Kudos
DavidPike
MVP Frequent Contributor

This is the concept I initially posted, @LukeAllen2  did it not work out?

XanderBakker
Esri Esteemed Contributor

Hi @DavidPike , sorry about that, you are absolutely right. I will mark it as a solution since it is the way to go.

LukeAllen2
Occasional Contributor

Hi David, yes this worked, sorry i went down a wormhole with some other issue that Xander was helping me work through and forgot to give credits - thank you 🙂

0 Kudos
AbiDhakal
Occasional Contributor III

@XanderBakker @LukeAllen2

- I have this expression that calculates years and populates a field called 'Age'. It gets this information to calculate years from a field called EstbYear (as you can see in the expression below) that I populate with the year it was established. However, it puts the years in the 'Age' field only after the layer is checked and unchecked in the web map. With this happening, another field  calculation that relies on 'Age' is not getting calculated unless I go back in and put the age manually first, before I put in the other variables for the calculation to happen

This is the calculation I used which is working just fine:

var currentTime = Year(Now());
var survey = $feature["EstbYear"];

// Calculate age in years
var age = 0;
if (!IsEmpty(survey)) {
age = currentTime - survey;
}

return age;

Is there something I am missing. Do I have to tell somewhere that the next calculation needs to double check the 'Age' field so it can calculate the next field. Do I need to put something in the arcade rule in ArcGIS Pro for the calculation to recognize 'Age' field to so it can see the 'Age' field value to do the next calculation?

Thank you for your help,
Abi

0 Kudos