-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Closed
Description
Description
In the string produced by string.Format()
using either the short time pattern "t" or long time pattern "T" in en-US (CultureInfo.GetCultureInfo("en-US")
), the regular space between the numeric portion of the time and AM/PM portion changed from a regular space (\u0020
) to a non-breaking space (\u202f
). This breaks any existing code expecting a regular space.
Reproduction Steps
xUnit test demonstrating issue:
using System.Globalization;
using Xunit.Abstractions;
namespace SpaceInTimeTests;
public class UnitTest1
{
private readonly ITestOutputHelper _testOutputHelper;
public UnitTest1(ITestOutputHelper testOutputHelper)
{
_testOutputHelper = testOutputHelper;
}
[Theory]
[InlineData("2009-06-15T13:45:30", "en-US", "t", "1:45 PM")]
[InlineData("2009-06-15T13:45:30", "hr-HR", "t", "13:45")]
[InlineData("2009-06-15T13:45:30", "en-US", "T", "1:45:30 PM")]
[InlineData("2009-06-15T13:45:30", "hr-HR", "T", "13:45:30")]
public void Test1(string timestamp, string locale, string formatStyle, string expected)
{
if (!DateTimeOffset.TryParse(timestamp, out var dateTime))
{
throw new ArgumentException("Failed to parse {0}", timestamp);
}
var actual = string.Format(CultureInfo.GetCultureInfo(locale), $"{{0:{formatStyle}}}", dateTime);
_testOutputHelper.WriteLine("EXPECTED '{0}' => {1}", expected, string.Join('|', expected.ToCharArray().Select(x => $"0x{(int)x:x4}")));
_testOutputHelper.WriteLine("ACTUAL '{0}' => {1}", actual, string.Join('|', actual.ToCharArray().Select(x => $"0x{(int)x:x4}")));
Assert.Equal(expected, actual);
}
}
Cases using the "en-US" locale fail with the following error:
Assert.Equal() Failure: Strings differ
↓ (pos 7)
Expected: "1:45:30 PM"
Actual: "1:45:30 PM"
↑ (pos 7)
at SpaceInTimeTests.UnitTest1.Test1(String timestamp, String locale, String formatStyle, String expected) in /Users/chetan/projects/SpaceInTimeTests/UnitTest1.cs:line 30
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span`1 copyOfArgs, BindingFlags invokeAttr)
EXPECTED '1:45:30 PM' => 0x0031|0x003a|0x0034|0x0035|0x003a|0x0033|0x0030|0x0020|0x0050|0x004d
ACTUAL '1:45:30 PM' => 0x0031|0x003a|0x0034|0x0035|0x003a|0x0033|0x0030|0x202f|0x0050|0x004d
Expected behavior
Regular spaces (\u0020
) between numeric and AM/PM portions of the timestamp. (see "expected" from the output in "Reproduction Steps").
Actual behavior
See "Actual" output in "Reproduction Steps"
Regression?
Yes, it worked prior to 8.0.204. I'm seeing this happening in 8.0.204 and 8.0.300.
Known Workarounds
Disabling unit tests
Configuration
- .NET version: 8.0.300 (and 8.0.204)
- OS: MacOS 14.4 (Sonoma) (ARM64), Linux Ubuntu 20.04 (x64), whatever OS linux .NET ASP.Net containers use (x64)
Other information
No response