Fix the ICU time format conversion logic - #103681

Merged
tarekgh merged 13 commits into
dotnet:mainfrom
PopSlime:fix-icu-date-time-format-conversion
Jun 21, 2024
Merged

Fix the ICU time format conversion logic#103681
tarekgh merged 13 commits into
dotnet:mainfrom
PopSlime:fix-icu-date-time-format-conversion

Conversation

@PopSlime

Copy link
Copy Markdown
Contributor

Revise the ICU time format conversion logic to support all unquoted literal texts and the B and b pattern symbols.

Fix#103592

Revise the ICU time format conversion logic to support all unquoted literal texts and the `B` and `b` pattern symbols.
Fixdotnet#103592
@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Jun 19, 2024
@PopSlime

PopSlime commented Jun 19, 2024

Copy link
Copy Markdown
ContributorAuthor

I'm new to such a big and complex project and not sure how to test these changes, so this is a draft at the moment. Looking forward to help from anyone.

Example affected patterns:

ICU patternResult (Old)Result (New)
a नि h:mmtt h:mmtt नि h:mm
ཆུ་ཚོད་h:mm:ss ah:mm:ss ttཆུ་ཚོད་h:mm:ss tt
ཆུ་ཚོད་ h སྐར་མ་ mm a h mm ttཆུ་ཚོད་ h སྐར་མ་ mm tt
Bh:mm:ssh:mm:sstth:mm:ss

More information can be found in the fixing issue.

@mkhamoyan

Copy link
Copy Markdown
Contributor

@mkhamoyan

Copy link
Copy Markdown
Contributor

/azp run runtime-extra-platforms

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@PopSlime

PopSlime commented Jun 19, 2024

Copy link
Copy Markdown
ContributorAuthor

@mkhamoyan I'm not sure how to write the test for this because the retrieved time format is device-/platform-dependent.

Instead of testing against some specific patterns, I'm considering adding a test that fails if a 12-hour clock is used without an AM/PM designator in any pattern in any culture. Also we need another test for the unquoted literal texts, which I have no clues how to do yet.

By the way, short time patterns are also affected by this PR.

@mkhamoyan

mkhamoyan commented Jun 19, 2024

Copy link
Copy Markdown
Contributor

@PopSlime I was thinking something like below (same test case for shorttime patterns under here) would validate the change.

[Theory]
[InlineData("zh-TW")]
[InlineData("en-US")]
[InlineData("fr-FR")]
public void LongTimePattern_ValidateAMPMDesignators(string cultureName)
{
var cultureInfo = new CultureInfo(cultureName);
var date = DateTime.Today + TimeSpan.FromDays(10) + TimeSpan.FromMinutes(10);
string formattedDateTime = date.ToString("T", cultureInfo);
Assert.True(formattedDateTime.Contains(cultureInfo.DateTimeFormat.AMDesignator));
}

This should be consistent for all platforms and devices.
Now we see issue only in some android devices because of different CLDR versions.

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

@mkhamoyan Is it safe to assume those cultures use a 12-hour clock? fr-FR uses a 24-hour clock on my side.

@mkhamoyan

Copy link
Copy Markdown
Contributor

@mkhamoyan Is it safe to assume those cultures use a 12-hour clock? fr-FR uses a 24-hour clock on my side.

My bad, fr-FR shouldn't be there.

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

How about this?

[Fact]publicvoidLongTimePattern_VerifyTimePatterns(){foreach(varcultureinCultureInfo.GetCultures(CultureTypes.AllCultures)){varpattern=culture.DateTimeFormat.LongTimePattern;varsegments=pattern.Split('\'');booluse12Hour=false;booluseAMPM=false;for(vari=0;i<segments.Length;i+=2){varsegment=segments[i];use12Hour|=segment.Contains('h',StringComparison.Ordinal);useAMPM|=segment.Contains('t',StringComparison.Ordinal);}Assert.True(!use12Hour||useAMPM,$"Bad time pattern for culture {culture.Name}: '{pattern}'");}}

By the way, this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'. Should we address this in another issue?

@mkhamoyan

Copy link
Copy Markdown
Contributor

How about this?

Looks good to me.

By the way, this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'. Should we address this in another issue?

Yes , we should file an issue for that.
Let's push in the PR and check how it behaves on other platforms.

@tarekgh
tarekgh self-requested a review June 19, 2024 16:06
Add tests verifying that all the short and long time patterns either use
a 24-hour clock or have an AM/PM designator.
@PopSlime

Copy link
Copy Markdown
ContributorAuthor

@dotnet-policy-service agree

@PopSlime
PopSlime marked this pull request as ready for review June 19, 2024 17:31
@tarekgh

Copy link
Copy Markdown
Member

By the way, this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'. Should we address this in another issue?
Yes , we should file an issue for that.

I don't think we can fix that as the patterns are picked from Windows. I suggest you mark your new test methods with the attribute and see if this can help?

[ConditionalFact(typeof(PlatformDetection),nameof(PlatformDetection.IsIcuGlobalization))]

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

I'll do that, but I also want to see if similar issues are occurring on other platforms, so let's wait for these checks to be done.

@tarekgh

tarekgh commented Jun 19, 2024

Copy link
Copy Markdown
Member

this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'.

I am trying on my machine, and I am not getting the same results you are getting.

mi-NZ .. Maori (New Zealand) .. h:mm tt .. h:mm:ss tt
mi .. Maori .. h:mm tt .. h:mm:ss tt

running code like:

varci=CultureInfo.GetCultureInfo("mi-NZ");Console.WriteLine($"{ci.Name} .. {ci.EnglishName} .. {ci.DateTimeFormat.ShortTimePattern} .. {ci.DateTimeFormat.LongTimePattern}");ci=CultureInfo.GetCultureInfo("mi");Console.WriteLine($"{ci.Name} .. {ci.EnglishName} .. {ci.DateTimeFormat.ShortTimePattern} .. {ci.DateTimeFormat.LongTimePattern}");

What Windows version do you have? I am wondering how you get this result?

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

It seems that the version of the CLDR data installed on my PC is below 36. The time format for mi was fixed in unicode-org/cldr#104.

  • Operating system: Windows 10
  • Version number: 22H2
  • Internal version: 19045.4529

@tarekgh

tarekgh commented Jun 19, 2024

Copy link
Copy Markdown
Member

ok, then the attribute

[ConditionalFact(typeof(PlatformDetection),nameof(PlatformDetection.IsIcuGlobalization))]
is not going to help. You may try using something like
if(PlatformDetection.WindowsVersion>=10||PlatformDetection.ICUVersion.Major>=55||PlatformDetection.IsHybridGlobalizationOnApplePlatform)
to avoid the failure.

I meant using check like if (PlatformDetection.ICUVersion.Major >= 68) .

@ilonatommy

Copy link
Copy Markdown
Member

@PopSlime the tests are still failing. For now, can you exclude running this test with hype globalization? or special case fr-CA when encountering it? @ilonatommy@mkhamoyan do you have any better suggestion? @PopSlime already logged issue to tracking fixing fr-CA formats.

Current behavior was expected and other HybridGlobalization tests are prepared for that. I am looking if we can provide a generic fix. For now this test can be blocked with PlatformDetection.IsNotHybridGlobalizationOnBrowser. The fix can get in in a separate PR

@mkhamoyan

Copy link
Copy Markdown
Contributor

/azp run runtime-ioslike,runtime-ioslikesimulator,runtime-maccatalyst

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 3 pipeline(s).

@mkhamoyanmkhamoyan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.
Let's wait for ios pipelines and then we can merge.

@mkhamoyan

Copy link
Copy Markdown
Contributor

/azp run runtime-ioslike,runtime-ioslikesimulator,runtime-maccatalyst

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 3 pipeline(s).

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime

@azure-pipelines

Copy link
Copy Markdown
Commenter does not have sufficient privileges for PR 103681 in repo dotnet/runtime

@ilonatommy

Copy link
Copy Markdown
Member

/azp run runtime

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@tarekgh
tarekgh merged commit 4b9a1b2 into dotnet:mainJun 21, 2024
rzikm pushed a commit to rzikm/dotnet-runtime that referenced this pull request Jun 24, 2024
* Fix the ICU time format conversion logic
Revise the ICU time format conversion logic to support all unquoted literal texts and the `B` and `b` pattern symbols.
Fixdotnet#103592
* Clarify literal texts in the conversion logic
* Add tests for verifying time patterns
Add tests verifying that all the short and long time patterns either use
a 24-hour clock or have an AM/PM designator.
* Fix literal single quote and literal backslash conversion
* Refactor the literal quote conversion logic
* Revise the test logic to ignore literal texts and check pattern redundancy
Modify the test logic so that it recognizes literal texts correctly, and
fails if 12-hour and 24-hour clocks are used at the same time.
* Revise the test logic to ensure all cultures are tested
* Add comments to clarify the backslash conversion
* Refactor the conversion logic
Simplify some logic and improve readability.
* Exclude bad ICU patterns from the tests
* Exclude the VerifyTimePatterns tests from hybrid globalization on browser
* Add missing usings
* Improve readability of the for-loops
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 23, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Globalizationcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect general long time pattern for some cultures on Android

4 participants

@PopSlime@mkhamoyan@tarekgh@ilonatommy
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Fix the ICU time format conversion logic - #103681

