diff --git a/Jint/Native/Intl/IntlUtilities.cs b/Jint/Native/Intl/IntlUtilities.cs
index 618186cc70..81218970e8 100644
--- a/Jint/Native/Intl/IntlUtilities.cs
+++ b/Jint/Native/Intl/IntlUtilities.cs
@@ -1638,7 +1638,8 @@ private static string RemoveUnicodeExtensions(string locale)
// Use new CultureInfo() instead of GetCultureInfo() to get correct locale-specific
// data. GetCultureInfo returns a cached read-only culture that may have different
// NumberFormatInfo patterns (e.g., CurrencyNegativePattern).
- return new CultureInfo(cultureTag);
+ // useUserOverride: false ensures consistent behavior regardless of Windows regional settings.
+ return new CultureInfo(cultureTag, false);
}
catch (CultureNotFoundException)
{
diff --git a/Jint/Native/Intl/JsDateTimeFormat.cs b/Jint/Native/Intl/JsDateTimeFormat.cs
index 24481fbf97..4914b9f407 100644
--- a/Jint/Native/Intl/JsDateTimeFormat.cs
+++ b/Jint/Native/Intl/JsDateTimeFormat.cs
@@ -465,58 +465,48 @@ public LocaleDateFormatInfo(string dateOrder, string dateSeparator, bool hasText
}
///
- /// Determines the locale-specific date format order and separator.
+ /// Determines the locale-specific date format order and separator
+ /// by parsing the ShortDatePattern from DateTimeFormatInfo.
///
private LocaleDateFormatInfo GetLocaleDateFormat()
{
- // Check if month is textual (long, short, narrow) vs numeric
var hasTextualMonth = Month != null && Month is "long" or "short" or "narrow";
- // Get locale's short date pattern to determine order
- var lang = Locale.Split('-')[0].ToLowerInvariant();
- var region = Locale.Contains('-') ? Locale.Split('-')[1].ToUpperInvariant() : "";
+ // Derive date order and separator from the locale's ShortDatePattern (e.g., "dd-MM-yyyy", "M/d/yyyy")
+ var pattern = CultureInfo.DateTimeFormat.ShortDatePattern;
+ var dateOrder = ParseDateOrder(pattern);
+ var dateSeparator = hasTextualMonth ? " " : CultureInfo.DateTimeFormat.DateSeparator;
- // Determine date component order based on locale
- // MDY: en-US, en-CA (Canada uses MDY in English), fil (Philippines)
- // DMY: Most of Europe, UK, Australia, most of world
- // YMD: East Asia (China, Japan, Korea), Lithuania, Hungary
- string dateOrder;
- if (string.Equals(lang, "en", StringComparison.Ordinal) &&
- (string.Equals(region, "US", StringComparison.Ordinal) ||
- string.Equals(region, "", StringComparison.Ordinal)))
- {
- // en-US and plain "en" use MDY
- dateOrder = "Mdy";
- }
- else if (string.Equals(lang, "zh", StringComparison.Ordinal) ||
- string.Equals(lang, "ja", StringComparison.Ordinal) ||
- string.Equals(lang, "ko", StringComparison.Ordinal) ||
- string.Equals(lang, "hu", StringComparison.Ordinal) ||
- string.Equals(lang, "lt", StringComparison.Ordinal))
- {
- // East Asian languages and Hungarian/Lithuanian use YMD
- dateOrder = "yMd";
- }
- else
- {
- // Most of the world uses DMY
- dateOrder = "dMy";
- }
+ return new LocaleDateFormatInfo(dateOrder, dateSeparator, hasTextualMonth);
+ }
- // Determine separator based on whether month is textual
- string dateSeparator;
- if (hasTextualMonth)
- {
- // Textual month uses space separators: "Jan 3, 2019"
- dateSeparator = " ";
- }
- else
+ ///
+ /// Parses a .NET ShortDatePattern to extract the date component order (e.g., "dMy", "Mdy", "yMd").
+ ///
+ private static string ParseDateOrder(string pattern)
+ {
+ var order = new StringBuilder(3);
+ foreach (var c in pattern)
{
- // Numeric format uses "/" for en-US, varies by locale
- dateSeparator = "/";
+ var component = char.ToLowerInvariant(c) switch
+ {
+ 'd' => 'd',
+ 'm' => 'M',
+ 'y' => 'y',
+ _ => '\0'
+ };
+
+ if (component != '\0' && (order.Length == 0 || order[order.Length - 1] != component))
+ {
+ order.Append(component);
+ if (order.Length == 3)
+ {
+ break;
+ }
+ }
}
- return new LocaleDateFormatInfo(dateOrder, dateSeparator, hasTextualMonth);
+ return order.Length == 3 ? order.ToString() : "dMy"; // fallback to DMY
}
private void AddMonthPart(DateTime dateTime, List result, ref bool hasDate, string separator, bool hasTextualMonth, ChineseCalendarHelper.ChineseCalendarDate? lunisolarDate = null)
@@ -1198,9 +1188,11 @@ private string BuildFormatString(List parts)
}
else
{
- // Numeric format: "1/3/2019"
- // Use literal '/' by escaping with single quotes to avoid .NET's culture-specific date separator
- result.Append("'/'");
+ // Numeric format: use locale-specific date separator
+ var sep = CultureInfo.DateTimeFormat.DateSeparator;
+ result.Append('\'');
+ result.Append(sep);
+ result.Append('\'');
}
}
}