Skip to content

Class Name: LocalTimeConverter

Last Updated: 2025-10-22 Source Code: https://github.com/AANP-IT/I2C.Salesforce.Metadata/blob/STAGING/force-app/main/default/classes/LocalTimeConverter.cls

API Name: LocalTimeConverter Type: Invocable Method (Flow Utility) Test Coverage: LocalTimeConverterTest.cls Author: Unknown Created: Unknown

Business Purpose

This utility class provides timezone conversion capabilities for Salesforce Flow and Process Builder, enabling datetime values to be displayed in users' local timezones. It supports member-facing processes that need to show meeting times, event schedules, appointment slots, or any time-sensitive information in the appropriate local time for members across different geographical regions. This improves user experience and reduces timezone-related confusion in communications and scheduling.

Class Overview

Scope and Sharing

  • Sharing Model: with sharing (respects record-level security)
  • Access Modifier: public
  • Interfaces Implemented: None (uses @InvocableMethod)

Key Responsibilities

  • Convert UTC datetime values to specific local timezones
  • Support bulk conversion of multiple datetime values
  • Integrate with Salesforce Flow and Process Builder
  • Handle errors gracefully with fallback behavior
  • Format datetime values consistently
  • Support any valid timezone SID key

Inner Classes

TimeConversionInput

public class TimeConversionInput {
    @InvocableVariable
    public Datetime utcDatetime;

    @InvocableVariable
    public String timeZoneSidKey;
}

Purpose: Input parameter wrapper for invocable method.

Fields: - utcDatetime: UTC datetime to convert - timeZoneSidKey: Target timezone (e.g., 'America/New_York', 'America/Los_Angeles', 'Europe/London')


TimeConversionOutput

public class TimeConversionOutput {
    @InvocableVariable
    public Datetime localDatetimeFormatted;
}

Purpose: Output parameter wrapper for invocable method.

Fields: - localDatetimeFormatted: Converted datetime in local timezone


Public Methods

convertDatetimeToLocal

@InvocableMethod(label='Convert UTC Datetime to Local Time')
public static List<TimeConversionOutput> convertDatetimeToLocal(List<TimeConversionInput> inputs)

Purpose: Invocable method that converts UTC datetime values to specified local timezones for use in Salesforce Flow.

Parameters: - inputs (List): List of datetime/timezone pairs to convert

Returns: - List<TimeConversionOutput>: List of converted local datetime values

Throws: - Catches all exceptions internally (does not propagate)

Usage Example in Flow:

Element: Action - Apex
Action Type: Invocable Apex
Action: Convert UTC Datetime to Local Time
Input Variables:
  - utcDatetime: {!MeetingDateTime}
  - timeZoneSidKey: {!UserTimeZone}
Output Variable: {!LocalMeetingTime}

Business Logic:

  1. Initialize Results:

    List<TimeConversionOutput> results = new List<TimeConversionOutput>();
    

  2. Process Each Input:

    for (TimeConversionInput input : inputs) {
        TimeConversionOutput output = new TimeConversionOutput();
    

  3. Validate Inputs:

    if (input.utcDatetime != null && String.isNotBlank(input.timeZoneSidKey)) {
    

  4. Checks datetime not null
  5. Checks timezone key not blank

  6. Format with Timezone:

    String formatted = input.utcDatetime.format(
        'yyyy-MM-dd HH:mm:ss',
        input.timeZoneSidKey
    );
    

  7. Formats UTC datetime using specified timezone
  8. Uses 'yyyy-MM-dd HH:mm:ss' pattern

  9. Convert Back to Datetime:

    output.localDatetimeFormatted = Datetime.valueOf(formatted);
    

  10. Converts formatted string back to Datetime object
  11. Required for Flow compatibility

  12. Handle Invalid Inputs:

    } else {
        output.localDatetimeFormatted = DateTime.now();
    }
    

  13. Uses current time as fallback

  14. Error Handling:

    } catch (Exception e) {
        System.debug(e.getMessage());
        System.debug(e.getStackTraceString());
        output.localDatetimeFormatted = DateTime.now();
        results.add(output);
        return results;  // ⚠️ BUG: Early return skips remaining inputs
    }
    

  15. CRITICAL BUG: Returns immediately on first exception
  16. Prevents processing of remaining inputs in list

  17. Add to Results:

    results.add(output);
    

Timezone SID Key Examples: - America/New_York - Eastern Time - America/Los_Angeles - Pacific Time - America/Chicago - Central Time - Europe/London - GMT/BST - Asia/Tokyo - Japan Standard Time - Australia/Sydney - Australian Eastern Time

Format Pattern: - Pattern: yyyy-MM-dd HH:mm:ss - Example: 2025-10-22 14:30:00 - 24-hour format - No timezone indicator in output


Private/Helper Methods

None - All logic in single invocable method


Dependencies

Apex Classes

  • None - Standalone utility class
  • Called by: Salesforce Flows and Process Builder

Salesforce Objects

  • None - Pure datetime conversion utility

Custom Settings/Metadata

  • None - Uses standard Salesforce timezone functionality

External Services

  • None - Internal Salesforce processing only

Design Patterns

  • Utility Pattern: Static method for stateless conversion
  • DTO Pattern: Input/Output wrapper classes for Flow integration
  • Bulk Pattern: Processes list of conversions
  • Fail-Safe Pattern: Fallback to DateTime.now() on errors

Why These Patterns: - Utility pattern appropriate for stateless operations - DTO pattern required for invocable methods - Bulk pattern enables efficient Flow processing - Fail-safe prevents Flow errors from blocking execution

Governor Limits Considerations

SOQL Queries: 0 DML Operations: 0 CPU Time: Low (datetime formatting only) Heap Size: Minimal (small objects)

Bulkification: Yes - processes list of inputs Async Processing: No (synchronous for Flow)

Governor Limit Risks: - NONE: No queries or DML - LOW: CPU time minimal for datetime conversion - LOW: Called from Flow (may have many invocations)

Performance Considerations: - Very lightweight operation - Datetime.format() is fast - No external dependencies

Recommendations: - Current implementation efficient - No optimization needed

Error Handling

Strategy: Try-catch with fallback to DateTime.now()

Logging: - System.debug for exception message and stack trace - Debug logs may not be visible in production - No persistent logging

User Notifications: - None - Silent fallback to current time - Flow users don't see conversion failures - Could lead to incorrect times being used

Fallback Behavior: - Invalid inputs: Uses DateTime.now() - Exceptions: Uses DateTime.now() - CRITICAL BUG: Early return on exception skips remaining conversions

Bug Impact:

// If converting 5 datetimes and #3 fails:
Input 1: Converted successfully
Input 2: Converted successfully
Input 3: Exception → returns [Input1, Input2, Input3_with_current_time]
Input 4: SKIPPED ❌
Input 5: SKIPPED ❌

Recommended Improvements: - Remove return results; from catch block - Continue processing remaining inputs after exception - Log failures to custom object for troubleshooting - Return error details to Flow for conditional logic - Validate timezone SID before conversion

Fixed Code:

} catch (Exception e) {
    System.debug(e.getMessage());
    System.debug(e.getStackTraceString());
    output.localDatetimeFormatted = DateTime.now();
    // Remove this line: return results;
}
results.add(output); // Move outside try-catch

Security Considerations

Sharing Rules: RESPECTED - Uses 'with sharing' - Appropriate for utility class

Field-Level Security: N/A - No field access

CRUD Permissions: N/A - No database operations

Input Validation: MINIMAL - Checks for null/blank inputs - No validation of timezone SID format - Trusts Flow-provided values

Security Risks: - LOW: No data access or modification - LOW: Invalid timezone SID causes exception (handled) - NONE: No security implications

Mitigation Recommendations: - Current security appropriate for utility class - Consider validating timezone SID against known list

Test Class

Test Class: LocalTimeConverterTest.cls Coverage: To be determined

Test Scenarios That Should Be Covered: - ✓ Valid UTC datetime and timezone conversion - ✓ Multiple timezone conversions (PST, EST, GMT, etc.) - ✓ Null utcDatetime input (should use DateTime.now()) - ✓ Blank timeZoneSidKey input (should use DateTime.now()) - ✓ Invalid timezone SID (should handle exception) - ✓ Bulk conversion (multiple inputs) - ✓ BUG TEST: Exception on middle input (should process all inputs, not just return early) - ✓ Daylight Saving Time transitions - ✓ Date boundary crossings (e.g., midnight conversions) - ✓ Future and past dates - ✓ Extreme timezone offsets (e.g., UTC+14, UTC-12)

Testing Challenges: - Difficult to test invalid timezone SIDs - DST transitions require specific test dates - Bug testing requires forcing exception

Test Data Requirements: - Various UTC datetimes - Multiple timezone SID keys - Test dates during DST transitions