Merged
tarekgh merged 13 commits into
dotnet:mainfrom
PopSlime:fix-icu-date-time-format-conversion
Jun 21, 2024
Merged

Fix the ICU time format conversion logic#103681
tarekgh merged 13 commits into
dotnet:mainfrom
PopSlime:fix-icu-date-time-format-conversion

Conversation

@PopSlime

Copy link
Copy Markdown
Contributor

Revise the ICU time format conversion logic to support all unquoted literal texts and the B and b pattern symbols.

Fix#103592

Revise the ICU time format conversion logic to support all unquoted literal texts and the `B` and `b` pattern symbols.
Fixdotnet#103592
@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Jun 19, 2024
@PopSlime

PopSlime commented Jun 19, 2024

Copy link
Copy Markdown
ContributorAuthor

I'm new to such a big and complex project and not sure how to test these changes, so this is a draft at the moment. Looking forward to help from anyone.

Example affected patterns:

ICU patternResult (Old)Result (New)
a नि h:mmtt h:mmtt नि h:mm
ཆུ་ཚོད་h:mm:ss ah:mm:ss ttཆུ་ཚོད་h:mm:ss tt
ཆུ་ཚོད་ h སྐར་མ་ mm a h mm ttཆུ་ཚོད་ h སྐར་མ་ mm tt
Bh:mm:ssh:mm:sstth:mm:ss

More information can be found in the fixing issue.

@mkhamoyan

Copy link
Copy Markdown
Contributor

@mkhamoyan

Copy link
Copy Markdown
Contributor

/azp run runtime-extra-platforms

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@PopSlime

PopSlime commented Jun 19, 2024

Copy link
Copy Markdown
ContributorAuthor

@mkhamoyan I'm not sure how to write the test for this because the retrieved time format is device-/platform-dependent.

Instead of testing against some specific patterns, I'm considering adding a test that fails if a 12-hour clock is used without an AM/PM designator in any pattern in any culture. Also we need another test for the unquoted literal texts, which I have no clues how to do yet.

By the way, short time patterns are also affected by this PR.

@mkhamoyan

mkhamoyan commented Jun 19, 2024

Copy link
Copy Markdown
Contributor

@PopSlime I was thinking something like below (same test case for shorttime patterns under here) would validate the change.

[Theory]
[InlineData("zh-TW")]
[InlineData("en-US")]
[InlineData("fr-FR")]
public void LongTimePattern_ValidateAMPMDesignators(string cultureName)
{
var cultureInfo = new CultureInfo(cultureName);
var date = DateTime.Today + TimeSpan.FromDays(10) + TimeSpan.FromMinutes(10);
string formattedDateTime = date.ToString("T", cultureInfo);
Assert.True(formattedDateTime.Contains(cultureInfo.DateTimeFormat.AMDesignator));
}

This should be consistent for all platforms and devices.
Now we see issue only in some android devices because of different CLDR versions.

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

@mkhamoyan Is it safe to assume those cultures use a 12-hour clock? fr-FR uses a 24-hour clock on my side.

@mkhamoyan

Copy link
Copy Markdown
Contributor

@mkhamoyan Is it safe to assume those cultures use a 12-hour clock? fr-FR uses a 24-hour clock on my side.

My bad, fr-FR shouldn't be there.

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

How about this?

[Fact]publicvoidLongTimePattern_VerifyTimePatterns(){foreach(varcultureinCultureInfo.GetCultures(CultureTypes.AllCultures)){varpattern=culture.DateTimeFormat.LongTimePattern;varsegments=pattern.Split('\'');booluse12Hour=false;booluseAMPM=false;for(vari=0;i<segments.Length;i+=2){varsegment=segments[i];use12Hour|=segment.Contains('h',StringComparison.Ordinal);useAMPM|=segment.Contains('t',StringComparison.Ordinal);}Assert.True(!use12Hour||useAMPM,$"Bad time pattern for culture {culture.Name}: '{pattern}'");}}

By the way, this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'. Should we address this in another issue?

@mkhamoyan

Copy link
Copy Markdown
Contributor

How about this?

Looks good to me.

By the way, this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'. Should we address this in another issue?

Yes , we should file an issue for that.
Let's push in the PR and check how it behaves on other platforms.

@tarekgh
tarekgh self-requested a review June 19, 2024 16:06
Add tests verifying that all the short and long time patterns either use
a 24-hour clock or have an AM/PM designator.
@PopSlime

Copy link
Copy Markdown
ContributorAuthor

@dotnet-policy-service agree

@PopSlime
PopSlime marked this pull request as ready for review June 19, 2024 17:31
@tarekgh

Copy link
Copy Markdown
Member

By the way, this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'. Should we address this in another issue?
Yes , we should file an issue for that.

I don't think we can fix that as the patterns are picked from Windows. I suggest you mark your new test methods with the attribute and see if this can help?

[ConditionalFact(typeof(PlatformDetection),nameof(PlatformDetection.IsIcuGlobalization))]

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

I'll do that, but I also want to see if similar issues are occurring on other platforms, so let's wait for these checks to be done.

@tarekgh

tarekgh commented Jun 19, 2024

Copy link
Copy Markdown
Member

this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'.

I am trying on my machine, and I am not getting the same results you are getting.

mi-NZ .. Maori (New Zealand) .. h:mm tt .. h:mm:ss tt
mi .. Maori .. h:mm tt .. h:mm:ss tt

running code like:

varci=CultureInfo.GetCultureInfo("mi-NZ");Console.WriteLine($"{ci.Name} .. {ci.EnglishName} .. {ci.DateTimeFormat.ShortTimePattern} .. {ci.DateTimeFormat.LongTimePattern}");ci=CultureInfo.GetCultureInfo("mi");Console.WriteLine($"{ci.Name} .. {ci.EnglishName} .. {ci.DateTimeFormat.ShortTimePattern} .. {ci.DateTimeFormat.LongTimePattern}");

What Windows version do you have? I am wondering how you get this result?

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

It seems that the version of the CLDR data installed on my PC is below 36. The time format for mi was fixed in unicode-org/cldr#104.

  • Operating system: Windows 10
  • Version number: 22H2
  • Internal version: 19045.4529

@tarekgh

tarekgh commented Jun 19, 2024

Copy link
Copy Markdown
Member

ok, then the attribute

[ConditionalFact(typeof(PlatformDetection),nameof(PlatformDetection.IsIcuGlobalization))]
is not going to help. You may try using something like
if(PlatformDetection.WindowsVersion>=10||PlatformDetection.ICUVersion.Major>=55||PlatformDetection.IsHybridGlobalizationOnApplePlatform)
to avoid the failure.

I meant using check like if (PlatformDetection.ICUVersion.Major >= 68) .

@ilonatommy

Copy link
Copy Markdown
Member

@PopSlime the tests are still failing. For now, can you exclude running this test with hype globalization? or special case fr-CA when encountering it? @ilonatommy@mkhamoyan do you have any better suggestion? @PopSlime already logged issue to tracking fixing fr-CA formats.

Current behavior was expected and other HybridGlobalization tests are prepared for that. I am looking if we can provide a generic fix. For now this test can be blocked with PlatformDetection.IsNotHybridGlobalizationOnBrowser. The fix can get in in a separate PR

@mkhamoyan

Copy link
Copy Markdown
Contributor

/azp run runtime-ioslike,runtime-ioslikesimulator,runtime-maccatalyst

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 3 pipeline(s).

@mkhamoyanmkhamoyan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.
Let's wait for ios pipelines and then we can merge.

@mkhamoyan

Copy link
Copy Markdown
Contributor

/azp run runtime-ioslike,runtime-ioslikesimulator,runtime-maccatalyst

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 3 pipeline(s).

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime

@azure-pipelines

Copy link
Copy Markdown
Commenter does not have sufficient privileges for PR 103681 in repo dotnet/runtime

@ilonatommy

Copy link
Copy Markdown
Member

/azp run runtime

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@tarekgh
tarekgh merged commit 4b9a1b2 into dotnet:mainJun 21, 2024
rzikm pushed a commit to rzikm/dotnet-runtime that referenced this pull request Jun 24, 2024
* Fix the ICU time format conversion logic
Revise the ICU time format conversion logic to support all unquoted literal texts and the `B` and `b` pattern symbols.
Fixdotnet#103592
* Clarify literal texts in the conversion logic
* Add tests for verifying time patterns
Add tests verifying that all the short and long time patterns either use
a 24-hour clock or have an AM/PM designator.
* Fix literal single quote and literal backslash conversion
* Refactor the literal quote conversion logic
* Revise the test logic to ignore literal texts and check pattern redundancy
Modify the test logic so that it recognizes literal texts correctly, and
fails if 12-hour and 24-hour clocks are used at the same time.
* Revise the test logic to ensure all cultures are tested
* Add comments to clarify the backslash conversion
* Refactor the conversion logic
Simplify some logic and improve readability.
* Exclude bad ICU patterns from the tests
* Exclude the VerifyTimePatterns tests from hybrid globalization on browser
* Add missing usings
* Improve readability of the for-loops
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 23, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Globalizationcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect general long time pattern for some cultures on Android

4 participants

@PopSlime@mkhamoyan@tarekgh@ilonatommy
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix the ICU time format conversion logic - #103681

Merged
tarekgh merged 13 commits into
dotnet:mainfrom
PopSlime:fix-icu-date-time-format-conversion
Jun 21, 2024
Merged

Fix the ICU time format conversion logic#103681
tarekgh merged 13 commits into
dotnet:mainfrom
PopSlime:fix-icu-date-time-format-conversion

Conversation

@PopSlime

Copy link
Copy Markdown
Contributor

Revise the ICU time format conversion logic to support all unquoted literal texts and the B and b pattern symbols.

Fix#103592

Revise the ICU time format conversion logic to support all unquoted literal texts and the `B` and `b` pattern symbols.
Fixdotnet#103592
@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Jun 19, 2024
@PopSlime

PopSlime commented Jun 19, 2024

Copy link
Copy Markdown
ContributorAuthor

I'm new to such a big and complex project and not sure how to test these changes, so this is a draft at the moment. Looking forward to help from anyone.

Example affected patterns:

ICU patternResult (Old)Result (New)
a नि h:mmtt h:mmtt नि h:mm
ཆུ་ཚོད་h:mm:ss ah:mm:ss ttཆུ་ཚོད་h:mm:ss tt
ཆུ་ཚོད་ h སྐར་མ་ mm a h mm ttཆུ་ཚོད་ h སྐར་མ་ mm tt
Bh:mm:ssh:mm:sstth:mm:ss

More information can be found in the fixing issue.

@mkhamoyan

Copy link
Copy Markdown
Contributor

@mkhamoyan

Copy link
Copy Markdown
Contributor

/azp run runtime-extra-platforms

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@PopSlime

PopSlime commented Jun 19, 2024

Copy link
Copy Markdown
ContributorAuthor

@mkhamoyan I'm not sure how to write the test for this because the retrieved time format is device-/platform-dependent.

Instead of testing against some specific patterns, I'm considering adding a test that fails if a 12-hour clock is used without an AM/PM designator in any pattern in any culture. Also we need another test for the unquoted literal texts, which I have no clues how to do yet.

By the way, short time patterns are also affected by this PR.

@mkhamoyan

mkhamoyan commented Jun 19, 2024

Copy link
Copy Markdown
Contributor

@PopSlime I was thinking something like below (same test case for shorttime patterns under here) would validate the change.

[Theory]
[InlineData("zh-TW")]
[InlineData("en-US")]
[InlineData("fr-FR")]
public void LongTimePattern_ValidateAMPMDesignators(string cultureName)
{
var cultureInfo = new CultureInfo(cultureName);
var date = DateTime.Today + TimeSpan.FromDays(10) + TimeSpan.FromMinutes(10);
string formattedDateTime = date.ToString("T", cultureInfo);
Assert.True(formattedDateTime.Contains(cultureInfo.DateTimeFormat.AMDesignator));
}

This should be consistent for all platforms and devices.
Now we see issue only in some android devices because of different CLDR versions.

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

@mkhamoyan Is it safe to assume those cultures use a 12-hour clock? fr-FR uses a 24-hour clock on my side.

@mkhamoyan

Copy link
Copy Markdown
Contributor

@mkhamoyan Is it safe to assume those cultures use a 12-hour clock? fr-FR uses a 24-hour clock on my side.

My bad, fr-FR shouldn't be there.

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

How about this?

[Fact]publicvoidLongTimePattern_VerifyTimePatterns(){foreach(varcultureinCultureInfo.GetCultures(CultureTypes.AllCultures)){varpattern=culture.DateTimeFormat.LongTimePattern;varsegments=pattern.Split('\'');booluse12Hour=false;booluseAMPM=false;for(vari=0;i<segments.Length;i+=2){varsegment=segments[i];use12Hour|=segment.Contains('h',StringComparison.Ordinal);useAMPM|=segment.Contains('t',StringComparison.Ordinal);}Assert.True(!use12Hour||useAMPM,$"Bad time pattern for culture {culture.Name}: '{pattern}'");}}

By the way, this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'. Should we address this in another issue?

@mkhamoyan

Copy link
Copy Markdown
Contributor

How about this?

Looks good to me.

By the way, this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'. Should we address this in another issue?

Yes , we should file an issue for that.
Let's push in the PR and check how it behaves on other platforms.

@tarekgh
tarekgh self-requested a review June 19, 2024 16:06
Add tests verifying that all the short and long time patterns either use
a 24-hour clock or have an AM/PM designator.
@PopSlime

Copy link
Copy Markdown
ContributorAuthor

@dotnet-policy-service agree

@PopSlime
PopSlime marked this pull request as ready for review June 19, 2024 17:31
@tarekgh

Copy link
Copy Markdown
Member

By the way, this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'. Should we address this in another issue?
Yes , we should file an issue for that.

I don't think we can fix that as the patterns are picked from Windows. I suggest you mark your new test methods with the attribute and see if this can help?

[ConditionalFact(typeof(PlatformDetection),nameof(PlatformDetection.IsIcuGlobalization))]

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

I'll do that, but I also want to see if similar issues are occurring on other platforms, so let's wait for these checks to be done.

@tarekgh

tarekgh commented Jun 19, 2024

Copy link
Copy Markdown
Member

this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'.

I am trying on my machine, and I am not getting the same results you are getting.

mi-NZ .. Maori (New Zealand) .. h:mm tt .. h:mm:ss tt
mi .. Maori .. h:mm tt .. h:mm:ss tt

running code like:

varci=CultureInfo.GetCultureInfo("mi-NZ");Console.WriteLine($"{ci.Name} .. {ci.EnglishName} .. {ci.DateTimeFormat.ShortTimePattern} .. {ci.DateTimeFormat.LongTimePattern}");ci=CultureInfo.GetCultureInfo("mi");Console.WriteLine($"{ci.Name} .. {ci.EnglishName} .. {ci.DateTimeFormat.ShortTimePattern} .. {ci.DateTimeFormat.LongTimePattern}");

What Windows version do you have? I am wondering how you get this result?

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

It seems that the version of the CLDR data installed on my PC is below 36. The time format for mi was fixed in unicode-org/cldr#104.

  • Operating system: Windows 10
  • Version number: 22H2
  • Internal version: 19045.4529

@tarekgh

tarekgh commented Jun 19, 2024

Copy link
Copy Markdown
Member

ok, then the attribute

[ConditionalFact(typeof(PlatformDetection),nameof(PlatformDetection.IsIcuGlobalization))]
is not going to help. You may try using something like
if(PlatformDetection.WindowsVersion>=10||PlatformDetection.ICUVersion.Major>=55||PlatformDetection.IsHybridGlobalizationOnApplePlatform)
to avoid the failure.

I meant using check like if (PlatformDetection.ICUVersion.Major >= 68) .

@ilonatommy

Copy link
Copy Markdown
Member

@PopSlime the tests are still failing. For now, can you exclude running this test with hype globalization? or special case fr-CA when encountering it? @ilonatommy@mkhamoyan do you have any better suggestion? @PopSlime already logged issue to tracking fixing fr-CA formats.

Current behavior was expected and other HybridGlobalization tests are prepared for that. I am looking if we can provide a generic fix. For now this test can be blocked with PlatformDetection.IsNotHybridGlobalizationOnBrowser. The fix can get in in a separate PR

@mkhamoyan

Copy link
Copy Markdown
Contributor

/azp run runtime-ioslike,runtime-ioslikesimulator,runtime-maccatalyst

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 3 pipeline(s).

@mkhamoyanmkhamoyan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.
Let's wait for ios pipelines and then we can merge.

@mkhamoyan

Copy link
Copy Markdown
Contributor

/azp run runtime-ioslike,runtime-ioslikesimulator,runtime-maccatalyst

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 3 pipeline(s).

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime

@azure-pipelines

Copy link
Copy Markdown
Commenter does not have sufficient privileges for PR 103681 in repo dotnet/runtime

@ilonatommy

Copy link
Copy Markdown
Member

/azp run runtime

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@tarekgh
tarekgh merged commit 4b9a1b2 into dotnet:mainJun 21, 2024
rzikm pushed a commit to rzikm/dotnet-runtime that referenced this pull request Jun 24, 2024
* Fix the ICU time format conversion logic
Revise the ICU time format conversion logic to support all unquoted literal texts and the `B` and `b` pattern symbols.
Fixdotnet#103592
* Clarify literal texts in the conversion logic
* Add tests for verifying time patterns
Add tests verifying that all the short and long time patterns either use
a 24-hour clock or have an AM/PM designator.
* Fix literal single quote and literal backslash conversion
* Refactor the literal quote conversion logic
* Revise the test logic to ignore literal texts and check pattern redundancy
Modify the test logic so that it recognizes literal texts correctly, and
fails if 12-hour and 24-hour clocks are used at the same time.
* Revise the test logic to ensure all cultures are tested
* Add comments to clarify the backslash conversion
* Refactor the conversion logic
Simplify some logic and improve readability.
* Exclude bad ICU patterns from the tests
* Exclude the VerifyTimePatterns tests from hybrid globalization on browser
* Add missing usings
* Improve readability of the for-loops
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 23, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Globalizationcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect general long time pattern for some cultures on Android

4 participants

@PopSlime@mkhamoyan@tarekgh@ilonatommy
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix the ICU time format conversion logic - #103681

