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¶
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
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:
-
Initialize Results:
-
Process Each Input:
-
Validate Inputs:
- Checks datetime not null
-
Checks timezone key not blank
-
Format with Timezone:
- Formats UTC datetime using specified timezone
-
Uses 'yyyy-MM-dd HH:mm:ss' pattern
-
Convert Back to Datetime:
- Converts formatted string back to Datetime object
-
Required for Flow compatibility
-
Handle Invalid Inputs:
-
Uses current time as fallback
-
Error Handling:
- CRITICAL BUG: Returns immediately on first exception
-
Prevents processing of remaining inputs in list
-
Add to Results:
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:
- 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