Hi-
I am using the labeling from this link for my street sweeping application and the date is incorrect
Create Map - My Government Services | ArcGIS for Local Government
It is returning the same for routes with different sweep days. Example, sweep day for route 12 is Friday, but is returning a date of 3/25 and route 7 has a sweep day of Wednesday, but the expression is returning 3/25 as well.
Thanks!!
The code is below:
/*If the cleaning isn't available year-round
specify the first and last day of the season that cleaning will occur*/
var openSeason = [[1,1],[12,31]]
var cleaningWeek = [];
var cleaningWeekFields = [$feature.WEEKONE, $feature.WEEKTWO,
$feature.WEEKTHREE, $feature.WEEKFOUR]
for (var k in cleaningWeekFields) {
if (cleaningWeekFields == 'Yes') {
cleaningWeek[Count(cleaningWeek)] = k;
}
}
if (Count(cleaningWeek) == 0)
return;
function getNextCleaningWeek(fromDate) {
var firstSundayCurrentMonth = Date(Year(fromDate), Month(fromDate), 1);
var firstWeekday = Weekday(firstSundayCurrentMonth);
if (firstWeekday > 0)
firstSundayCurrentMonth = DateAdd(firstSundayCurrentMonth, 7 - firstWeekday, 'days');
for (var k in cleaningWeek) {
var startCleaningWeek = DateAdd(firstSundayCurrentMonth, (cleaningWeek*7), 'days');
if (fromDate <= startCleaningWeek)
return [startCleaningWeek, DateAdd(startCleaningWeek, 6, 'days')];
}
var firstSundayNextMonth = Date(Year(fromDate), Month(fromDate) + 1, 1);
var firstWeekday = Weekday(firstSundayNextMonth);
if (firstWeekday > 0)
firstSundayNextMonth = DateAdd(firstSundayNextMonth, 7 - firstWeekday, 'days');
var startCleaningWeek = DateAdd(firstSundayNextMonth, (7 * cleaningWeek[0]), 'days');
return [startCleaningWeek, DateAdd(startCleaningWeek, 6, 'days')];
}
function validateSeasonCleaning(cleaningWeek) {
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(cleaningWeek[1]), startSeasonMonth, startSeasonDay) > Date(Year(cleaningWeek[1]), endSeasonMonth, endSeasonDay)) {
if (cleaningWeek[1] < Date(Year(cleaningWeek[1]), startSeasonMonth, startSeasonDay) && cleaningWeek[1] > Date(Year(cleaningWeek[1]) - 1, endSeasonMonth, endSeasonDay))
cleaningWeek = getNextCleaningWeek(Date(Year(cleaningWeek[1]), startSeasonMonth, startSeasonDay))
}
else {
if (cleaningWeek[1] < Date(Year(cleaningWeek[1]), startSeasonMonth, startSeasonDay))
cleaningWeek = getNextCleaningWeek(Date(Year(cleaningWeek[1]), startSeasonMonth, startSeasonDay));
else if (cleaningWeek[1] > Date(Year(cleaningWeek[1]), endSeasonMonth, endSeasonDay))
cleaningWeek = getNextCleaningWeek(Date(Year(cleaningWeek[1]) + 1, startSeasonMonth, startSeasonDay));
}
return cleaningWeek;
}
var nextCleaning = getNextCleaningWeek(Today());
nextCleaning = validateSeasonCleaning(nextCleaning);
return Text(nextCleaning[0], 'MMMM D, YYYY');
Can you use these instructions (https://community.esri.com/docs/DOC-8691-posting-code-with-syntax-highlighting-on-geonet ) to edit your post (use Javascript as language) and insert the code using the correct indentation? It is very difficult to interpret the code as it is. There is one thing to keep in mind. When you create a date the month is a value in the range from 0 to 11, not 1 to 12.
I have done something similar for sweeping streets of Medellín:
http://utility-esri-co.maps.arcgis.com/apps/Styler/index.html?appid=d69c88aacf9a47d0bf9a3ea8bf16c590
And something for the collection of solid waste:
http://utility-esri-co.maps.arcgis.com/apps/View/index.html?appid=c381a2e150ef4e4cb62b4027a31e0d45
I posted the code again per your suggestion, thanks. I checked out the solid waste collection app you created, pretty cool. I am trying to do the same thing.
Hi Whitney Loy , can you also include some test values for:
$feature.WEEKONE, $feature.WEEKTWO, $feature.WEEKTHREE and $feature.WEEKFOUR
... and the expected outcome for nextCleaning[0]?
That will allow me to track down what might be going wrong.
I think I am confused I copied the wrong code. My bad. The issue I am having is my routes very by week.
This is what 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 == '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 >= currentDay) {
nextPickupDay = pickupDays;
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[0] -1, holidays[1]);
if (holiday < fromDate)
holiday = Date(Year(fromDate) + 1, holidays[0] -1, holidays[1]);
holidayDates = holiday;
}
for (var k in variableHolidays) {
var x = variableHolidays;
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) {
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');
OK, thanks for sharing the other script. Can you provide some sample values for:
$feature.SUNDAY,
$feature.MONDAY,
$feature.TUESDAY,
$feature.WEDNESDAY,
$feature.THURSDAY,
$feature.FRIDAY,
$feature.SATURDAY
... and the corresponding expected values for the resulting nextPickup
Here is a link to the data.
Hi Whitney Loy ,
Thanks for sharing the data, but be careful since it is editable. I just did a small test with a list containing Monday and Thursday and it yielded Thursday, March 22 (in Spanish), which would be correct. I will do a test linking directly to the data to see what the result is.
Just did a test against your data in ArcGIS Online and it seems to provide the correct result:
I didn't change anything in your code just added some Console statements:
/*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]
// var pickupDaysFields = ['No', 'Yes', 'No', 'No', 'Yes', 'No', 'No']
Console("pickupDaysFields (Sun-Sat):" + pickupDaysFields);
for (var k in pickupDaysFields) {
if (pickupDaysFields[k] == 'Yes') {
pickupDays[Count(pickupDays)] = k;
}
}
if (Count(pickupDays) == 0)
return;
Console("pickupDays:" + pickupDays);
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');
}
Console("calcRelativeHoliday::holiday:" + holiday);
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);
}
Console("getNextPickupDay:" + DateAdd(fromDate, difDays, 'days'));
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;
}
Console("getHolidays::holidayDates:" + holidayDates);
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));
}
Console("validateSeasonPickup::pickupDate:" + pickupDate)
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;
}
}
Console("validateHolidayPickup::pickupDate:" + pickupDate);
return pickupDate
}
var nextPickup = getNextPickupDay(Today());
Console("nextPickup (1):" + nextPickup);
nextPickup = validateSeasonPickup(nextPickup);
Console("nextPickup (2):" + nextPickup);
nextPickup = validateHolidayPickup(nextPickup, getHolidays(nextPickup));
Console("nextPickup (3):" + nextPickup);
Console("return:" + Text(nextPickup, 'dddd, MMMM D'));
return Text(nextPickup, 'dddd, MMMM D');
This is returned to the Console:
pickupDaysFields (Sun-Sat):[null,null,null,null,"Yes",null,null]
pickupDays:[4]
getNextPickupDay:2018-03-22T00:00:00-05:00
nextPickup (1):2018-03-22T00:00:00-05:00
validateSeasonPickup::pickupDate:2018-03-22T00:00:00-05:00
nextPickup (2):2018-03-22T00:00:00-05:00
calcRelativeHoliday::holiday:2018-05-28T00:00:00-05:00
calcRelativeHoliday::holiday:2018-09-03T00:00:00-05:00
calcRelativeHoliday::holiday:2018-11-22T00:00:00-05:00
getHolidays::holidayDates:["2019-01-01T00:00:00-05:00","2018-07-04T00:00:00-05:00","2018-12-25T00:00:00-05:00","2018-05-28T00:00:00-05:00","2018-09-03T00:00:00-05:00","2018-11-22T00:00:00-05:00"]
validateHolidayPickup::pickupDate:2018-03-22T00:00:00-05:00
nextPickup (3):2018-03-22T00:00:00-05:00
return:Thursday, March 22
If one of these expressions is working, you should consider adding it as a template to the arcade-expressions repo so others can benefit from it: GitHub - Esri/arcade-expressions: ArcGIS Arcade expression templates for all supported profiles in t...
Here's a blog post describing the repo: Share your Arcade expressions as templates | ArcGIS Blog