Merged
tarekgh merged 13 commits into
dotnet:mainfrom
PopSlime:fix-icu-date-time-format-conversion
Jun 21, 2024
Merged

Fix the ICU time format conversion logic#103681
tarekgh merged 13 commits into
dotnet:mainfrom
PopSlime:fix-icu-date-time-format-conversion

Conversation

@PopSlime

Copy link
Copy Markdown
Contributor

Revise the ICU time format conversion logic to support all unquoted literal texts and the B and b pattern symbols.

Fix#103592

Revise the ICU time format conversion logic to support all unquoted literal texts and the `B` and `b` pattern symbols.
Fixdotnet#103592
@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Jun 19, 2024
@PopSlime

PopSlime commented Jun 19, 2024

Copy link
Copy Markdown
ContributorAuthor

I'm new to such a big and complex project and not sure how to test these changes, so this is a draft at the moment. Looking forward to help from anyone.

Example affected patterns:

ICU patternResult (Old)Result (New)
a नि h:mmtt h:mmtt नि h:mm
ཆུ་ཚོད་h:mm:ss ah:mm:ss ttཆུ་ཚོད་h:mm:ss tt
ཆུ་ཚོད་ h སྐར་མ་ mm a h mm ttཆུ་ཚོད་ h སྐར་མ་ mm tt
Bh:mm:ssh:mm:sstth:mm:ss

More information can be found in the fixing issue.

@mkhamoyan

Copy link
Copy Markdown
Contributor

@mkhamoyan

Copy link
Copy Markdown
Contributor

/azp run runtime-extra-platforms

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@PopSlime

PopSlime commented Jun 19, 2024

Copy link
Copy Markdown
ContributorAuthor

@mkhamoyan I'm not sure how to write the test for this because the retrieved time format is device-/platform-dependent.

Instead of testing against some specific patterns, I'm considering adding a test that fails if a 12-hour clock is used without an AM/PM designator in any pattern in any culture. Also we need another test for the unquoted literal texts, which I have no clues how to do yet.

By the way, short time patterns are also affected by this PR.

@mkhamoyan

mkhamoyan commented Jun 19, 2024

Copy link
Copy Markdown
Contributor

@PopSlime I was thinking something like below (same test case for shorttime patterns under here) would validate the change.

[Theory]
[InlineData("zh-TW")]
[InlineData("en-US")]
[InlineData("fr-FR")]
public void LongTimePattern_ValidateAMPMDesignators(string cultureName)
{
var cultureInfo = new CultureInfo(cultureName);
var date = DateTime.Today + TimeSpan.FromDays(10) + TimeSpan.FromMinutes(10);
string formattedDateTime = date.ToString("T", cultureInfo);
Assert.True(formattedDateTime.Contains(cultureInfo.DateTimeFormat.AMDesignator));
}

This should be consistent for all platforms and devices.
Now we see issue only in some android devices because of different CLDR versions.

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

@mkhamoyan Is it safe to assume those cultures use a 12-hour clock? fr-FR uses a 24-hour clock on my side.

@mkhamoyan

Copy link
Copy Markdown
Contributor

@mkhamoyan Is it safe to assume those cultures use a 12-hour clock? fr-FR uses a 24-hour clock on my side.

My bad, fr-FR shouldn't be there.

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

How about this?

[Fact]publicvoidLongTimePattern_VerifyTimePatterns(){foreach(varcultureinCultureInfo.GetCultures(CultureTypes.AllCultures)){varpattern=culture.DateTimeFormat.LongTimePattern;varsegments=pattern.Split('\'');booluse12Hour=false;booluseAMPM=false;for(vari=0;i<segments.Length;i+=2){varsegment=segments[i];use12Hour|=segment.Contains('h',StringComparison.Ordinal);useAMPM|=segment.Contains('t',StringComparison.Ordinal);}Assert.True(!use12Hour||useAMPM,$"Bad time pattern for culture {culture.Name}: '{pattern}'");}}

By the way, this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'. Should we address this in another issue?

@mkhamoyan

Copy link
Copy Markdown
Contributor

How about this?

Looks good to me.

By the way, this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'. Should we address this in another issue?

Yes , we should file an issue for that.
Let's push in the PR and check how it behaves on other platforms.

@tarekgh
tarekgh self-requested a review June 19, 2024 16:06
Add tests verifying that all the short and long time patterns either use
a 24-hour clock or have an AM/PM designator.
@PopSlime

Copy link
Copy Markdown
ContributorAuthor

@dotnet-policy-service agree

@PopSlime
PopSlime marked this pull request as ready for review June 19, 2024 17:31
@tarekgh

Copy link
Copy Markdown
Member

By the way, this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'. Should we address this in another issue?
Yes , we should file an issue for that.

I don't think we can fix that as the patterns are picked from Windows. I suggest you mark your new test methods with the attribute and see if this can help?

[ConditionalFact(typeof(PlatformDetection),nameof(PlatformDetection.IsIcuGlobalization))]

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

I'll do that, but I also want to see if similar issues are occurring on other platforms, so let's wait for these checks to be done.

@tarekgh

tarekgh commented Jun 19, 2024

Copy link
Copy Markdown
Member

this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'.

I am trying on my machine, and I am not getting the same results you are getting.

mi-NZ .. Maori (New Zealand) .. h:mm tt .. h:mm:ss tt
mi .. Maori .. h:mm tt .. h:mm:ss tt

running code like:

varci=CultureInfo.GetCultureInfo("mi-NZ");Console.WriteLine($"{ci.Name} .. {ci.EnglishName} .. {ci.DateTimeFormat.ShortTimePattern} .. {ci.DateTimeFormat.LongTimePattern}");ci=CultureInfo.GetCultureInfo("mi");Console.WriteLine($"{ci.Name} .. {ci.EnglishName} .. {ci.DateTimeFormat.ShortTimePattern} .. {ci.DateTimeFormat.LongTimePattern}");

What Windows version do you have? I am wondering how you get this result?

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

It seems that the version of the CLDR data installed on my PC is below 36. The time format for mi was fixed in unicode-org/cldr#104.

  • Operating system: Windows 10
  • Version number: 22H2
  • Internal version: 19045.4529

@tarekgh

tarekgh commented Jun 19, 2024

Copy link
Copy Markdown
Member

ok, then the attribute

[ConditionalFact(typeof(PlatformDetection),nameof(PlatformDetection.IsIcuGlobalization))]
is not going to help. You may try using something like
if(PlatformDetection.WindowsVersion>=10||PlatformDetection.ICUVersion.Major>=55||PlatformDetection.IsHybridGlobalizationOnApplePlatform)
to avoid the failure.

I meant using check like if (PlatformDetection.ICUVersion.Major >= 68) .

@ilonatommy

Copy link
Copy Markdown
Member

@PopSlime the tests are still failing. For now, can you exclude running this test with hype globalization? or special case fr-CA when encountering it? @ilonatommy@mkhamoyan do you have any better suggestion? @PopSlime already logged issue to tracking fixing fr-CA formats.

Current behavior was expected and other HybridGlobalization tests are prepared for that. I am looking if we can provide a generic fix. For now this test can be blocked with PlatformDetection.IsNotHybridGlobalizationOnBrowser. The fix can get in in a separate PR

@mkhamoyan

Copy link
Copy Markdown
Contributor

/azp run runtime-ioslike,runtime-ioslikesimulator,runtime-maccatalyst

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 3 pipeline(s).

@mkhamoyanmkhamoyan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.
Let's wait for ios pipelines and then we can merge.

@mkhamoyan

Copy link
Copy Markdown
Contributor

/azp run runtime-ioslike,runtime-ioslikesimulator,runtime-maccatalyst

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 3 pipeline(s).

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime

@azure-pipelines

Copy link
Copy Markdown
Commenter does not have sufficient privileges for PR 103681 in repo dotnet/runtime

@ilonatommy

Copy link
Copy Markdown
Member

/azp run runtime

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@tarekgh
tarekgh merged commit 4b9a1b2 into dotnet:mainJun 21, 2024
rzikm pushed a commit to rzikm/dotnet-runtime that referenced this pull request Jun 24, 2024
* Fix the ICU time format conversion logic
Revise the ICU time format conversion logic to support all unquoted literal texts and the `B` and `b` pattern symbols.
Fixdotnet#103592
* Clarify literal texts in the conversion logic
* Add tests for verifying time patterns
Add tests verifying that all the short and long time patterns either use
a 24-hour clock or have an AM/PM designator.
* Fix literal single quote and literal backslash conversion
* Refactor the literal quote conversion logic
* Revise the test logic to ignore literal texts and check pattern redundancy
Modify the test logic so that it recognizes literal texts correctly, and
fails if 12-hour and 24-hour clocks are used at the same time.
* Revise the test logic to ensure all cultures are tested
* Add comments to clarify the backslash conversion
* Refactor the conversion logic
Simplify some logic and improve readability.
* Exclude bad ICU patterns from the tests
* Exclude the VerifyTimePatterns tests from hybrid globalization on browser
* Add missing usings
* Improve readability of the for-loops
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 23, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Globalizationcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect general long time pattern for some cultures on Android

4 participants

@PopSlime@mkhamoyan@tarekgh@ilonatommy
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Fix the ICU time format conversion logic - #103681

