Arcade: Allow Date() values in date fields (esriFieldTypeDate)

2423
9
08-21-2022 11:35 PM
Status: Open
JohannesLindner
MVP Frequent Contributor

In things like Dashboards or Popups, it is common to create your own FeatureSet in the Arcade code. These FeatureSets often have date columns, these are defined with the field type "esriFieldTypeDate".

If you input a feature with a Date() attribute, the FeatureSet will be empty:

 

var fs_dict = {
    fields: [
        {name: 'DateField', type: 'esriFieldTypeDate'}
        ],
    features: [
        {attributes: {DateField: Now()}}
        ],
    geometryType: ''
}
return FeatureSet(Text(fs_dict))

 

JohannesLindner_0-1661149916211.png

 

 

To insert a date, you have to convert to Number() first (line 6):

 

var fs_dict = {
    fields: [
        {name: 'DateField', type: 'esriFieldTypeDate'}
        ],
    features: [
        {attributes: {DateField: Number(Now())}}
        ],
    geometryType: ''
}
return FeatureSet(Text(fs_dict))

 

JohannesLindner_1-1661149987926.png

 

This is absolutely not a behavior users expect and it leads to confusion regularly.

Please change the FeatureSet creation to allow Date() values in esriFieldTypeDate fields.

9 Comments
abrown8

This had me stumped for ages, trying a range of things before I came across your post! Definitely not expected behaviour and is wasting time by not being common knowledge when using data expressions.

Scott_Sambell

Oh how i wish i had found this post earlier! Thanks so much for directing me here Johannes.  

BritaAustin

Do you need to declare the number for a date if used in the script, but is not included in dictionary? I've included my script below, it returns empty. 

 

var portal = Portal("https://arcgis.com");
var fs = FeatureSetByPortalItem(
  portal,
  "MY_ITEM_NUM_HERE",
  0,
  [
    "date",
    "name",
    "sum_numberoftrainees",
    "sum_numberofqualified",
  ],
  false
);



var currentDate = Date(Max(fs, 'date'));
var monthAgo = Text(DateAdd(currentDate, -1, "month"), "YYYY-MM-DD");
currentDate = Text(currentDate, "YYYY-MM-DD");



var current = Filter(fs, "date = @currentDate");
var lastMonth = Filter(fs, "date = @monthAgo");



var dict = {
  fields: [
        {name: "name", type: "esriFieldTypeString"},
        {name: "current_trainee", type: "esriFieldTypeDouble"},
        {name: "month_ago_trainee", type: "esriFieldTypeDouble"},
        {name: "current_qualified", type: "esriFieldTypeDouble"},
        {name: "month_ago_qualified", type: "esriFieldTypeDouble"},
  ],
  geometryType: "",
  features: [],
};



for (var c in current) {
  for (var l in lastMonth) {
    dict.features[0] = {
      attributes: {
        name: c["name"],
        current_trainee: c["sum_numberoftrainees"],
        month_ago_trainee: l["sum_numberoftrainees"],
        current_qualified: c["sum_numberofqualified"],
        month_ago_qualified: l["sum_numberofqualified"],
      },
    };
  }
}
return FeatureSet(Text(dict));

 

@JohannesLindner @DavidNyenhuis1  - any assitance or direction on this is so greatly appreciated!

DavidNyenhuis1

Hi @BritaAustin

The Number(myDate) essentially converts it to an EPOCH value. This is only necessary for in the dictionary for constructing the Feature Set. (Checking to see there are any options or plans to change this requirement, as it does trip a lot of people up). 

In your scenario, I don't think this is the problem -- you aren't creating any date fields in your new feature set. It looks like your looping logic might need some work starting at line 44 (you aren't incrementing the feature index). 

JohannesLindner

@DavidNyenhuis1 , @Anonymous User Any news on this isssue?

 

I just answered another question about this and got curious. Here are some questions I found in a very cursory search where converting the Date() to Number() was the solution, I probably missed a few.

Arcade script to split multi pick field values - Esri Community

ArcGIS Dashboard Using Arcade to union two dataset... - Esri Community

Solved: Help getting a data expression to work. - Esri Community

Solved: Arcade Expression: No values returned by FeatureSe... - Esri Community

Solved: Arcade dictionary to FeatureSet - Esri Community

Solved: How to maintain date data in arcade expressions - Esri Community

Arcade FeatureSets and Date Fields: What's Going O... - Esri Community

Solved: esriFieldTypeDate in Data Expression in Dashboard ... - Esri Community

Solved: Arcade Data Expressions with Date Column Not Worki... - Esri Community

Solved: Date fields in data expressions for serial charts - Esri Community

Solved: Feature not being created due to date field type - Esri Community

Solved: Arcade Data Expression- Dictionary from multiple t... - Esri Community

Solved: Pass values to new columns Arcade - Esri Community

Solved: Re: Arcade - How to use a date field with a dictio... - Esri Community

 

There are probably many users who have the same problem but didn't ask a question (I know I was). They either got the solution from an already solved question (good: they got a solution, bad: they had this easily avoidable problem in the first place) or they couldn't solve this problem and moved on (obviously bad).

DavidNyenhuis1

Hi @JohannesLindner ,

Thank you for digging all these up and helping users with many of them. I have brought it to the attention of the Arcade team and they will discuss it. 

It sounds like there are some complexities around the feature layer specification (requiring EPOCH) and time zones (e.g., an Arcade date is in local time), but that is not to say a solution cannot be had. I'll keep you posted. 

For the time being, I thought I'd share a little helper function to convert dates in a feature to EPOCH. I will have to check if it is accounting for time zone correctly though. 

// Since a esriTypeDate can't take an Arcade Date, need to cast to EPOCH
// Pass in a feature
function CastDatesToEpoch(feat) {
    var modifiedAttributes = {};
    for (var att in feat) {
        if(TypeOf(feat[att]) == 'Date') {
            modifiedAttributes[att] = Number(feat[att])
            // Console(`${feat[att]} is now ${Number(feat[att])}`)
        }
        else {
            modifiedAttributes[att] = feat[att]
        }
    }
    return modifiedAttributes
}

var fs = FeatureSetByPortalItem(Portal('https://www.arcgis.com'), item, sublayer, ["*"], fetchGeom);
// Define a new dictionary feature set
var sch = Schema(fs);
var dict = {
  'fields': sch.fields,
  'geometryType': sch.geometryType, // Can be esriGeometryNull, esriGeometryPoint, esriGeometryPolyline, esriGeometryPolygon;
  'features': []
};
// Do something to each feature, like add a field, then add it to the dictionary
var index = 0;
for (var f in fs) {
    // Add each feature to new dictionary and cast dates to EPOCH
    dict.features[index] = {
        'geometry': Geometry(f),
        'attributes': CastDatesToEpoch(f)
    }
    index++;
}
// Convert dictionary to feature set.
return FeatureSet(Text(dict));

 

jzibbell_boise

This saved me, thank you!!

DavidNyenhuis1

@jzibbell_boise, with this week's update to Arcade and ArcGIS Dashboards, this issue is fixed. Dates in feature sets now just work. You no longer have to wrap dates with Number() if you pass the dictionary into the FeatureSet() function (which as of this release accepts a dictionary as opposed to only text based JSON).

Instead of:

return FeatureSet(Text(dict))

Do this:

return FeatureSet(dict)

Learn more on this blog post

 

NOTE: For Enterprise users, this update is targeted for 11.2

jzibbell_boise

@DavidNyenhuis1 thanks! Our Portal where I'm building the dashboards is behind versions, but in the future this will be helpful!