From JDK to ICU Locale Formats: Adapting Salesforce Applications for the Next Generation of Formatting

Salesforce is significantly changing its underlying date, time, and number formatting engines. With the Summer ’25 release, Salesforce will move from JDK (Java Development Kit) formatting to ICU (International Components for Unicode) formatting. While this might seem like a minor internal tweak, it can have wide-reaching implications on how your org’s custom logic, UI components, and integrations display and interpret locale-sensitive information.

In this post, we’ll explore:

  • The key differences between JDK and ICU formatting
  • The potential impact on ISV (Independent Software Vendor) applications
  • Concrete examples of how to adapt and migrate your code—ranging from Apex and Lightning Web Components (LWC) to triggers and Flows

Why the Change?

ICU is an industry-standard library for internationalization. It provides more accurate, consistent, and up-to-date locale data and formatting patterns across languages, countries, and regions. By standardizing on ICU, Salesforce ensures that:

  • You have access to the latest and most consistent localization standards.
  • Formatting is more reliable across all Salesforce-supported locales.
  • You can more easily manage future internationalization needs as your business and customer base expand.

Key Differences Between JDK and ICU Formatting

1. Pattern Syntax for Dates/Times

While both JDK (java.text.SimpleDateFormat) and ICU (java.text.DateFormatSymbols, UDateFormat) use similar concept patterns, there are subtle but important differences:

  • Era (G): JDK uses “G” for era, while ICU also uses “G” but may interpret multiple letters differently. For instance, “GGGG” in ICU is a full era name, while “G” is the abbreviated era.
  • Year (y): Generally similar, but ICU’s locale data might cause differences in how certain locale-specific years are displayed.
  • Month (M/L): In JDK, “M” is the month in context. ICU uses “M” for month numbers and “L” for stand-alone month names. For example, “MMMM” typically gives the full month name in both, but ICU’s handling of stand-alone vs. format (context-sensitive) month names can differ depending on locale.
  • Day (d): Largely the same, but ICU’s underlying locale data can yield small differences in formatting for certain regions.
  • Weekday (E): Similar usage, but again, ICU may provide different abbreviations or full names based on the most current Unicode CLDR (Common Locale Data Repository).

Example:

  • JDK Date Pattern: "EEEE, MMMM d, yyyy" might produce "Thursday, October 12, 2023".
  • ICU Date Pattern: The same pattern might still produce "Thursday, October 12, 2023", but in some locales, ICU may choose a different preferred abbreviation or translation based on the latest CLDR data 
For example, for "EEE, MMM d, yyyy" pattern in French (fr-FR) locale:
  • JDK-Based Formatting might produce: "jeu., oct. 12, 2023"
  • ICU-Based Formatting might produce: "jeu. 12 oct. 2023"

Notice that the order and spacing could differ slightly, and ICU might adhere to the latest CLDR data that prefers a certain word order or spacing convention. For instance, the day number may come directly after the abbreviated weekday, and the year might no longer have a comma before it if the CLDR data considers it unnecessary.

In other locales, you might see capitalization differences, spacing changes, or updated abbreviations for months and weekdays. While the overall meaning remains the same, these adjustments ensure that the formatting follows the most current and culturally appropriate standards for that language and region.

2. Number, Currency, and Percentage Formats

ICU relies on more frequently updated locale data. Thus, currency symbols, decimal separators, grouping separators, and the style of percentage formats may differ slightly (though generally more correct from a localization standpoint).

3. Time Zone Names and Adjustments

ICU periodically updates time zone names and rules according to the latest standards. While JDK might lag behind in certain releases, ICU ensures that your displayed time zones are more accurate and consistent.

Impact on ISVs

ISVs who have built packaged solutions that rely on specific date/time/number formatting patterns must re-validate their logic and UIs:

  • Visual Consistency: If your app shows date fields in a custom UI, the labels might now differ in subtle ways. For example, the French locale might show abbreviations differently.
  • Parsing and Validation: If you rely on pattern-based parsing of user input (e.g., in a custom Apex controller that parses date strings from user input), you must ensure the patterns are compatible and yield the same results under ICU.
  • Contracts and Documentation: If your product documentation or contracts with clients specify certain date formats, you’ll need to confirm that the output aligns with those guarantees after the switch to ICU.

