Skip to content

[Breaking change]: FindSystemTimeZoneById Returns Incorrect StandardName for Id #41830

Closed
@jchli

Description

@jchli

Description

It looks like the TimeZoneInfo object that is returned from FindSystemTimeZoneById() is returning an incorrect name for a given ID (It gives the correct offset but with "GMT"). Further, it seems to only be a problem for IDs that are shaped like "Eastern Standard Time". In contrast, "America/New_York" works fine.

I suspect that this has something to do with the caching behavior introduced in .NET 8. Take a look at the unit test below, which will fail in different ways depending on the test cases provided

Unit test to reproduce behavior:

public class TimeZoneHelperTests
{
    [Theory]
    [InlineData("Eastern Standard Time", false, "EST")] // fully qualified IDs fail sometimes
    [InlineData("Central Standard Time", false, "CST")]
    [InlineData("Mountain Standard Time", false, "MST")]
    [InlineData("Pacific Standard Time", false, "PST")]
    [InlineData("Eastern Standard Time", true, "EDT")]
    [InlineData("Central Standard Time", true, "CDT")]
    [InlineData("Mountain Standard Time", true, "MDT")]
    [InlineData("Pacific Standard Time", true, "PDT")]
    [InlineData("America/New_York", false, "EST")] //America/X type IDs always succeed
    [InlineData("America/Chicago", false, "CST")]
    [InlineData("America/Denver", false, "MST")]
    [InlineData("America/Los_Angeles", false, "PST")]
    [InlineData("America/New_York", true, "EDT")]
    [InlineData("America/Chicago", true, "CDT")]
    [InlineData("America/Denver", true, "MDT")]
    [InlineData("America/Los_Angeles", true, "PDT")]
    public void GetTzAbbreviation_BuildsCorrectAbbreviation(string timeZoneId, bool isDaylightSavingsTime, string expectedAbbreviation)
    {
        // Arrange
        var tzi = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
        
        // Act
        var abbreviation = GetTzAbbreviation(isDaylightSavingsTime, tzi);

        // Assert
        Assert.Equal(expectedAbbreviation, abbreviation);
    }
    
    private static string GetTzAbbreviation(bool isDaylightSavingsTime, TimeZoneInfo timeZoneInfo)
    {
        var timeZoneString = isDaylightSavingsTime ? timeZoneInfo.DaylightName : timeZoneInfo.StandardName;
            
        return string.Concat(Regex
            .Matches(timeZoneString, "[A-Z]")
            .Select(match => match.Value));
    }
}

Version

.NET 8 GA

Previous behavior

The standard name should be analogous the provided time zone.

New behavior

The standard name is set to GMT

Type of breaking change

  • Binary incompatible: Existing binaries might encounter a breaking change in behavior, such as failure to load or execute, and if so, require recompilation.
  • Source incompatible: When recompiled using the new SDK or component or to target the new runtime, existing source code might require source changes to compile successfully.
  • Behavioral change: Existing binaries might behave differently at run time.

Reason for change

N/A

Recommended action

Seems like the America/X IDs are working properly. Use those instead

Feature area

Core .NET libraries

Affected APIs

TimeZoneInfo.FindSystemTimeZoneById(String)

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions