Workflow end date issue

*here is an issue in the workflow logic related to calculating the user’s end date. Currently, the user end date is provided in months, rather than a specific date. We need to add this duration (in months) to the user’s start date in order to calculate the actual end date as a date value

i tried to add the number of months to the date but it cannot be added as it’s string value

Have you tried using a transform for calculating the end date instead of using a workflow?

The end date will be added from a form field and it’s only in numbers according to company policy from 1 to 6 in months

I have the exact same issue. We are currently attempting to leverage a form and workflow for contractor creation in a Non-Employee source. As we are unable to set any validation against the date field in the form (there is a non-negotiable requirement to disallow end dates beyond 12 months from the start date) I’ve had to specify a contract duration instead. e.g. 1,3,6 months etc.

I can’t determine any mechanism within workflows to convert strings to int. I also thought of doing a series of compares but then we still need determine which DefineVariable element to select from for all the emails that are sent for subsequent approval forms that are generated and HTTP Request which creates the NELM user

In that cause it sounds like you maybe casting the field incorrectly. Causing it to be a string instead of a date value. Are you able to share you form config?

Ok, i was able to spend a short amount of time on it today. I have a solution, a dirty one, but it works.

Create a ladder of compare strings:

Then in each of these check the duration variable against each possible option that can be selected from in your form. For you it will be 1-6. Therefore, you will have 5 compare strings for =“1”, =“2”,=“3”,=“4”,=“5” with the last one setting 6 months as the false result. From each of these compares, set a Variable in Define Variable with the exact same name defined in each (i.e. endDate). In each of these, add the corresponding number of months to the start date in the variable editor.

Lastly, have each of these Define Variables link to another single Define Variable. Define a variable in here, in the editor set an attribute with the following JSONPath:

$[‘defineVariable1’,‘defineVariable2’,‘defineVariable3’,‘defineVariable4’,‘defineVariable5’].endDate

There will be 6 of them for your use case and the numbering may differ for you depending on how many other defineVariables you already had in your workflow. What happens here is that it will only resolve the defineVariableX.endDate which has a value. Due to the structure of Compare Strings defined here, only one will ever have a value. Then you will leverage this last DefineVariable for any subsequent emails, http requests, forms, etc you are using later in the workflow.

I think I only have a solution of up to 10 months.

Define the variable base on (“012345678910” index of [the number of months].)

e.g. if number of months is 2, then index of 2 from the above string is 2, in number.

I suppose you can do “0123456789101112”…but you’ll need to do two additional IFs after that, (e.g. if returned index is 14, it’s really is meant to be 12)

The other, similar, alternative is this, change the form to have an alphabet prefix for the month selection, like:
a. 1
b. 2
c. 3

There, with that input string of say, “d. 4”, you’ll just need to do “xabcdefghijkl” index of (substring 0, 1 of “d. 4”).

This will return a number of 1 to 12.

@yasserdex777 -