Merged
tarekgh merged 13 commits into
dotnet:mainfrom
PopSlime:fix-icu-date-time-format-conversion
Jun 21, 2024
Merged

Fix the ICU time format conversion logic#103681
tarekgh merged 13 commits into
dotnet:mainfrom
PopSlime:fix-icu-date-time-format-conversion

Conversation

@PopSlime

Copy link
Copy Markdown
Contributor

Revise the ICU time format conversion logic to support all unquoted literal texts and the B and b pattern symbols.

Fix#103592

Revise the ICU time format conversion logic to support all unquoted literal texts and the `B` and `b` pattern symbols.
Fixdotnet#103592
@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Jun 19, 2024
@PopSlime

PopSlime commented Jun 19, 2024

Copy link
Copy Markdown
ContributorAuthor

I'm new to such a big and complex project and not sure how to test these changes, so this is a draft at the moment. Looking forward to help from anyone.

Example affected patterns:

ICU patternResult (Old)Result (New)
a नि h:mmtt h:mmtt नि h:mm
ཆུ་ཚོད་h:mm:ss ah:mm:ss ttཆུ་ཚོད་h:mm:ss tt
ཆུ་ཚོད་ h སྐར་མ་ mm a h mm ttཆུ་ཚོད་ h སྐར་མ་ mm tt
Bh:mm:ssh:mm:sstth:mm:ss

More information can be found in the fixing issue.

@mkhamoyan

Copy link
Copy Markdown
Contributor

@mkhamoyan

Copy link
Copy Markdown
Contributor

/azp run runtime-extra-platforms

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@PopSlime

PopSlime commented Jun 19, 2024

Copy link
Copy Markdown
ContributorAuthor

@mkhamoyan I'm not sure how to write the test for this because the retrieved time format is device-/platform-dependent.

Instead of testing against some specific patterns, I'm considering adding a test that fails if a 12-hour clock is used without an AM/PM designator in any pattern in any culture. Also we need another test for the unquoted literal texts, which I have no clues how to do yet.

By the way, short time patterns are also affected by this PR.

@mkhamoyan

mkhamoyan commented Jun 19, 2024

Copy link
Copy Markdown
Contributor

@PopSlime I was thinking something like below (same test case for shorttime patterns under here) would validate the change.

[Theory]
[InlineData("zh-TW")]
[InlineData("en-US")]
[InlineData("fr-FR")]
public void LongTimePattern_ValidateAMPMDesignators(string cultureName)
{
var cultureInfo = new CultureInfo(cultureName);
var date = DateTime.Today + TimeSpan.FromDays(10) + TimeSpan.FromMinutes(10);
string formattedDateTime = date.ToString("T", cultureInfo);
Assert.True(formattedDateTime.Contains(cultureInfo.DateTimeFormat.AMDesignator));
}

This should be consistent for all platforms and devices.
Now we see issue only in some android devices because of different CLDR versions.

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

@mkhamoyan Is it safe to assume those cultures use a 12-hour clock? fr-FR uses a 24-hour clock on my side.

@mkhamoyan

Copy link
Copy Markdown
Contributor

@mkhamoyan Is it safe to assume those cultures use a 12-hour clock? fr-FR uses a 24-hour clock on my side.

My bad, fr-FR shouldn't be there.

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

How about this?

[Fact]publicvoidLongTimePattern_VerifyTimePatterns(){foreach(varcultureinCultureInfo.GetCultures(CultureTypes.AllCultures)){varpattern=culture.DateTimeFormat.LongTimePattern;varsegments=pattern.Split('\'');booluse12Hour=false;booluseAMPM=false;for(vari=0;i<segments.Length;i+=2){varsegment=segments[i];use12Hour|=segment.Contains('h',StringComparison.Ordinal);useAMPM|=segment.Contains('t',StringComparison.Ordinal);}Assert.True(!use12Hour||useAMPM,$"Bad time pattern for culture {culture.Name}: '{pattern}'");}}

By the way, this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'. Should we address this in another issue?

@mkhamoyan

Copy link
Copy Markdown
Contributor

How about this?

Looks good to me.

By the way, this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'. Should we address this in another issue?

Yes , we should file an issue for that.
Let's push in the PR and check how it behaves on other platforms.

@tarekgh
tarekgh self-requested a review June 19, 2024 16:06
Add tests verifying that all the short and long time patterns either use
a 24-hour clock or have an AM/PM designator.
@PopSlime

Copy link
Copy Markdown
ContributorAuthor

@dotnet-policy-service agree

@PopSlime
PopSlime marked this pull request as ready for review June 19, 2024 17:31
@tarekgh

Copy link
Copy Markdown
Member

By the way, this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'. Should we address this in another issue?
Yes , we should file an issue for that.

I don't think we can fix that as the patterns are picked from Windows. I suggest you mark your new test methods with the attribute and see if this can help?

[ConditionalFact(typeof(PlatformDetection),nameof(PlatformDetection.IsIcuGlobalization))]

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

I'll do that, but I also want to see if similar issues are occurring on other platforms, so let's wait for these checks to be done.

@tarekgh

tarekgh commented Jun 19, 2024

Copy link
Copy Markdown
Member

this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'.

I am trying on my machine, and I am not getting the same results you are getting.

mi-NZ .. Maori (New Zealand) .. h:mm tt .. h:mm:ss tt
mi .. Maori .. h:mm tt .. h:mm:ss tt

running code like:

varci=CultureInfo.GetCultureInfo("mi-NZ");Console.WriteLine($"{ci.Name} .. {ci.EnglishName} .. {ci.DateTimeFormat.ShortTimePattern} .. {ci.DateTimeFormat.LongTimePattern}");ci=CultureInfo.GetCultureInfo("mi");Console.WriteLine($"{ci.Name} .. {ci.EnglishName} .. {ci.DateTimeFormat.ShortTimePattern} .. {ci.DateTimeFormat.LongTimePattern}");

What Windows version do you have? I am wondering how you get this result?

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

It seems that the version of the CLDR data installed on my PC is below 36. The time format for mi was fixed in unicode-org/cldr#104.

  • Operating system: Windows 10
  • Version number: 22H2
  • Internal version: 19045.4529

@tarekgh

tarekgh commented Jun 19, 2024

Copy link
Copy Markdown
Member

ok, then the attribute

[ConditionalFact(typeof(PlatformDetection),nameof(PlatformDetection.IsIcuGlobalization))]
is not going to help. You may try using something like
if(PlatformDetection.WindowsVersion>=10||PlatformDetection.ICUVersion.Major>=55||PlatformDetection.IsHybridGlobalizationOnApplePlatform)
to avoid the failure.

I meant using check like if (PlatformDetection.ICUVersion.Major >= 68) .

@ilonatommy

Copy link
Copy Markdown
Member

@PopSlime the tests are still failing. For now, can you exclude running this test with hype globalization? or special case fr-CA when encountering it? @ilonatommy@mkhamoyan do you have any better suggestion? @PopSlime already logged issue to tracking fixing fr-CA formats.

Current behavior was expected and other HybridGlobalization tests are prepared for that. I am looking if we can provide a generic fix. For now this test can be blocked with PlatformDetection.IsNotHybridGlobalizationOnBrowser. The fix can get in in a separate PR

@mkhamoyan

Copy link
Copy Markdown
Contributor

/azp run runtime-ioslike,runtime-ioslikesimulator,runtime-maccatalyst

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 3 pipeline(s).

@mkhamoyanmkhamoyan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.
Let's wait for ios pipelines and then we can merge.

@mkhamoyan

Copy link
Copy Markdown
Contributor

/azp run runtime-ioslike,runtime-ioslikesimulator,runtime-maccatalyst

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 3 pipeline(s).

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime

@azure-pipelines

Copy link
Copy Markdown
Commenter does not have sufficient privileges for PR 103681 in repo dotnet/runtime

@ilonatommy

Copy link
Copy Markdown
Member

/azp run runtime

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@tarekgh
tarekgh merged commit 4b9a1b2 into dotnet:mainJun 21, 2024
rzikm pushed a commit to rzikm/dotnet-runtime that referenced this pull request Jun 24, 2024
* Fix the ICU time format conversion logic
Revise the ICU time format conversion logic to support all unquoted literal texts and the `B` and `b` pattern symbols.
Fixdotnet#103592
* Clarify literal texts in the conversion logic
* Add tests for verifying time patterns
Add tests verifying that all the short and long time patterns either use
a 24-hour clock or have an AM/PM designator.
* Fix literal single quote and literal backslash conversion
* Refactor the literal quote conversion logic
* Revise the test logic to ignore literal texts and check pattern redundancy
Modify the test logic so that it recognizes literal texts correctly, and
fails if 12-hour and 24-hour clocks are used at the same time.
* Revise the test logic to ensure all cultures are tested
* Add comments to clarify the backslash conversion
* Refactor the conversion logic
Simplify some logic and improve readability.
* Exclude bad ICU patterns from the tests
* Exclude the VerifyTimePatterns tests from hybrid globalization on browser
* Add missing usings
* Improve readability of the for-loops
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 23, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Globalizationcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect general long time pattern for some cultures on Android

4 participants

@PopSlime@mkhamoyan@tarekgh@ilonatommy
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix the ICU time format conversion logic - #103681

