Skip to content

[iOS/HybridGlobalization] Force short date pattern to use yyyy #99515

@tipa

Description

@tipa

Description

When using HybridGlobalization on iOS, the shortdate format does only contain just either one or two y's, which result in only a two-digit year when formatting dates.

Reproduction Steps

Set <HybridGlobalization>true</HybridGlobalization> in iOS csproj file and format some date with "short date" format (e.g. DateTime.Now.ToString("d"))

Expected behavior

new CultureInfo("de-DE").DateTimeFormat.ShortDatePattern == "dd.MM.yyyy"
new CultureInfo("en-US").DateTimeFormat.ShortDatePattern == "M/d/yyyy"
new CultureInfo("fa-IR").DateTimeFormat.ShortDatePattern == "yyyy/M/d"

Actual behavior

new CultureInfo("de-DE").DateTimeFormat.ShortDatePattern == "dd.MM.yy"
new CultureInfo("en-US").DateTimeFormat.ShortDatePattern == "M/d/yy"
new CultureInfo("fa-IR").DateTimeFormat.ShortDatePattern == "y/M/d"

Regression?

No response

Known Workarounds

No response

Configuration

.NET 8

Other information

A similar problem was reported a while back for Linux here and fixed here. To code is still in the repo:

// FixDefaultShortDatePattern will convert the default short date pattern from using 'yy' to using 'yyyy'
// And will ensure the original pattern still exist in the list.
// doing that will have the short date pattern format the year as 4-digit number and not just 2-digit number.
// Example: June 5, 2018 will be formatted to something like 6/5/2018 instead of 6/5/18 fro en-US culture.
private static void FixDefaultShortDatePattern(List<string> shortDatePatterns)
{
if (shortDatePatterns.Count == 0)
return;
string s = shortDatePatterns[0];
// We are not expecting any pattern have length more than 100.
// We have to do this check to prevent stack overflow as we allocate the buffer on the stack.
if (s.Length > 100)
return;
Span<char> modifiedPattern = stackalloc char[s.Length + 2];
int index = 0;
while (index < s.Length)
{
if (s[index] == '\'')
{
do
{
modifiedPattern[index] = s[index];
index++;
} while (index < s.Length && s[index] != '\'');
if (index >= s.Length)
return;
}
else if (s[index] == 'y')
{
modifiedPattern[index] = 'y';
break;
}
modifiedPattern[index] = s[index];
index++;
}
if (index >= s.Length - 1 || s[index + 1] != 'y')
{
// not a 'yy' pattern
return;
}
if (index + 2 < s.Length && s[index + 2] == 'y')
{
// we have 'yyy' then nothing to do
return;
}
// we are sure now we have 'yy' pattern
Debug.Assert(index + 3 < modifiedPattern.Length);
modifiedPattern[index + 1] = 'y'; // second y
modifiedPattern[index + 2] = 'y'; // third y
modifiedPattern[index + 3] = 'y'; // fourth y
index += 2;
// Now, copy the rest of the pattern to the destination buffer
while (index < s.Length)
{
modifiedPattern[index + 2] = s[index];
index++;
}
shortDatePatterns[0] = modifiedPattern.ToString();
for (int i = 1; i < shortDatePatterns.Count; i++)
{
if (shortDatePatterns[i] == shortDatePatterns[0])
{
// Found match in the list to the new constructed pattern, then replace it with the original modified pattern
shortDatePatterns[i] = s;
return;
}
}
// if we come here means the newly constructed pattern not found on the list, then add the original pattern
shortDatePatterns.Add(s);
}

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions