Greetings, all!
I am configuring the My Trash Services solution deployed from the ArcGIS Solutions App, and specifically configuring the Next Pickup Arcade expression for the Pickup [polygon] layers. The expression includes a variable for nextPickupHoliday where I can configure "Next Weekday", "Next Day", or "Next Scheduled Pickup", and the returned value will be the next weekday, next day, or next scheduled pickup day, respectively.
I am seeking help to update the expression to accommodate the following scenario:
- If the pickup day is Memorial Day, then the next pickup day will be the following Thursday.
- If the pickup day is Independence Day, then the next pickup day will be the following Thursday.
- If the pickup day is Labor Day, then the next pickup day will be the following Thursday.
- If the pickup day is Thanksgiving, then there will be no pickup day that week.
- If the pickup day is Christmas, then there will be no pickup day that week.
- If thee pickup day is New Years Day, then there will be no pickup that week.
So, two scenarios to this special case: (1) if the pickup day is on a specific holiday, then the next pickup day will be on a specific day of the week during that week, and (2) if the pickup day is on a specific holiday, then there will be no pickup day during that week.
Since the Solutions experience updates and can change, I have included the Arcade expression below that I am using.
/*If pickup occurs weekly, specify 1.
If every other week specify 2, etc.*/
var pickupWeekInterval = 1;
/*Specify a date in the past in which pickup occurred.
This is used in the case where pickup doesn't occur every week
to determine the weeks where pickup is occurring.*/
var firstPickupWeek = Date('2017-01-01');
/*If the pickup service isn't available year-round
specify the first and last day of the season that pickup will occur, [[Start Month, Start Day], [[End Month, End Day]]*/
var openSeason = [[1,1],[12,31]]
//Specify any holidays where pickup will not occur, [Month, Day]
var holidays = [[1,1],[7,4],[12,25]]
/*Specify any variable holidays where pickup will not occur, [Occurrence, Month, Day of the Week (Sunday = 0, Saturday = 6)]
These are holidays that don't fall on the same date every year, i.e. Memorial Day, Labor Day, Thanksgiving
[-1,5,1] corresponds to Memorial Day -> Last occurrence in May of a Monday
[1,9,1] corresponds to Labor Day -> 1st occurrence in September of a Monday
[4,11,4] corresponds to Thanksgiving -> 4th occurrence in November of a Thursday*/
var variableHolidays = [[-1,5,1],[1,9,1],[4,11,4]];
/*Specify if the next scheduled pickup day falls on a holiday, when will the next actual pickup be.
"Next Weekday" - The pickup will occur on the next weekday after the holiday
"Next Day" - The pickup will occur on the next day after the holiday
"Next Scheduled Pickup" - The pickup will occur on the next scheduled day after the holiday*/
var nextPickupHoliday = "Next Weekday";
var pickupDays = [];
var pickupDaysFields = [$feature.SUNDAY, $feature.MONDAY, $feature.TUESDAY,
$feature.WEDNESDAY, $feature.THURSDAY,
$feature.FRIDAY, $feature.SATURDAY]
for (var k in pickupDaysFields) {
if (pickupDaysFields[k] == 'Yes') {
pickupDays[Count(pickupDays)] = k;
}
}
if (Count(pickupDays) == 0)
return;
function calcRelativeHoliday(week, month, day, year) {
var holiday;
if (week < 0){
var lastDay = DateAdd(Date(year, month + 1, 1), -1, 'days');
var dayOfWeek = Weekday(lastDay);
var dayDiff = day - dayOfWeek;
if (dayDiff > 0)
dayDiff -= 7;
holiday = DateAdd(lastDay, dayDiff + ((week + 1) * 7), 'days');
}
else{
var firstDay = Date(year, month, 1);
var dayOfWeek = Weekday(firstDay);
var dayDiff = day - dayOfWeek;
if (dayDiff < 0)
dayDiff += 7;
holiday = DateAdd(firstDay, dayDiff + ((week - 1) * 7), 'days');
}
return holiday;
}
function getNextPickupDay(fromDate) {
var currentDay = Weekday(fromDate);
var pickupOffset = 0;
if (pickupWeekInterval > 1){
var weekDif = DateDiff(DateAdd(fromDate, 0 - currentDay, 'days'),
DateAdd(firstPickupWeek, 0 - Weekday(firstPickupWeek), 'days'),
'days') / 7;
weekDif = weekDif % pickupWeekInterval;
if (weekDif > 0)
pickupOffset = pickupWeekInterval - weekDif;
}
var difDays;
var nextPickupDay;
if (pickupOffset > 0) {
nextPickupDay = pickupDays[0];
difDays = nextPickupDay - currentDay;
difDays += (7 * pickupOffset);
}
else {
for(var k in pickupDays) {
if (pickupDays[k] >= currentDay) {
nextPickupDay = pickupDays[k];
break;
}
}
if (IsEmpty(nextPickupDay))
nextPickupDay = pickupDays[0];
difDays = nextPickupDay - currentDay;
if (nextPickupDay < currentDay)
difDays += (7 * pickupWeekInterval);
}
return DateAdd(fromDate, difDays, 'days');
}
function getHolidays(fromDate) {
var holidayDates = [];
for (var k in holidays) {
var holiday = Date(Year(fromDate), holidays[k][0] -1, holidays[k][1]);
if (holiday < fromDate)
holiday = Date(Year(fromDate) + 1, holidays[k][0] -1, holidays[k][1]);
holidayDates[k] = holiday;
}
for (var k in variableHolidays) {
var x = variableHolidays[k];
var holiday = calcRelativeHoliday(x[0], x[1]-1, x[2], Year(fromDate));
if (holiday < fromDate)
holiday = calcRelativeHoliday(x[0], x[1]-1, x[2], Year(fromDate) + 1);
holidayDates[Count(holidayDates)] = holiday;
}
return holidayDates;
}
function validateSeasonPickup(pickupDate) {
var startSeasonMonth = openSeason[0][0]-1;
var startSeasonDay = openSeason[0][1];
var endSeasonMonth = openSeason[1][0]-1;
var endSeasonDay = openSeason[1][1];
if (Date(Year(pickupDate), startSeasonMonth, startSeasonDay) > Date(Year(pickupDate), endSeasonMonth, endSeasonDay)) {
if (pickupDate < Date(Year(pickupDate), startSeasonMonth, startSeasonDay) && pickupDate > Date(Year(pickupDate) - 1, endSeasonMonth, endSeasonDay))
pickupDate = getNextPickupDay(Date(Year(pickupDate), startSeasonMonth, startSeasonDay))
}
else {
if (pickupDate < Date(Year(pickupDate), startSeasonMonth, startSeasonDay))
pickupDate = getNextPickupDay(Date(Year(pickupDate), startSeasonMonth, startSeasonDay));
else if (pickupDate > Date(Year(pickupDate), endSeasonMonth, endSeasonDay))
pickupDate = getNextPickupDay(Date(Year(pickupDate) + 1, startSeasonMonth, startSeasonDay));
}
return pickupDate;
}
function validateHolidayPickup(pickupDate, holidayDates) {
for(var k in holidayDates) {
if (pickupDate == holidayDates[k]) {
if (nextPickupHoliday == "Next Scheduled Pickup") {
pickupDate = getNextPickupDay(DateAdd(pickupDate, 1, 'days'));
}
else if (nextPickupHoliday == "Next Day") {
pickupDate = DateAdd(pickupDate, 1, 'days');
}
else if (nextPickupHoliday == "Next Weekday") {
var currentDay = Weekday(pickupDate);
if (currentDay > 4) {
pickupDate = DateAdd(pickupDate, 8 - currentDay, 'days');
}
else {
pickupDate = DateAdd(pickupDate, 1, 'days');
}
}
break;
}
}
return pickupDate
}
var nextPickup = getNextPickupDay(Today());
nextPickup = validateSeasonPickup(nextPickup);
nextPickup = validateHolidayPickup(nextPickup, getHolidays(nextPickup));
return Text(nextPickup, 'dddd, MMMM D');
I genuinely appreciate any help and suggestions for best or better practices when working with expressions. Thanks all!
@ScottOppmann