Changes & History

  • Created: Unknown (check git history)
  • Author: Unknown
  • Purpose: Timezone conversion for Flow
  • Related to: Member portal, scheduling features

⚠️ Pre-Go-Live Concerns

CRITICAL - Fix Before Go-Live

  • EARLY RETURN BUG: Line 40 returns immediately on exception, preventing processing of remaining inputs in bulk operation. This breaks bulk processing! Remove return results; from catch block.
  • Silent Failures: Conversions that fail use DateTime.now() with no indication to Flow. Could result in incorrect times being used in communications.
  • No Validation: Invalid timezone SIDs cause exceptions. Should validate against known timezone list before attempting conversion.

HIGH - Address Soon After Go-Live

  • No Logging: Debug statements won't be visible in production. Impossible to troubleshoot conversion failures.
  • DateTime.now() Fallback Misleading: Using current time on failure could confuse users. Consider returning null or specific error indicator.
  • Format Hardcoded: 'yyyy-MM-dd HH:mm:ss' pattern hardcoded. Different use cases may need different formats.

MEDIUM - Future Enhancement

  • Limited Error Information: Flow cannot detect conversion failures. Add status output variable.
  • No Timezone Validation: Should validate timezone SID exists before attempting conversion.
  • Performance with Large Lists: Not optimized for very large bulk operations (though unlikely to be an issue).
  • No Configuration: Format pattern should be configurable via custom metadata.

LOW - Monitor

  • Invocable Method Limits: Flow can call invocables max 2000 times per transaction. Monitor for hitting limits.
  • Test Coverage: Ensure comprehensive test coverage for all scenarios including the bug.
  • Documentation: Add usage examples in Flow for developers.

Maintenance Notes

Complexity: Low (simple utility function) Recommended Review Schedule: Annually (stable functionality)

Key Maintainer Notes:

🐛 CRITICAL BUG: - Line 40: return results; in catch block causes early return - This breaks bulk processing - only first exception is handled, rest are skipped - FIX IMMEDIATELY before production use - Simple fix: Remove the return results; line from catch block

📋 Usage Patterns: - Called from Salesforce Flows - Used for member-facing datetime displays - Common in appointment scheduling flows - Used in email templates via Flow - Typically processes 1-10 datetimes per invocation

🧪 Testing Requirements: - Test with various timezones (PST, EST, GMT, JST, etc.) - Test DST transitions (March and November) - Test bulk operations (list of 5+ conversions) - Test the bug: Verify fix by forcing exception in middle of list - Test invalid timezone SIDs - Test null/blank inputs

🔧 Timezone Configuration: - Uses standard Salesforce timezone SID keys - Full list: Setup → Time Zones - Common values: - America/New_York (EST/EDT) - America/Los_Angeles (PST/PDT) - America/Chicago (CST/CDT) - Europe/London (GMT/BST) - Asia/Tokyo (JST)

⚠️ Gotchas and Warnings: - CRITICAL BUG: Early return in catch block - Fallback to DateTime.now() could be confusing - Timezone SID is case-sensitive - DST transitions handled automatically by Salesforce - Format pattern doesn't include timezone indicator - Invalid timezone SID throws exception (silently caught)

📅 When to Review This Class: - IMMEDIATELY: Fix the early return bug - When adding new timezone requirements - If Flow conversion failures increase - During DST transition periods (March/November) - When implementing new scheduling features

🛑 Emergency Workaround:

If conversions are failing in production:

// In Flow, add error handling:
1. Decision element after conversion
2. Check if result equals DateTime.now()
3. If yes, may indicate failed conversion
4. Provide fallback logic or error message

🔍 Debugging Tips: - Enable debug logs for Flow execution - Check debug logs for exception messages - Verify timezone SID key is correct - Test timezone SID in Execute Anonymous:

Datetime.now().format('yyyy-MM-dd HH:mm:ss', 'America/New_York');
- Check Flow interview for input values

📊 Monitoring Checklist: - Weekly: Review any timezone-related user complaints - Monthly: Check debug logs for exceptions - Quarterly: Verify timezone SIDs still valid - Before/after DST: Test conversions work correctly - Alert: Increase in Flow failures related to this action

🔗 Related Components: - Flows: Uses this method for timezone conversion - User object: TimeZoneSidKey field - Email templates: May use converted times - Scheduling LWCs: May call Flow using this method

Business Owner

Primary: IT / Development Team Secondary: Member Experience / Scheduling Team Stakeholders: Customer Service, Operations, Development Team