@@ -2335,14 +2335,55 @@ public static IEnumerable<object[]> SystemTimeZonesTestData()
2335
2335
private const string IanaAbbreviationPattern = @"^(?:[A-Z][A-Za-z]+|[+-]\d{2}|[+-]\d{4})$" ;
2336
2336
private static readonly Regex s_IanaAbbreviationRegex = new Regex ( IanaAbbreviationPattern ) ;
2337
2337
2338
+ // UTC aliases per https://github.com/unicode-org/cldr/blob/master/common/bcp47/timezone.xml
2339
+ // (This list is not likely to change.)
2340
+ private static readonly string [ ] s_UtcAliases = new [ ] {
2341
+ "Etc/UTC" ,
2342
+ "Etc/UCT" ,
2343
+ "Etc/Universal" ,
2344
+ "Etc/Zulu" ,
2345
+ "UCT" ,
2346
+ "UTC" ,
2347
+ "Universal" ,
2348
+ "Zulu"
2349
+ } ;
2350
+
2338
2351
[ Theory ]
2339
2352
[ MemberData ( nameof ( SystemTimeZonesTestData ) ) ]
2340
2353
[ PlatformSpecific ( TestPlatforms . AnyUnix ) ]
2341
2354
public static void TimeZoneDisplayNames_Unix ( TimeZoneInfo timeZone )
2342
2355
{
2343
- if ( timeZone . Id == TimeZoneInfo . Utc . Id || timeZone . StandardName == TimeZoneInfo . Utc . StandardName )
2356
+ bool isUtc = s_UtcAliases . Contains ( timeZone . Id , StringComparer . OrdinalIgnoreCase ) ;
2357
+
2358
+ if ( PlatformDetection . IsBrowser )
2344
2359
{
2345
- // UTC's display name is always the string "(UTC) " and the same text as the standard name.
2360
+ // Browser platform doesn't have full ICU names, but uses the IANA IDs and abbreviations instead.
2361
+
2362
+ // The display name will be the offset plus the ID.
2363
+ // The offset is checked separately in TimeZoneInfo_DisplayNameStartsWithOffset
2364
+ Assert . True ( timeZone . DisplayName . EndsWith ( " " + timeZone . Id ) ,
2365
+ $ "Id: \" { timeZone . Id } \" , DisplayName should have ended with the ID, Actual DisplayName: \" { timeZone . DisplayName } \" ") ;
2366
+
2367
+ if ( isUtc )
2368
+ {
2369
+ // Make sure UTC and its aliases have exactly "UTC" for the standard and daylight names
2370
+ Assert . True ( timeZone . StandardName == "UTC" ,
2371
+ $ "Id: \" { timeZone . Id } \" , Expected StandardName: \" UTC\" , Actual StandardName: \" { timeZone . StandardName } \" ") ;
2372
+ Assert . True ( timeZone . DaylightName == "UTC" ,
2373
+ $ "Id: \" { timeZone . Id } \" , Expected DaylightName: \" UTC\" , Actual DaylightName: \" { timeZone . DaylightName } \" ") ;
2374
+ }
2375
+ else
2376
+ {
2377
+ // For other time zones, match any valid IANA time zone abbreviation, including numeric forms
2378
+ Assert . True ( s_IanaAbbreviationRegex . IsMatch ( timeZone . StandardName ) ,
2379
+ $ "Id: \" { timeZone . Id } \" , StandardName should have matched the pattern @\" { IanaAbbreviationPattern } \" , Actual StandardName: \" { timeZone . StandardName } \" ") ;
2380
+ Assert . True ( s_IanaAbbreviationRegex . IsMatch ( timeZone . DaylightName ) ,
2381
+ $ "Id: \" { timeZone . Id } \" , DaylightName should have matched the pattern @\" { IanaAbbreviationPattern } \" , Actual DaylightName: \" { timeZone . DaylightName } \" ") ;
2382
+ }
2383
+ }
2384
+ else if ( isUtc )
2385
+ {
2386
+ // UTC's display name is the string "(UTC) " and the same text as the standard name.
2346
2387
Assert . True ( timeZone . DisplayName == $ "(UTC) { timeZone . StandardName } ",
2347
2388
$ "Id: \" { timeZone . Id } \" , Expected DisplayName: \" (UTC) { timeZone . StandardName } \" , Actual DisplayName: \" { timeZone . DisplayName } \" ") ;
2348
2389
@@ -2354,21 +2395,6 @@ public static void TimeZoneDisplayNames_Unix(TimeZoneInfo timeZone)
2354
2395
Assert . True ( timeZone . DaylightName == TimeZoneInfo . Utc . DaylightName ,
2355
2396
$ "Id: \" { timeZone . Id } \" , Expected DaylightName: \" { TimeZoneInfo . Utc . DaylightName } \" , Actual DaylightName: \" { timeZone . DaylightName } \" ") ;
2356
2397
}
2357
- else if ( PlatformDetection . IsBrowser )
2358
- {
2359
- // Browser platform doesn't have full ICU names, but uses the IANA data instead.
2360
-
2361
- // The display name will be the offset plus the ID.
2362
- // The offset is checked separately in TimeZoneInfo_DisplayNameStartsWithOffset
2363
- Assert . True ( timeZone . DisplayName . EndsWith ( " " + timeZone . Id ) ,
2364
- $ "Id: \" { timeZone . Id } \" , DisplayName should have ended with the ID, Actual DisplayName: \" { timeZone . DisplayName } \" ") ;
2365
-
2366
- // Match any valid IANA time zone abbreviation, including numeric forms
2367
- Assert . True ( s_IanaAbbreviationRegex . IsMatch ( timeZone . StandardName ) ,
2368
- $ "Id: \" { timeZone . Id } \" , StandardName should have matched the pattern @\" { IanaAbbreviationPattern } \" , Actual StandardName: \" { timeZone . StandardName } \" ") ;
2369
- Assert . True ( s_IanaAbbreviationRegex . IsMatch ( timeZone . DaylightName ) ,
2370
- $ "Id: \" { timeZone . Id } \" , DaylightName should have matched the pattern @\" { IanaAbbreviationPattern } \" , Actual DaylightName: \" { timeZone . DaylightName } \" ") ;
2371
- }
2372
2398
else
2373
2399
{
2374
2400
// All we can really say generically here is that they aren't empty.
@@ -2530,7 +2556,7 @@ public static void TimeZoneInfo_DaylightDeltaIsNoMoreThan12Hours()
2530
2556
[ MemberData ( nameof ( SystemTimeZonesTestData ) ) ]
2531
2557
public static void TimeZoneInfo_DisplayNameStartsWithOffset ( TimeZoneInfo tzi )
2532
2558
{
2533
- if ( tzi . StandardName == TimeZoneInfo . Utc . StandardName )
2559
+ if ( s_UtcAliases . Contains ( tzi . Id , StringComparer . OrdinalIgnoreCase ) )
2534
2560
{
2535
2561
// UTC and all of its aliases (Etc/UTC, and others) start with just "(UTC) "
2536
2562
Assert . StartsWith ( "(UTC) " , tzi . DisplayName ) ;
0 commit comments