Merged
tarekgh merged 13 commits into
dotnet:mainfrom
PopSlime:fix-icu-date-time-format-conversion
Jun 21, 2024
Merged

Fix the ICU time format conversion logic#103681
tarekgh merged 13 commits into
dotnet:mainfrom
PopSlime:fix-icu-date-time-format-conversion

Conversation

@PopSlime

Copy link
Copy Markdown
Contributor

Revise the ICU time format conversion logic to support all unquoted literal texts and the B and b pattern symbols.

Fix#103592

Revise the ICU time format conversion logic to support all unquoted literal texts and the `B` and `b` pattern symbols.
Fixdotnet#103592
@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Jun 19, 2024
@PopSlime

PopSlime commented Jun 19, 2024

Copy link
Copy Markdown
ContributorAuthor

I'm new to such a big and complex project and not sure how to test these changes, so this is a draft at the moment. Looking forward to help from anyone.

Example affected patterns:

ICU patternResult (Old)Result (New)
a नि h:mmtt h:mmtt नि h:mm
ཆུ་ཚོད་h:mm:ss ah:mm:ss ttཆུ་ཚོད་h:mm:ss tt
ཆུ་ཚོད་ h སྐར་མ་ mm a h mm ttཆུ་ཚོད་ h སྐར་མ་ mm tt
Bh:mm:ssh:mm:sstth:mm:ss

More information can be found in the fixing issue.

@mkhamoyan

Copy link
Copy Markdown
Contributor

@mkhamoyan

Copy link
Copy Markdown
Contributor

/azp run runtime-extra-platforms

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@PopSlime

PopSlime commented Jun 19, 2024

Copy link
Copy Markdown
ContributorAuthor

@mkhamoyan I'm not sure how to write the test for this because the retrieved time format is device-/platform-dependent.

Instead of testing against some specific patterns, I'm considering adding a test that fails if a 12-hour clock is used without an AM/PM designator in any pattern in any culture. Also we need another test for the unquoted literal texts, which I have no clues how to do yet.

By the way, short time patterns are also affected by this PR.

@mkhamoyan

mkhamoyan commented Jun 19, 2024

Copy link
Copy Markdown
Contributor

@PopSlime I was thinking something like below (same test case for shorttime patterns under here) would validate the change.

[Theory]
[InlineData("zh-TW")]
[InlineData("en-US")]
[InlineData("fr-FR")]
public void LongTimePattern_ValidateAMPMDesignators(string cultureName)
{
var cultureInfo = new CultureInfo(cultureName);
var date = DateTime.Today + TimeSpan.FromDays(10) + TimeSpan.FromMinutes(10);
string formattedDateTime = date.ToString("T", cultureInfo);
Assert.True(formattedDateTime.Contains(cultureInfo.DateTimeFormat.AMDesignator));
}

This should be consistent for all platforms and devices.
Now we see issue only in some android devices because of different CLDR versions.

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

@mkhamoyan Is it safe to assume those cultures use a 12-hour clock? fr-FR uses a 24-hour clock on my side.

@mkhamoyan

Copy link
Copy Markdown
Contributor

@mkhamoyan Is it safe to assume those cultures use a 12-hour clock? fr-FR uses a 24-hour clock on my side.

My bad, fr-FR shouldn't be there.

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

How about this?

[Fact]publicvoidLongTimePattern_VerifyTimePatterns(){foreach(varcultureinCultureInfo.GetCultures(CultureTypes.AllCultures)){varpattern=culture.DateTimeFormat.LongTimePattern;varsegments=pattern.Split('\'');booluse12Hour=false;booluseAMPM=false;for(vari=0;i<segments.Length;i+=2){varsegment=segments[i];use12Hour|=segment.Contains('h',StringComparison.Ordinal);useAMPM|=segment.Contains('t',StringComparison.Ordinal);}Assert.True(!use12Hour||useAMPM,$"Bad time pattern for culture {culture.Name}: '{pattern}'");}}

By the way, this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'. Should we address this in another issue?

@mkhamoyan

Copy link
Copy Markdown
Contributor

How about this?

Looks good to me.

By the way, this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'. Should we address this in another issue?

Yes , we should file an issue for that.
Let's push in the PR and check how it behaves on other platforms.

@tarekgh
tarekgh self-requested a review June 19, 2024 16:06
Add tests verifying that all the short and long time patterns either use
a 24-hour clock or have an AM/PM designator.
@PopSlime

Copy link
Copy Markdown
ContributorAuthor

@dotnet-policy-service agree

@PopSlime
PopSlime marked this pull request as ready for review June 19, 2024 17:31
@tarekgh

Copy link
Copy Markdown
Member

By the way, this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'. Should we address this in another issue?
Yes , we should file an issue for that.

I don't think we can fix that as the patterns are picked from Windows. I suggest you mark your new test methods with the attribute and see if this can help?

[ConditionalFact(typeof(PlatformDetection),nameof(PlatformDetection.IsIcuGlobalization))]

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

I'll do that, but I also want to see if similar issues are occurring on other platforms, so let's wait for these checks to be done.

@tarekgh

tarekgh commented Jun 19, 2024

Copy link
Copy Markdown
Member

this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'.

I am trying on my machine, and I am not getting the same results you are getting.

mi-NZ .. Maori (New Zealand) .. h:mm tt .. h:mm:ss tt
mi .. Maori .. h:mm tt .. h:mm:ss tt

running code like:

varci=CultureInfo.GetCultureInfo("mi-NZ");Console.WriteLine($"{ci.Name} .. {ci.EnglishName} .. {ci.DateTimeFormat.ShortTimePattern} .. {ci.DateTimeFormat.LongTimePattern}");ci=CultureInfo.GetCultureInfo("mi");Console.WriteLine($"{ci.Name} .. {ci.EnglishName} .. {ci.DateTimeFormat.ShortTimePattern} .. {ci.DateTimeFormat.LongTimePattern}");

What Windows version do you have? I am wondering how you get this result?

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

It seems that the version of the CLDR data installed on my PC is below 36. The time format for mi was fixed in unicode-org/cldr#104.

  • Operating system: Windows 10
  • Version number: 22H2
  • Internal version: 19045.4529

@tarekgh

tarekgh commented Jun 19, 2024

Copy link
Copy Markdown
Member

ok, then the attribute

[ConditionalFact(typeof(PlatformDetection),nameof(PlatformDetection.IsIcuGlobalization))]
is not going to help. You may try using something like
if(PlatformDetection.WindowsVersion>=10||PlatformDetection.ICUVersion.Major>=55||PlatformDetection.IsHybridGlobalizationOnApplePlatform)
to avoid the failure.

I meant using check like if (PlatformDetection.ICUVersion.Major >= 68) .

@ilonatommy

Copy link
Copy Markdown
Member

@PopSlime the tests are still failing. For now, can you exclude running this test with hype globalization? or special case fr-CA when encountering it? @ilonatommy@mkhamoyan do you have any better suggestion? @PopSlime already logged issue to tracking fixing fr-CA formats.

Current behavior was expected and other HybridGlobalization tests are prepared for that. I am looking if we can provide a generic fix. For now this test can be blocked with PlatformDetection.IsNotHybridGlobalizationOnBrowser. The fix can get in in a separate PR

@mkhamoyan

Copy link
Copy Markdown
Contributor

/azp run runtime-ioslike,runtime-ioslikesimulator,runtime-maccatalyst

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 3 pipeline(s).

@mkhamoyanmkhamoyan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.
Let's wait for ios pipelines and then we can merge.

@mkhamoyan

Copy link
Copy Markdown
Contributor

/azp run runtime-ioslike,runtime-ioslikesimulator,runtime-maccatalyst

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 3 pipeline(s).

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime

@azure-pipelines

Copy link
Copy Markdown
Commenter does not have sufficient privileges for PR 103681 in repo dotnet/runtime

@ilonatommy

Copy link
Copy Markdown
Member

/azp run runtime

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@tarekgh
tarekgh merged commit 4b9a1b2 into dotnet:mainJun 21, 2024
rzikm pushed a commit to rzikm/dotnet-runtime that referenced this pull request Jun 24, 2024
* Fix the ICU time format conversion logic
Revise the ICU time format conversion logic to support all unquoted literal texts and the `B` and `b` pattern symbols.
Fixdotnet#103592
* Clarify literal texts in the conversion logic
* Add tests for verifying time patterns
Add tests verifying that all the short and long time patterns either use
a 24-hour clock or have an AM/PM designator.
* Fix literal single quote and literal backslash conversion
* Refactor the literal quote conversion logic
* Revise the test logic to ignore literal texts and check pattern redundancy
Modify the test logic so that it recognizes literal texts correctly, and
fails if 12-hour and 24-hour clocks are used at the same time.
* Revise the test logic to ensure all cultures are tested
* Add comments to clarify the backslash conversion
* Refactor the conversion logic
Simplify some logic and improve readability.
* Exclude bad ICU patterns from the tests
* Exclude the VerifyTimePatterns tests from hybrid globalization on browser
* Add missing usings
* Improve readability of the for-loops
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 23, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Globalizationcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect general long time pattern for some cultures on Android

4 participants

@PopSlime@mkhamoyan@tarekgh@ilonatommy
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix the ICU time format conversion logic - #103681

