Skip to content

Commit 27f73bc

Browse files
author
igorrylko
committed
fix: fix datettime formatting
1 parent 2e72d1b commit 27f73bc

2 files changed

Lines changed: 49 additions & 5 deletions

File tree

src/Rh.MessageFormat.CldrGenerator/Generators/LocaleDataCollector.DatePatterns.cs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,18 +91,33 @@ private async Task CollectDatePatternsAsync(Dictionary<string, LocaleData> local
9191
return icuPattern;
9292

9393
var result = icuPattern;
94-
result = Regex.Replace(result, @"y{5,}", "yyyy");
95-
result = Regex.Replace(result, @"y{4}", "yyyy");
96-
result = Regex.Replace(result, @"y{3}", "yyyy");
97-
result = Regex.Replace(result, @"y{2}", "yy");
98-
result = Regex.Replace(result, @"y{1}(?!y)", "yyyy");
94+
95+
// Remove ICU optional section markers [...] - keep the content, remove brackets
96+
result = Regex.Replace(result, @"\[([^\]]*)\]", "$1");
97+
98+
// Remove ICU numeric prefix '#' (used for non-padded numbers)
99+
result = Regex.Replace(result, @"#(?=[yMdHhms])", "");
100+
101+
// Convert year patterns: ICU y -> .NET y
102+
// Use a single regex to avoid double-replacement issues
103+
result = Regex.Replace(result, @"y+", m => m.Length == 2 ? "yy" : "yyyy");
104+
105+
// Convert day of week patterns
99106
result = Regex.Replace(result, @"E{4,}", "dddd");
100107
result = Regex.Replace(result, @"E{1,3}", "ddd");
101108
result = Regex.Replace(result, @"c{4,}", "dddd");
102109
result = Regex.Replace(result, @"c{1,3}", "ddd");
110+
111+
// Convert day period patterns
103112
result = Regex.Replace(result, @"a+", "tt");
113+
// ICU 'B' (flexible day period like "in the morning") -> .NET 'tt' (AM/PM)
114+
result = Regex.Replace(result, @"B+", "tt");
115+
116+
// Convert era patterns
104117
result = Regex.Replace(result, @"G{4,}", "gg");
105118
result = Regex.Replace(result, @"G{1,3}", "g");
119+
120+
// Convert standalone month patterns (L -> M)
106121
result = Regex.Replace(result, @"L{4,}", "MMMM");
107122
result = Regex.Replace(result, @"L{3}", "MMM");
108123
result = Regex.Replace(result, @"L{2}", "MM");

tests/Rh.MessageFormat.Tests/Ast/DateTimeTypeConversionTests.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,35 @@ public void Date_FromUnixMilliseconds_String_FormatsCorrectly()
123123
Assert.Contains("1", result); // January
124124
}
125125

126+
[Fact]
127+
public void Date_FromUnixMilliseconds_NoExtraZeroInYear()
128+
{
129+
// Verify that formatting doesn't add extra zeros before the year
130+
// 1704067200000 = January 1, 2024 00:00:00 UTC
131+
var args = new Dictionary<string, object?> { { "d", 1704067200000L } };
132+
133+
var result = _formatter.FormatMessage("{d, date, short}", args);
134+
135+
// Should be like "1/1/24" or "1/1/2024", NOT "1/1/02024"
136+
Assert.DoesNotContain("02024", result);
137+
Assert.DoesNotContain("002024", result);
138+
}
139+
140+
[Fact]
141+
public void Date_FromUnixMilliseconds_UkrainianLocale_NoExtraZeroInYear()
142+
{
143+
// Bug fix: Ukrainian locale was generating "dd.MM.yyyyy" instead of "dd.MM.yy"
144+
// This caused dates like "01.01.02024" instead of "01.01.24"
145+
var ukFormatter = new MessageFormatter("uk", TestOptions.WithCommonLocales());
146+
var args = new Dictionary<string, object?> { { "expiringDate", "1704067200000" } };
147+
148+
var result = ukFormatter.FormatMessage("{expiringDate, date, short}", args);
149+
150+
// Should be "01.01.24", NOT "01.01.02024"
151+
Assert.DoesNotContain("02024", result);
152+
Assert.Contains("24", result); // 2-digit year
153+
}
154+
126155
[Fact]
127156
public void Date_FromDateString_StillWorks()
128157
{

0 commit comments

Comments
 (0)