Here’s a straightforward way to think about how the workflow calculates the user’s end date:

  1. Get the user’s current information

    • The Get Identity step pulls the user’s data (including their startDate and the number of months that represent their end date, called endDateMonths here).
    • This data comes from $.trigger.identity.id, meaning it’s using the identity ID from the event that triggered this workflow.
  2. Define Variables

    • Inside Define Variables, we create three variables:

      1. startDate
        • Pulled from $.getIdentity.attributes.startDate.
      2. endDateMonths
        • Pulled from $.getIdentity.attributes.endDateMonths (the user’s end date in “months” form, a numeric value).
      3. calculatedEndDate
        • First uses the Add Time transform (sp:transform:addTime:time) to add endDateMonths months to the startDate.
        • Then applies the Date Format transform (sp:transform:formatDate:string) to convert the date into a text format (YYYY-MM-DD).
        • In other words, it says: “Take the startDate, add the specified number of months to it, then convert that updated value into a YYYY-MM-DD format.”
    • The result of this is a nicely formatted date in calculatedEndDate.

  3. Update Identity

    • Once we have calculatedEndDate, the workflow updates the user’s record with this new “actual” end date.
    • It does so by making a PATCH request (the sp:http action) to the IdentityNow API (https://api.identitynow.com/v3/identities), sending along the new endDate value from calculatedEndDate.
    • This means the user’s profile in IdentityNow will store a precise, calendar-based date rather than just a number of months.
  4. Finish Up

    • The workflow ends with End Step - Success once the identity record is updated.

Below is the full JSON, with each piece corresponding to the explanation above:

{
  "name": "Transform User End Date",
  "description": "Transforms the user end date from months to a specific date by adding the duration to the user's start date",
  "modified": "2025-04-08T07:23:44.876934669Z",
  "modifiedBy": {
    "type": "IDENTITY",
    "id": "902586a42cd3424a86bcc82a1a8697f6",
    "name": "official.amit"
  },
  "definition": {
    "start": "Get Identity",
    "steps": {
      "Get Identity": {
        "actionId": "sp:get-identity",
        "attributes": {
          "id.$": "$.trigger.identity.id"
        },
        "displayName": "",
        "nextStep": "Define Variables",
        "type": "action",
        "versionNumber": 2
      },
      "Define Variables": {
        "attributes": {
          "id": "sp:define-variable",
          "variables": [
            {
              "name": "startDate",
              "transforms": [],
              "variableA.$": "$.getIdentity.attributes.startDate"
            },
            {
              "name": "endDateMonths",
              "transforms": [],
              "variableA.$": "$.getIdentity.attributes.endDateMonths"
            },
            {
              "name": "calculatedEndDate",
              "transforms": [
                {
                  "id": "sp:transform:addTime:time",
                  "input": {
                    "length.$": "$.endDateMonths",
                    "unit": "months"
                  }
                },
                {
                  "id": "sp:transform:formatDate:string",
                  "input": {
                    "dateFormat": "YYYY-MM-DD"
                  }
                }
              ],
              "variableA.$": "$.startDate"
            }
          ]
        },
        "displayName": "",
        "nextStep": "Update Identity",
        "type": "Mutation"
      },
      "Update Identity": {
        "actionId": "sp:http",
        "attributes": {
          "authenticationType": "OAuth",
          "basicAuthPassword": "",
          "basicAuthUserName": "testUser",
          "headerAuthName": "password",
          "headerAuthValue": "",
          "jsonRequestBody": {
            "attributes": {
              "endDate.$": "$.defineVariables.calculatedEndDate"
            },
            "id.$": "$.trigger.identity.id"
          },
          "method": "patch",
          "oAuthClientId": "client",
          "oAuthClientSecret": "",
          "oAuthCredentialLocation": "oAuthInHeader",
          "oAuthScope": "NONE",
          "oAuthTokenUrl": "https://devrel.api.identitynow.com",
          "requestContentType": "json",
          "requestHeaders": {
            "TestHeader": "TestHeaderValue"
          },
          "url": "https://api.identitynow.com/v3/identities",
          "urlParams": {
            "limit": "2"
          }
        },
        "displayName": "",
        "nextStep": "End Step - Success",
        "type": "action",
        "versionNumber": 2
      },
      "End Step - Success": {
        "displayName": "",
        "type": "success"
      }
    }
  },
  "creator": {
    "type": "IDENTITY",
    "id": "902586a42cd3424a86bcc82a1a8697f6",
    "name": "official.amit"
  },
  "trigger": {
    "type": "EVENT",
    "attributes": {
      "id": "idn:identity-attributes-changed"
    }
  }
}

In simpler terms: The workflow’s core logic is to take the user’s start date, add a certain number of months, format that as a standard calendar date, and then update the user’s IdentityNow record. That way, the user’s end date is stored as a properly formatted date instead of just a numeric month count.

Hope this helps.

This response is predicated on the fact that 'endDateMonths" is of int datatype. Given we are pulling this value from a static Select Field in a Form. It can only be provided as a string. The issue here is using that string to provide a value that must be of type int. My previous response and Terry’s response provide sufficient workarounds in lieu of any method of datatype conversion within the workflow engine.

Thanks for your reply, but you cannot add months to a date format because number of months is string and cannot be added to a date format iw will give you paring error