Merged
tarekgh merged 13 commits into
dotnet:mainfrom
PopSlime:fix-icu-date-time-format-conversion
Jun 21, 2024
Merged

Fix the ICU time format conversion logic#103681
tarekgh merged 13 commits into
dotnet:mainfrom
PopSlime:fix-icu-date-time-format-conversion

Conversation

@PopSlime

Copy link
Copy Markdown
Contributor

Revise the ICU time format conversion logic to support all unquoted literal texts and the B and b pattern symbols.

Fix#103592

Revise the ICU time format conversion logic to support all unquoted literal texts and the `B` and `b` pattern symbols.
Fixdotnet#103592
@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Jun 19, 2024
@PopSlime

PopSlime commented Jun 19, 2024

Copy link
Copy Markdown
ContributorAuthor

I'm new to such a big and complex project and not sure how to test these changes, so this is a draft at the moment. Looking forward to help from anyone.

Example affected patterns:

ICU patternResult (Old)Result (New)
a नि h:mmtt h:mmtt नि h:mm
ཆུ་ཚོད་h:mm:ss ah:mm:ss ttཆུ་ཚོད་h:mm:ss tt
ཆུ་ཚོད་ h སྐར་མ་ mm a h mm ttཆུ་ཚོད་ h སྐར་མ་ mm tt
Bh:mm:ssh:mm:sstth:mm:ss

More information can be found in the fixing issue.

@mkhamoyan

Copy link
Copy Markdown
Contributor

@mkhamoyan

Copy link
Copy Markdown
Contributor

/azp run runtime-extra-platforms

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@PopSlime

PopSlime commented Jun 19, 2024

Copy link
Copy Markdown
ContributorAuthor

@mkhamoyan I'm not sure how to write the test for this because the retrieved time format is device-/platform-dependent.

Instead of testing against some specific patterns, I'm considering adding a test that fails if a 12-hour clock is used without an AM/PM designator in any pattern in any culture. Also we need another test for the unquoted literal texts, which I have no clues how to do yet.

By the way, short time patterns are also affected by this PR.

@mkhamoyan

mkhamoyan commented Jun 19, 2024

Copy link
Copy Markdown
Contributor

@PopSlime I was thinking something like below (same test case for shorttime patterns under here) would validate the change.

[Theory]
[InlineData("zh-TW")]
[InlineData("en-US")]
[InlineData("fr-FR")]
public void LongTimePattern_ValidateAMPMDesignators(string cultureName)
{
var cultureInfo = new CultureInfo(cultureName);
var date = DateTime.Today + TimeSpan.FromDays(10) + TimeSpan.FromMinutes(10);
string formattedDateTime = date.ToString("T", cultureInfo);
Assert.True(formattedDateTime.Contains(cultureInfo.DateTimeFormat.AMDesignator));
}

This should be consistent for all platforms and devices.
Now we see issue only in some android devices because of different CLDR versions.

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

@mkhamoyan Is it safe to assume those cultures use a 12-hour clock? fr-FR uses a 24-hour clock on my side.

@mkhamoyan

Copy link
Copy Markdown
Contributor

@mkhamoyan Is it safe to assume those cultures use a 12-hour clock? fr-FR uses a 24-hour clock on my side.

My bad, fr-FR shouldn't be there.

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

How about this?

[Fact]publicvoidLongTimePattern_VerifyTimePatterns(){foreach(varcultureinCultureInfo.GetCultures(CultureTypes.AllCultures)){varpattern=culture.DateTimeFormat.LongTimePattern;varsegments=pattern.Split('\'');booluse12Hour=false;booluseAMPM=false;for(vari=0;i<segments.Length;i+=2){varsegment=segments[i];use12Hour|=segment.Contains('h',StringComparison.Ordinal);useAMPM|=segment.Contains('t',StringComparison.Ordinal);}Assert.True(!use12Hour||useAMPM,$"Bad time pattern for culture {culture.Name}: '{pattern}'");}}

By the way, this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'. Should we address this in another issue?

@mkhamoyan

Copy link
Copy Markdown
Contributor

How about this?

Looks good to me.

By the way, this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'. Should we address this in another issue?

Yes , we should file an issue for that.
Let's push in the PR and check how it behaves on other platforms.

@tarekgh
tarekgh self-requested a review June 19, 2024 16:06
Add tests verifying that all the short and long time patterns either use
a 24-hour clock or have an AM/PM designator.
@PopSlime

Copy link
Copy Markdown
ContributorAuthor

@dotnet-policy-service agree

@PopSlime
PopSlime marked this pull request as ready for review June 19, 2024 17:31
@tarekgh

Copy link
Copy Markdown
Member

By the way, this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'. Should we address this in another issue?
Yes , we should file an issue for that.

I don't think we can fix that as the patterns are picked from Windows. I suggest you mark your new test methods with the attribute and see if this can help?

[ConditionalFact(typeof(PlatformDetection),nameof(PlatformDetection.IsIcuGlobalization))]

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

I'll do that, but I also want to see if similar issues are occurring on other platforms, so let's wait for these checks to be done.

@tarekgh

tarekgh commented Jun 19, 2024

Copy link
Copy Markdown
Member

this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'.

I am trying on my machine, and I am not getting the same results you are getting.

mi-NZ .. Maori (New Zealand) .. h:mm tt .. h:mm:ss tt
mi .. Maori .. h:mm tt .. h:mm:ss tt

running code like:

varci=CultureInfo.GetCultureInfo("mi-NZ");Console.WriteLine($"{ci.Name} .. {ci.EnglishName} .. {ci.DateTimeFormat.ShortTimePattern} .. {ci.DateTimeFormat.LongTimePattern}");ci=CultureInfo.GetCultureInfo("mi");Console.WriteLine($"{ci.Name} .. {ci.EnglishName} .. {ci.DateTimeFormat.ShortTimePattern} .. {ci.DateTimeFormat.LongTimePattern}");

What Windows version do you have? I am wondering how you get this result?

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

It seems that the version of the CLDR data installed on my PC is below 36. The time format for mi was fixed in unicode-org/cldr#104.

  • Operating system: Windows 10
  • Version number: 22H2
  • Internal version: 19045.4529

@tarekgh

tarekgh commented Jun 19, 2024

Copy link
Copy Markdown
Member

ok, then the attribute

[ConditionalFact(typeof(PlatformDetection),nameof(PlatformDetection.IsIcuGlobalization))]
is not going to help. You may try using something like
if(PlatformDetection.WindowsVersion>=10||PlatformDetection.ICUVersion.Major>=55||PlatformDetection.IsHybridGlobalizationOnApplePlatform)
to avoid the failure.

I meant using check like if (PlatformDetection.ICUVersion.Major >= 68) .

@ilonatommy

Copy link
Copy Markdown
Member

@PopSlime the tests are still failing. For now, can you exclude running this test with hype globalization? or special case fr-CA when encountering it? @ilonatommy@mkhamoyan do you have any better suggestion? @PopSlime already logged issue to tracking fixing fr-CA formats.

Current behavior was expected and other HybridGlobalization tests are prepared for that. I am looking if we can provide a generic fix. For now this test can be blocked with PlatformDetection.IsNotHybridGlobalizationOnBrowser. The fix can get in in a separate PR

@mkhamoyan

Copy link
Copy Markdown
Contributor

/azp run runtime-ioslike,runtime-ioslikesimulator,runtime-maccatalyst

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 3 pipeline(s).

@mkhamoyanmkhamoyan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.
Let's wait for ios pipelines and then we can merge.

@mkhamoyan

Copy link
Copy Markdown
Contributor

/azp run runtime-ioslike,runtime-ioslikesimulator,runtime-maccatalyst

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 3 pipeline(s).

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime

@azure-pipelines

Copy link
Copy Markdown
Commenter does not have sufficient privileges for PR 103681 in repo dotnet/runtime

@ilonatommy

Copy link
Copy Markdown
Member

/azp run runtime

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@tarekgh
tarekgh merged commit 4b9a1b2 into dotnet:mainJun 21, 2024
rzikm pushed a commit to rzikm/dotnet-runtime that referenced this pull request Jun 24, 2024
* Fix the ICU time format conversion logic
Revise the ICU time format conversion logic to support all unquoted literal texts and the `B` and `b` pattern symbols.
Fixdotnet#103592
* Clarify literal texts in the conversion logic
* Add tests for verifying time patterns
Add tests verifying that all the short and long time patterns either use
a 24-hour clock or have an AM/PM designator.
* Fix literal single quote and literal backslash conversion
* Refactor the literal quote conversion logic
* Revise the test logic to ignore literal texts and check pattern redundancy
Modify the test logic so that it recognizes literal texts correctly, and
fails if 12-hour and 24-hour clocks are used at the same time.
* Revise the test logic to ensure all cultures are tested
* Add comments to clarify the backslash conversion
* Refactor the conversion logic
Simplify some logic and improve readability.
* Exclude bad ICU patterns from the tests
* Exclude the VerifyTimePatterns tests from hybrid globalization on browser
* Add missing usings
* Improve readability of the for-loops
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 23, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Globalizationcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect general long time pattern for some cultures on Android

4 participants

@PopSlime@mkhamoyan@tarekgh@ilonatommy
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Fix the ICU time format conversion logic - #103681

