BLOG ARTICLE

Working with Time data type in Flows

Share This Post

Discover innovative solutions to manage time data types in Salesforce Flow, including overcoming time zone challenges and the absence of native Time data support. Learn how to employ Apex classes and custom LWC components to ensure accurate time inputs in local time zones, enhancing data precision and user interaction in your Salesforce applications. 

Introduction to Time Data Types

Time is a data type we often need to collect and store. When time is bound to a specific date and time zone we use Date/Time. Time data type comes in handy when we want to avoid time zone dependency, for example, data like flight arrival and departure time. It could be in different time zones than the user, but we always want to show it in the time zone of the location rather than the user.

Salesforce Flow supports Date/Time data type and formula functions, but the Time data type is not supported yet and TIMEVALUE() function doesn’t work in Flow. There is an Idea on IdeaExchange to implement this, unfortunately without any comment from Salesforce.

NOTE: Working Hours is just an example, we don’t try to replace the Operating Hours object.

Time Values and Salesforce Flow

Time values can be cast and held in Date/Time variables. Then they even can be used in Create or Update Record elements. However, the result will be affected by time zones and won’t satisfy a user without additional processing. This is why:

Date/Time values are stored in GMT (UTC). Assume the users’ time zone is GMT-8. When the user saves Date/Time 2024–08–13 12:00:00 it’s stored as 2024–08–13 04:00:00Z in the database (GMT). Nevertheless, it is displayed in the users’ time zone. The problem is that Flow has no built-in feature to get the time component of a Date/Time in the local time zone of the context user.

Let's go through workarounds now!

Workaround #1: Get Time Values from Existing Records

For this purpose, we will create an Apex class with an invocable method. This method can be called from a Flow and will return a list of DateTime values modified to provide the expected result when we create or update records with Time fields. More details are in the code comments.

				
					public with sharing class FlowAction_GetTime {
    /**
     * @description getTime returns Time converted to Datetime we can use in Flows.
     * If the field has no value, the method will return null.
     * The number of elements in the returned array is always equal to the number of fields passed to the parameter
     * @param  params  List<FlowTime>
     * @return         List<List<Datetime>> that actually acts like just a List<Datetime>
     */
    @InvocableMethod(label='Get Time' description='Returns Time converted to Datetime. It returns null when field has no value' iconName='slds:standard:date_time')
    public static List<List<Datetime>> getTime(List<FlowTime> params) {
        List<Datetime> dateTimes = new List<Datetime>();
        String datePart = '2000-01-01'; //any date can replace this
        for (FlowTime ft : params) {
            sObject record = ft.record;
            for (String field :  ft.timeFields.split(',')) {
                if (field == null || field.isWhitespace()) {
                    continue; // skip items without actual value
                }
                if (record.get(field.trim()) != null) {
                    Time timeValue = (Time)record.get(field.trim());
                    String timePart = String.valueOf(timeValue).left(8); // without milliseconds
                    dateTimes.add(Datetime.valueOfGmt(datePart + ' ' + timePart));
                } else {
                    dateTimes.add(null); // indicates that field has no value
                }
            }    
        }
        return new List<List<Datetime>>{ dateTimes };
    }
    /**
     * @description Wrapper for input parameters
     */
    public class FlowTime {
        /**
         * @description record with fields of Time datatype
         */
        @InvocableVariable(label='Record with Time fields'  required=true)
        public sObject record;
        /**
         * @description API names of Time fields of the given record
         */
        @InvocableVariable(label='Comma-separated list of Time fields API names' required=true)
        public String timeFields;
    }
}

				
			

NOTE: When we instantiate Time or Date/Time from a string, it must be of the following format:

Time

Date/Time

HH:MM:SS.MS
17:30:45.125

YYYY-MM-DD HH:MM:SS
2024-02-19 12:00:00

Workaround #2: Take Users' Time Input in Screen Flows

Here we will need a custom LWC that will take time input and pass it as a string to a Screen Flow where we will convert this string to the appropriate Date/Time.

LWC Coponents
  • flowTime.html
  • flowTime.js
  • flowTime.js-meta.xml

flowTime.html

				
					<template>
    <lightning-input
        type="time"
        name="timeInput"
        label={label}
        value={value}
        onchange={handleChange}
    >
    </lightning-input>
</template>
				
			

flowTime.js

				
					import { LightningElement, api } from 'lwc';
export default class FlowTime extends LightningElement {
    @api label = 'Enter Time';
    //e.g. 18:30:00.000 (HH:MM:SS.MS)
    @api value;
    //e.g. 2000-01-01 18:30:00 (YYYY-MM-DD HH:MM:SS)
    @api timeInDateTimeString;


    handleChange(event) {
        let value = event.detail.value;
        this.value = value;
        //any date can replace 2000-01-01. We can attach it in the Flow instead
        //we remove milliseconds since they are not expected by DATETIMEVALUE() formula function
        this.timeInDateTimeString = `2000-01-01 ${value.split('.')[0]}`;
    }
}

				
			

flowTime.js-meta.xml

				
					<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>60.0</apiVersion>
    <masterLabel>flowTime</masterLabel>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__FlowScreen</target>
    </targets>
    <targetConfigs>
        <targetConfig targets="lightning__FlowScreen">
            <property name="timeInDateTimeString" type="String" role="outputOnly"/>
            <property name="label" type="String" role="inputOnly"/>
        </targetConfig>
     </targetConfigs>
</LightningComponentBundle>

				
			

Using flowTime

Don’t forget to manually assign variables from the Advanced tab while editing screen.

NOTE: Ensure new time values are correctly assigned in the Create or Update Record elements to avoid errors.

It’s important to assign new time values in the Create or Update Record elements itself (“Specify conditions to identify records, and set fields individually”). Using the assignment element first will lead to an INVALID_TYPE_ON_FIELD_IN_RECORD error.

Values named startTimeInDateTime and endTimeInDateTime are just formulas taking the string from the flowTime LWC, and converting it to Date/Time via the DATETIMEVALUE() function. As simple as that: DATETIMEVALUE({!startTimeInDateTimeString})

All code can be found in this GitHub repository. It contains everything we went through, plus sample Screen Flow which uses getTime invocable Apex and test class for it.

Have questions yet? Don’t hesitate to contact TVA, Loki, or us 🙂

About the Author
Mykola Kanunnikov, Junior Salesforce Developer at Nubessom Consulting

Mykola Kanunnikov, Junior Salesforce Developer at Nubessom Consulting

Junior Salesforce Developer with a rich background that includes earning the Salesforce PD1 certification and developing the innovative CTU Freight Container Packing Checklist app, now available on AppExchange.

Let´s talk about your challenge!

    In order to provide you the content requested, we need to store and process your personal data. If you consent to us storing your personal data for this purpose, please tick the checkbox below.


    You can unsubscribe from these communications at any time. For more information on how to unsubscribe, our privacy practices, and how we are committed to protecting and respecting your privacy, please review our Privacy Policy.

    Need more Inspiration? keep reading Our related content

    Blog Article

    Generate Magic Links for your users in Experience Cloud

    A magic link, or one-time login (OTL) or passwordless login link, is a unique, time-sensitive URL sent to a user’s registered email address as a secure means of authentication. Learn how to generate them in Experience Cloud (Community Cloud)
    Read More »