ISVs should allocate time for testing and validating these changes well before Summer ’25. Consider creating a test environment that simulates ICU formatting and verifying that your reports, dashboards, LWC components, and Apex logic work as expected.

Examples: Adapting Your Code

Apex Example: Using ICU Formatting Patterns

Previously, you might have used DateTime.format() or String.format() with JDK patterns. Going forward, the same code should continue to work, but if you’ve hard-coded certain patterns, verify they produce the desired result under ICU.

// Before (JDK-like pattern)
String jdkFormat = Datetime.now().format('EEEE, MMMM d, yyyy', 'en_US');
// e.g. "Thursday, October 12, 2023"

// After (ICU patterns are effectively the same for this example)
String icuFormat = Datetime.now().format('EEEE, MMMM d, yyyy', 'en_US');
// Expect very similar output, but verify locale differences

If you need more control, consider using System.Locale and newer ICU-compatible methods from Salesforce’s localization services (once Salesforce has documented them in the release notes).

LWC (Lightning Web Components) Example

If you’re using JavaScript’s Intl API (which is ICU-based under the hood), you’re likely already aligned with the ICU approach. Just confirm that your formatting strings are correct and do not rely on outdated assumptions.

// LWC JS Controller
const date = new Date();
const options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
const formattedDate = new Intl.DateTimeFormat('en-US', options).format(date);
// ICU-based Intl APIs handle locale formatting automatically.
// Check outputs for subtle differences in abbreviations or month names.

Trigger Example

Triggers themselves rarely do formatting - usually, they handle backend logic. However, if your trigger uses formatted date strings for some reason (e.g., integrating with a legacy system via callouts), ensure the pattern remains valid:

trigger OpportunityDateHandler on Opportunity (before insert) {
    for (Opportunity opp : Trigger.new) {
        // Just as an example of date formatting
        opp.Description = Datetime.now().format('yyyy-MM-dd HH:mm:ss', UserInfo.getLocale());
        // Ensure this pattern yields the same style under ICU.
    }
}

Salesforce Flow Example

In Flow, you might use formulas or display formatted date/time strings in Screens. Flow date/time formatting will align with ICU automatically after the transition. You’ll want to review any custom date/time display formats (such as screen text or custom labels) and verify the rendered result in preview mode.

For instance, if you have a Display Text element showing {!$Flow.CurrentDateTime} in a specific format, test it in a sandbox once ICU is available. If the format is controlled by the Flow’s locale settings, the result may show slight differences.

Best Practices for a Smooth Transition

  1. Test Early and Often:
    Spin up a sandbox with the new ICU formatting enabled (when available in pre-release orgs or after enabling the pilot setting as Salesforce offers it). Compare the results of your existing patterns and logic side-by-side.

  2. Audit Hard-Coded Patterns:
    Scan your codebase for hard-coded date/time patterns. Most patterns are still supported, but some may require adjustments. Document these patterns now so you can quickly validate them later.

  3. Leverage Built-in Formatting Tools:
    Instead of hard-coding patterns, consider relying on Salesforce’s built-in formatting utilities, fields, or the Intl API in LWC. These are less likely to break during global changes, as they’re maintained and tested by Salesforce and the standards community.

  4. Update Documentation and Training Materials:
    If your end-users or customers are accustomed to certain date/time formats, prepare them for potential minor shifts. Update your product help documentation or internal training materials as needed.

Conclusion

The enforced change to ICU formatting in Summer ’25 is part of Salesforce’s ongoing efforts to provide a more accurate, current, and globally consistent platform. While the majority of patterns and formatting logic should remain similar, now is the time to verify, adjust, and future-proof your code and user interfaces.

By planning ahead, testing thoroughly, and understanding the differences between JDK and ICU formats, you’ll ensure a seamless experience for both your internal teams and your end-users - no matter where in the world they do business.

Comments

Popular posts from this blog

Building Stronger Relationships with Stakeholder Management in Nonprofit Cloud

Should I Migrate from NPSP to Nonprofit Cloud? A Strategic Decision for Your Mission