Merged
tarekgh merged 13 commits into
dotnet:mainfrom
PopSlime:fix-icu-date-time-format-conversion
Jun 21, 2024
Merged

Fix the ICU time format conversion logic#103681
tarekgh merged 13 commits into
dotnet:mainfrom
PopSlime:fix-icu-date-time-format-conversion

Conversation

@PopSlime

Copy link
Copy Markdown
Contributor

Revise the ICU time format conversion logic to support all unquoted literal texts and the B and b pattern symbols.

Fix#103592

Revise the ICU time format conversion logic to support all unquoted literal texts and the `B` and `b` pattern symbols.
Fixdotnet#103592
@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Jun 19, 2024
@PopSlime

PopSlime commented Jun 19, 2024

Copy link
Copy Markdown
ContributorAuthor

I'm new to such a big and complex project and not sure how to test these changes, so this is a draft at the moment. Looking forward to help from anyone.

Example affected patterns:

ICU patternResult (Old)Result (New)
a नि h:mmtt h:mmtt नि h:mm
ཆུ་ཚོད་h:mm:ss ah:mm:ss ttཆུ་ཚོད་h:mm:ss tt
ཆུ་ཚོད་ h སྐར་མ་ mm a h mm ttཆུ་ཚོད་ h སྐར་མ་ mm tt
Bh:mm:ssh:mm:sstth:mm:ss

More information can be found in the fixing issue.

@mkhamoyan

Copy link
Copy Markdown
Contributor

@mkhamoyan

Copy link
Copy Markdown
Contributor

/azp run runtime-extra-platforms

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@PopSlime

PopSlime commented Jun 19, 2024

Copy link
Copy Markdown
ContributorAuthor

@mkhamoyan I'm not sure how to write the test for this because the retrieved time format is device-/platform-dependent.

Instead of testing against some specific patterns, I'm considering adding a test that fails if a 12-hour clock is used without an AM/PM designator in any pattern in any culture. Also we need another test for the unquoted literal texts, which I have no clues how to do yet.

By the way, short time patterns are also affected by this PR.

@mkhamoyan

mkhamoyan commented Jun 19, 2024

Copy link
Copy Markdown
Contributor

@PopSlime I was thinking something like below (same test case for shorttime patterns under here) would validate the change.

[Theory]
[InlineData("zh-TW")]
[InlineData("en-US")]
[InlineData("fr-FR")]
public void LongTimePattern_ValidateAMPMDesignators(string cultureName)
{
var cultureInfo = new CultureInfo(cultureName);
var date = DateTime.Today + TimeSpan.FromDays(10) + TimeSpan.FromMinutes(10);
string formattedDateTime = date.ToString("T", cultureInfo);
Assert.True(formattedDateTime.Contains(cultureInfo.DateTimeFormat.AMDesignator));
}

This should be consistent for all platforms and devices.
Now we see issue only in some android devices because of different CLDR versions.

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

@mkhamoyan Is it safe to assume those cultures use a 12-hour clock? fr-FR uses a 24-hour clock on my side.

@mkhamoyan

Copy link
Copy Markdown
Contributor

@mkhamoyan Is it safe to assume those cultures use a 12-hour clock? fr-FR uses a 24-hour clock on my side.

My bad, fr-FR shouldn't be there.

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

How about this?

[Fact]publicvoidLongTimePattern_VerifyTimePatterns(){foreach(varcultureinCultureInfo.GetCultures(CultureTypes.AllCultures)){varpattern=culture.DateTimeFormat.LongTimePattern;varsegments=pattern.Split('\'');booluse12Hour=false;booluseAMPM=false;for(vari=0;i<segments.Length;i+=2){varsegment=segments[i];use12Hour|=segment.Contains('h',StringComparison.Ordinal);useAMPM|=segment.Contains('t',StringComparison.Ordinal);}Assert.True(!use12Hour||useAMPM,$"Bad time pattern for culture {culture.Name}: '{pattern}'");}}

By the way, this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'. Should we address this in another issue?

@mkhamoyan

Copy link
Copy Markdown
Contributor

How about this?

Looks good to me.

By the way, this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'. Should we address this in another issue?

Yes , we should file an issue for that.
Let's push in the PR and check how it behaves on other platforms.

@tarekgh
tarekgh self-requested a review June 19, 2024 16:06
Add tests verifying that all the short and long time patterns either use
a 24-hour clock or have an AM/PM designator.
@PopSlime

Copy link
Copy Markdown
ContributorAuthor

@dotnet-policy-service agree

@PopSlime
PopSlime marked this pull request as ready for review June 19, 2024 17:31
@tarekgh

Copy link
Copy Markdown
Member

By the way, this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'. Should we address this in another issue?
Yes , we should file an issue for that.

I don't think we can fix that as the patterns are picked from Windows. I suggest you mark your new test methods with the attribute and see if this can help?

[ConditionalFact(typeof(PlatformDetection),nameof(PlatformDetection.IsIcuGlobalization))]

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

I'll do that, but I also want to see if similar issues are occurring on other platforms, so let's wait for these checks to be done.

@tarekgh

tarekgh commented Jun 19, 2024

Copy link
Copy Markdown
Member

this fails on my PC (Windows) with mi: 'h:mm:ss' and mi-NZ: 'h:mm:ss'.

I am trying on my machine, and I am not getting the same results you are getting.

mi-NZ .. Maori (New Zealand) .. h:mm tt .. h:mm:ss tt
mi .. Maori .. h:mm tt .. h:mm:ss tt

running code like:

varci=CultureInfo.GetCultureInfo("mi-NZ");Console.WriteLine($"{ci.Name} .. {ci.EnglishName} .. {ci.DateTimeFormat.ShortTimePattern} .. {ci.DateTimeFormat.LongTimePattern}");ci=CultureInfo.GetCultureInfo("mi");Console.WriteLine($"{ci.Name} .. {ci.EnglishName} .. {ci.DateTimeFormat.ShortTimePattern} .. {ci.DateTimeFormat.LongTimePattern}");

What Windows version do you have? I am wondering how you get this result?

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

It seems that the version of the CLDR data installed on my PC is below 36. The time format for mi was fixed in unicode-org/cldr#104.

  • Operating system: Windows 10
  • Version number: 22H2
  • Internal version: 19045.4529

@tarekgh

tarekgh commented Jun 19, 2024

Copy link
Copy Markdown
Member

ok, then the attribute

[ConditionalFact(typeof(PlatformDetection),nameof(PlatformDetection.IsIcuGlobalization))]
is not going to help. You may try using something like
if(PlatformDetection.WindowsVersion>=10||PlatformDetection.ICUVersion.Major>=55||PlatformDetection.IsHybridGlobalizationOnApplePlatform)
to avoid the failure.

I meant using check like if (PlatformDetection.ICUVersion.Major >= 68) .

@ilonatommy

Copy link
Copy Markdown
Member

@PopSlime the tests are still failing. For now, can you exclude running this test with hype globalization? or special case fr-CA when encountering it? @ilonatommy@mkhamoyan do you have any better suggestion? @PopSlime already logged issue to tracking fixing fr-CA formats.

Current behavior was expected and other HybridGlobalization tests are prepared for that. I am looking if we can provide a generic fix. For now this test can be blocked with PlatformDetection.IsNotHybridGlobalizationOnBrowser. The fix can get in in a separate PR

@mkhamoyan

Copy link
Copy Markdown
Contributor

/azp run runtime-ioslike,runtime-ioslikesimulator,runtime-maccatalyst

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 3 pipeline(s).

@mkhamoyanmkhamoyan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.
Let's wait for ios pipelines and then we can merge.

@mkhamoyan

Copy link
Copy Markdown
Contributor

/azp run runtime-ioslike,runtime-ioslikesimulator,runtime-maccatalyst

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 3 pipeline(s).

@PopSlime

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime

@azure-pipelines

Copy link
Copy Markdown
Commenter does not have sufficient privileges for PR 103681 in repo dotnet/runtime

@ilonatommy

Copy link
Copy Markdown
Member

/azp run runtime

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@tarekgh
tarekgh merged commit 4b9a1b2 into dotnet:mainJun 21, 2024
rzikm pushed a commit to rzikm/dotnet-runtime that referenced this pull request Jun 24, 2024
* Fix the ICU time format conversion logic
Revise the ICU time format conversion logic to support all unquoted literal texts and the `B` and `b` pattern symbols.
Fixdotnet#103592
* Clarify literal texts in the conversion logic
* Add tests for verifying time patterns
Add tests verifying that all the short and long time patterns either use
a 24-hour clock or have an AM/PM designator.
* Fix literal single quote and literal backslash conversion
* Refactor the literal quote conversion logic
* Revise the test logic to ignore literal texts and check pattern redundancy
Modify the test logic so that it recognizes literal texts correctly, and
fails if 12-hour and 24-hour clocks are used at the same time.
* Revise the test logic to ensure all cultures are tested
* Add comments to clarify the backslash conversion
* Refactor the conversion logic
Simplify some logic and improve readability.
* Exclude bad ICU patterns from the tests
* Exclude the VerifyTimePatterns tests from hybrid globalization on browser
* Add missing usings
* Improve readability of the for-loops
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 23, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Globalizationcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect general long time pattern for some cultures on Android

4 participants

@PopSlime@mkhamoyan@tarekgh@ilonatommy