Follow the link to learn more about us.
Interview with Website Planet
Follow the link to learn more about us.
The Local Time App for Salesforce has out-of-the-box support for getting the time zone information for Account, Contact, Lead, and Task standard Salesforce objects. We have now extended the App’s functionality to also support the Salesforce User object.
There are two options to show the time zone information on the User records. Option 1 is to add the Local Time lightning component to the User lightning record page layouts. However, if you want to have time zone information stored as custom fields, so that you can use them in your User related processes and automations, then Option 2 is the preferred solution.
This blog post describes the steps involved in enabling Option 2.
It is assumed that you have installed Local Time App version v2.29 or later in your sandbox and production environments. You can install the latest version of the App from this link.
From Local Time Config tab -> Settings subtab, configure the User object to use the appropriate address and phone fields. Click the Save button to update the App settings.
From Local Time Config tab -> Settings subtab, enable the triggers on the User object and click the Save button to update the App settings.
Modify the User lightning record page layouts and add the Timezones object as a related list and save the page layout settings. After this step, whenever a user record is created or updated, you will see the time zone information as shown below in Option 2.
The child Timezone (API Name: tz__Timezone__c) record has all the relevant custom fields that you can query and use in your automations.
As mentioned in the previous blog post, the approach discussed there has a limitation. If the Scheduled Start or Scheduled End values are in the future (crossing the DST), the formula still uses the current time zone and UTC Offset fields, instead of using the time zone and UTC Offset values that are relevant for the future date. As a consequence, the calculated Scheduled Start Date or Scheduled End Date values could be potentially off by an hour, and thus inaccurate.
In this post, we will discuss a code based approach that overcomes this limitation. We will use the ServiceAppointment object as an example. The ServiceAppointment has lookup fields to both Account and Contact objects. We will use the Account field in our example and you can easily extend this logic to Contact field if needed.
From Setup -> Object Manager -> Field Service, select the ServiceAppointment object and create the following fields.
Label | API Name | Data Type | Comments |
---|---|---|---|
Scheduled Start Date | Scheduled_Start_Date__c | Formula (Text) | Scheduled start date in customer local time zone. |
Scheduled End Date | Scheduled_End_Date__c | Formula (Text) | Scheduled end date in customer local time zone. |
Scheduled Start Timezone | Scheduled_Start_Timezone__c | Text(10) | Timezone of the scheduled start date. |
Scheduled End Timezone | Scheduled_End_Timezone__c | Text(10) | Timezone of the scheduled end date. |
Scheduled Start UTC Offset | Scheduled_Start_UTC_Offset__c | Number(3, 2) | UTC offset for the scheduled start date. |
Scheduled End UTC Offset | Scheduled_End_UTC_Offset__c | Number(3, 2) | UTC offset for the scheduled end date. |
IF(ISBLANK(Scheduled_Start_UTC_Offset__c), "Unknown", MID( TEXT( SchedStartTime+ Scheduled_Start_UTC_Offset__c /24 ), 6, 2 ) & "/" & MID( TEXT( SchedStartTime+ Scheduled_Start_UTC_Offset__c /24 ), 9, 2 ) & "/" & LEFT( TEXT( SchedStartTime+ Scheduled_Start_UTC_Offset__c /24 ), 4 ) & " " & TEXT( IF( OR( VALUE( MID( TEXT( SchedStartTime+ Scheduled_Start_UTC_Offset__c /24 ), 12, 2 ) ) = 0, VALUE( MID( TEXT( SchedStartTime+ Scheduled_Start_UTC_Offset__c /24 ), 12, 2 ) ) = 12 ), 12, VALUE( MID( TEXT( SchedStartTime+ Scheduled_Start_UTC_Offset__c /24 ), 12, 2 ) ) - IF( VALUE( MID( TEXT( SchedStartTime+ Scheduled_Start_UTC_Offset__c /24 ), 12, 2 ) ) < 12, 0, 12 ) ) ) &":"& MID( TEXT( SchedStartTime+ Scheduled_Start_UTC_Offset__c /24 ), 15, 2 ) &" "& IF( VALUE( MID( TEXT( SchedStartTime+ Scheduled_Start_UTC_Offset__c /24 ), 12, 2 ) ) < 12, "AM", "PM" ) & " " & Scheduled_Start_Timezone__c )
IF(ISBLANK(Scheduled_End_UTC_Offset__c), "Unknown", MID( TEXT( SchedEndTime+ Scheduled_End_UTC_Offset__c /24 ), 6, 2 ) & "/" & MID( TEXT( SchedEndTime+ Scheduled_End_UTC_Offset__c /24 ), 9, 2 ) & "/" & LEFT( TEXT( SchedEndTime+ Scheduled_End_UTC_Offset__c /24 ), 4 ) & " " & TEXT( IF( OR( VALUE( MID( TEXT( SchedEndTime+ Scheduled_End_UTC_Offset__c /24 ), 12, 2 ) ) = 0, VALUE( MID( TEXT( SchedEndTime+ Scheduled_End_UTC_Offset__c /24 ), 12, 2 ) ) = 12 ), 12, VALUE( MID( TEXT( SchedEndTime+ Scheduled_End_UTC_Offset__c /24 ), 12, 2 ) ) - IF( VALUE( MID( TEXT( SchedEndTime+ Scheduled_End_UTC_Offset__c /24 ), 12, 2 ) ) < 12, 0, 12 ) ) ) &":"& MID( TEXT( SchedEndTime+ Scheduled_End_UTC_Offset__c /24 ), 15, 2 ) &" "& IF( VALUE( MID( TEXT( SchedEndTime+ Scheduled_End_UTC_Offset__c /24 ), 12, 2 ) ) < 12, "AM", "PM" ) & " " & Scheduled_End_Timezone__c )
Implement the following trigger on the ServiceAppointment object.
trigger ServiceAppointmentLocalTimeTrigger on ServiceAppointment (before insert, before update) { ServiceAppointmentLocalTimeHelper.populateTimezoneInfo(Trigger.new); }
Implement the following apex class which is called from the trigger.
public with sharing class ServiceAppointmentLocalTimeHelper { public static void populateTimezoneInfo(List<ServiceAppointment> lstSA) { // The following logic is built based on timezone info from related accounts. // STEP 1 - get the related accounts Set<Id> acctIds = new Set<Id>(); for(ServiceAppointment sa : lstSA) { if(sa.AccountId != null) acctIds.add(sa.AccountId); } if(acctIds.IsEmpty()) { return; } // STEP 2 - Query the standard and DST timezone fields from the related accounts Map<Id, Account> mapAccts = new Map<Id, Account>(); for(Account acct : [SELECT Id, tz__UTF_Offset__c, tz__Timezone__c, tz__UTC_Offset_DST__c, tz__Timezone_DST__c, tz__Timezone_SFDC__c FROM Account WHERE Id IN :acctIds AND tz__UTF_Offset__c != null]) { mapAccts.put(acct.Id, acct); } // STEP 3 - Populate the timezone fields on the ServiceAppointment records for(ServiceAppointment sa : lstSA) { if(sa.AccountId == null) continue; Account acct = mapAccts.get(sa.AccountId); if(acct != null) { populateTimezone(sa, acct); } } } // check if the datetime value is observing DST or not. If DST is on, use the DST fields from the related account. Else use the standard (non-DST) fields. private static void populateTimezone(ServiceAppointment sa, Account acct) { if(sa.SchedStartTime != null) { Decimal startUTC = tz.LocalTimeV2.getUTCOffset(sa.SchedStartTime, acct.tz__Timezone_SFDC__c); if(startUTC == acct.tz__UTF_Offset__c) { // DST is off sa.Scheduled_Start_UTC_Offset__c = acct.tz__UTF_Offset__c; sa.Scheduled_Start_Timezone__c = acct.tz__Timezone__c; } else { // DST is on sa.Scheduled_Start_UTC_Offset__c = acct.tz__UTC_Offset_DST__c; sa.Scheduled_Start_Timezone__c = acct.tz__Timezone_DST__c; } } if(sa.SchedEndTime != null) { Decimal endUTC = tz.LocalTimeV2.getUTCOffset(sa.SchedEndTime, acct.tz__Timezone_SFDC__c); if(endUTC == acct.tz__UTF_Offset__c) { // DST is off sa.Scheduled_End_UTC_Offset__c = acct.tz__UTF_Offset__c; sa.Scheduled_End_Timezone__c = acct.tz__Timezone__c; } else { // DST is on sa.Scheduled_End_UTC_Offset__c = acct.tz__UTC_Offset_DST__c; sa.Scheduled_End_Timezone__c = acct.tz__Timezone_DST__c; } } } }
Create a test class to get adequate coverage for your trigger code. Following is a sample test class with some guidelines. Ensure that you make any changes to it where necessary for the test class to pass successfully.
// NOTE: It is important to set SeeAllData=true to ensure that the test class has the visibility to the Local Time App configuration custom settings @isTest(SeeAllData=true) private class ServiceAppointmentLocalTimeHelperTest { static testmethod void testTrigger(){ // Create the test account record // Create any other records, such as Work Order, Work Type, Service Territory etc. needed by the ServiceAppointment object // Create/Insert the ServiceAppointment record (sa). Doing so will fire the trigger on this object and populate the time zone related custom fields List<ServiceAppointment> lstSA = [SELECT Id, Scheduled_Start_Timezone__c FROM ServiceAppointment WHERE Id=:sa.Id]; // where sa is the ServiceAppointment record you created earlier system.assert(lstSA.size() == 1); system.assert(lstSA[0].Scheduled_Start_Timezone__c != null); } }
Add the custom fields to the ServiceAppoinment page layout. Whenever you create or edit the ServiceAppoinement record, the trigger will fire and calculate the values for these fields.
The related Account record in this example is in the US Pacific time zone. The calculated Scheduled Start Date and Scheduled End Date values are in the same time zone, namely Pacific Standard Time (PST).
The related Account record in this example is in the US Pacific time zone. The Scheduled End value is changed from 3/11/2023, 12:00 PM to 3/14/2023, 12:00 PM. The calculated Scheduled Start Date value is in PST but the calculated Scheduled End Date value is in Pacific Daylight Time (PDT), because in the US, the clocks are forwarded by an hour on March 12, 2023 to adjust for DST (Daylight Saving Time).
Create the outbound change set in the sandbox and add the above components to it. Send the change set to the production org. Login to production org and then deploy the inbound change set.
In this article, we presented a more robust solution that takes into consideration DST changes while computing the Datetime values on the ServiceAppointment records. We illustrated this concept by using the Scheduled Start and Scheduled End Datetime fields. You can extend this solution to other Datetime fields in the ServiceAppointment object if needed. Moreover, you can implement similar code for other Salesforce objects where you have a similar requirement to show Datetime values in different time zones.
Field Service (formerly known as Field Service Lightning) gives you a powerful, highly customizable, mobile-friendly field service hub in Salesforce. When Field Service is enabled, you gain access to a suite of standard objects that you can find in Setup and as tabs in Salesforce. These objects make up the core Field Service features, including work orders and service appointments.
Many of the Field Service objects have a lookup reference to either the Account or Contact object or in some instances, to both of them. As the Local Time App already supports time zones on Accounts and Contacts, one easy low-code option is to create formula fields on the Field Service objects to get the time zone information from the related Account or Contact records.
In this article, we will use the ServiceAppointment object as an example. The ServiceAppointment has lookup fields to both Account and Contact objects. We will use Account field in our example and you can easily extend this logic to Contact field if needed.
Moreover, the ServiceAppointment object has many Datetime fields such as SchedStartTime, SchedEndTime. The values for these fields are usually displayed in the Salesforce user’s time zone. However, the related Account record could be in a different time zone. Thus, in some instances, it will be useful to also show these Datetime field in the related record’s time zone.
For example, if you would like to show SchedStartTime (Label: Scheduled Start) value in the related Account time zone, you can do as follows:
IF(ISBLANK(Account.tz__UTC_Offset_F__c), "Unknown", MID( TEXT( SchedStartTime+ Account.tz__UTC_Offset_F__c /24 ), 6, 2 ) & "/" & MID( TEXT( SchedStartTime+ Account.tz__UTC_Offset_F__c /24 ), 9, 2 ) & "/" & LEFT( TEXT( SchedStartTime+ Account.tz__UTC_Offset_F__c /24 ), 4 ) & " " & TEXT( IF( OR( VALUE( MID( TEXT( SchedStartTime+ Account.tz__UTC_Offset_F__c /24 ), 12, 2 ) ) = 0, VALUE( MID( TEXT( SchedStartTime+ Account.tz__UTC_Offset_F__c /24 ), 12, 2 ) ) = 12 ), 12, VALUE( MID( TEXT( SchedStartTime+ Account.tz__UTC_Offset_F__c /24 ), 12, 2 ) ) - IF( VALUE( MID( TEXT( SchedStartTime+ Account.tz__UTC_Offset_F__c /24 ), 12, 2 ) ) < 12, 0, 12 ) ) ) &":"& MID( TEXT( SchedStartTime+ Account.tz__UTC_Offset_F__c /24 ), 15, 2 ) &" "& IF( VALUE( MID( TEXT( SchedStartTime+ Account.tz__UTC_Offset_F__c /24 ), 12, 2 ) ) < 12, "AM", "PM" ) & " " & Account.tz__Timezone_F__c )
In this article, we illustrated how you can leverage formula fields to easily surface time zone information on Salesforce Field Service objects. A limitation with this approach is that the time zone values obtained from the related record are “as of now” and thus this method does not account for any Daylight Saving Time (DST) changes in the future. Thus if your Scheduled Start value is in the future (crossing the DST), the formula still uses the current time zone and UTC Offset fields, instead of using the time zone and UTC Offset values that are relevant for the future date. As a consequence, the calculated Scheduled Start Date value could be potentially off by an hour.
In the next article: How to Show Time Zone Information on Salesforce Field Service Records? – Part 2, we will present a code based solution that overcomes this limitation.
The Local Time App for Salesforce has out-of-the-box support for getting the time zone information for Account, Contact, Lead, and Task standard Salesforce objects. We have now extended the App’s functionality to also support the Salesforce Event object.
When a user creates an Event in Salesforce, the Event Start and Event End Dates are displayed in the Salesforce user’s time zone. However, the related record (Lead, Contact, Account, Opportunity) of the Event could be in a different time zone. Thus, it will be useful to also have the Event Start and End dates in the related record’s time zone so that you can use this information, for instance, in your outbound communication (Example: meeting appointment email).
If you have a similar requirement, please read the rest of this article to understand how you can fulfil the requirement.
It is assumed that you have installed Local Time App version v2.25 or later in your sandbox and production environments. You can install the latest version of the App from this link.
From Setup -> Object Manager, select the Activity object and create the following fields.
Label | API Name | Data Type | Comments |
---|---|---|---|
Event Start Date | Event_Start_Date__c | Text(20) | Event start date in the related record time zone. |
Event End Date | Event_End_Date__c | Text(20) | Event end date in the related record time zone. |
Timezone * | tz__Timezone__c | Text(10) | Event Start Date timezone abbreviation (PST, EST, etc.) for the related record (Lead, Contact etc.). |
Event End Timezone | Event_End_Timezone__c | Text(10) | Event End Date timezone abbreviation (PST, EST, etc.) for the related record (Lead, Contact etc.) |
UTC Offset * | tz__UTC_Offset__c | Number(3, 2) | Event Start Date UTC timezone offset for the related record (Lead, Contact etc.). |
Event End UTC Offset | Event_End_UTC_Offset__c | Number(3, 2) | Event End Date UTC timezone offset for the related record (Lead, Contact etc.) |
Timezone IANA | Timezone_IANA__c | Text(35) | Timezone as defined by IANA. Example: America/New_York |
* In the example, we are re-using two fields that are already included in the App. However, if you prefer, you can also create your own custom fields (for example: Event Start Timezone and Event Start UTC Offset).
From Local Time Config tab -> Settings subtab, configure the Event object to use the fields created in Step 1.
From Local Time Config tab -> Settings subtab, enable the triggers on the Event object and click the Save button to update the App settings.
Assume that your time zone in Salesforce is US Eastern (America/New_York). The related record on the Event is a lead and it is in US Pacific (America/Los_Angeles) time zone.
You created an event at 1 PM EST on December 01, 2022 lasting for an hour. After the event is saved, you can see that the Event Start Date, Event End Date, and other custom fields created in Step 1 show the event details in the related record’s time zone.
Assume that your time zone in Salesforce is US Eastern (America/New_York). The related record on the Event is a lead and it is in US Pacific (America/Los_Angeles) time zone.
You created a two-day event starting at 1 PM EST on March 11, 2022. After the event is saved, you can see that the Event Start Date, Event End Date, and other custom fields show the event details in the related record’s time zone.
Note that the Event End Date is in PDT (Pacific Daylight Time) because in the US the clocks will be forwarded by an hour on March 12, 2023 to adjust for DST (Daylight Saving Time).