From 686e9ea3b51f83625f7ae04e3d12249acb4a5d51 Mon Sep 17 00:00:00 2001 From: bombipappoo Date: Fri, 12 Jun 2020 00:54:16 +0900 Subject: [PATCH 1/2] Add Calendar localization. --- .../CalendarFormatInfoTests.cs | 130 ++++++++ .../CalendarFormatInfo.cs | 282 ++++++++++++++++++ .../Converters/CalendarYearMonthConverter.cs | 31 ++ .../MaterialDateDisplay.cs | 13 +- .../Themes/MaterialDesignTheme.Calendar.xaml | 10 +- 5 files changed, 461 insertions(+), 5 deletions(-) create mode 100644 MaterialDesignThemes.Wpf.Tests/CalendarFormatInfoTests.cs create mode 100644 MaterialDesignThemes.Wpf/CalendarFormatInfo.cs create mode 100644 MaterialDesignThemes.Wpf/Converters/CalendarYearMonthConverter.cs diff --git a/MaterialDesignThemes.Wpf.Tests/CalendarFormatInfoTests.cs b/MaterialDesignThemes.Wpf.Tests/CalendarFormatInfoTests.cs new file mode 100644 index 0000000000..369e1848bf --- /dev/null +++ b/MaterialDesignThemes.Wpf.Tests/CalendarFormatInfoTests.cs @@ -0,0 +1,130 @@ +using System.Globalization; +using Xunit; + +namespace MaterialDesignThemes.Wpf.Tests +{ + public class CalendarFormatInfoTests + { + [StaTheory] + [InlineData("en-US", "MMMM yyyy", "yyyy", "ddd,", "MMM d")] + [InlineData("fr-CA", "MMMM, yyyy", "yyyy", "ddd", "d MMM")] + [InlineData("ja-JP", "yyyy'年'M'月'", "yyyy年", "M月d日", "dddd")] + public void TestFromCultureInfo(string cultureName, string yearMonth, string componentThree, string componentTwo, string componentOne) + { + var result = CalendarFormatInfo.FromCultureInfo(CultureInfo.GetCultureInfo(cultureName)); + + Assert.Equal(yearMonth, result.YearMonthPattern); + Assert.Equal(componentOne, result.ComponentOnePattern); + Assert.Equal(componentTwo, result.ComponentTwoPattern); + Assert.Equal(componentThree, result.ComponentThreePattern); + } + + [Theory] + [InlineData("", "ddd", "", true)] + [InlineData("ddd", "ddd", "", true)] + [InlineData("dddd", "ddd", "", true)] + [InlineData("dddd ", "ddd", "", true)] + [InlineData("dddd,", "ddd", ",", true)] + [InlineData("dddd ,", "ddd", ",", true)] + [InlineData("dddd','", "ddd", ",", true)] + [InlineData("dddd' , '", "ddd", ",", true)] + [InlineData("ddddd", "ddd", "", true)] + [InlineData("ddddd,", "ddd", "", true)] + [InlineData("Xddd", "ddd", "", false)] + [InlineData("Xdddd", "ddd", "", false)] + [InlineData("X ddd", "ddd", "", false)] + [InlineData("X dddd", "ddd", "", false)] + [InlineData("X, ddd", "ddd", ",", false)] + [InlineData("X,ddd", "ddd", ",", false)] + [InlineData("X','ddd", "ddd", ",", false)] + [InlineData("X' , 'ddd", "ddd", ",", false)] + [InlineData("Xddddd", "ddd", "", false)] + [InlineData("X,ddddd", "ddd", "", false)] + public void CanParseDayOfWeek(string s, string pattern, string separator, bool isFirst) + { + var result = CalendarFormatInfo.DayOfWeekStyle.Parse(s); + + Assert.Equal(pattern, result.Pattern); + Assert.Equal(separator, result.Separator); + Assert.Equal(isFirst, result.IsFirst); + } + + [StaFact] + public void SettingYearPattern() + { + const string cultureName = "en-001"; + CalendarFormatInfo.SetYearPattern(cultureName, "A"); + var result = CalendarFormatInfo.FromCultureInfo(CultureInfo.GetCultureInfo(cultureName)); + Assert.Equal("A", result.ComponentThreePattern); + + CalendarFormatInfo.SetYearPattern(cultureName, null); + result = CalendarFormatInfo.FromCultureInfo(CultureInfo.GetCultureInfo(cultureName)); + Assert.Equal("yyyy", result.ComponentThreePattern); + } + + [StaFact] + public void SettingYearPatternOfMultupleCultures() + { + string[] cultureNames = { "en-001", "en-150" }; + CalendarFormatInfo.SetYearPattern(cultureNames, "B"); + foreach (var cultureName in cultureNames) + { + var result = CalendarFormatInfo.FromCultureInfo(CultureInfo.GetCultureInfo(cultureName)); + Assert.Equal("B", result.ComponentThreePattern); + } + } + + [StaFact] + public void SettingDayOfWeekStyle() + { + const string cultureName = "en-001"; + CalendarFormatInfo.SetDayOfWeekStyle(cultureName, new CalendarFormatInfo.DayOfWeekStyle("Z", "@", true)); + var result = CalendarFormatInfo.FromCultureInfo(CultureInfo.GetCultureInfo(cultureName)); + Assert.Equal("d MMM", result.ComponentOnePattern); + Assert.Equal("Z@", result.ComponentTwoPattern); + + CalendarFormatInfo.SetDayOfWeekStyle(cultureName, new CalendarFormatInfo.DayOfWeekStyle("Y", "@", false)); + result = CalendarFormatInfo.FromCultureInfo(CultureInfo.GetCultureInfo(cultureName)); + Assert.Equal("Y", result.ComponentOnePattern); + Assert.Equal("d MMM@", result.ComponentTwoPattern); + } + + [StaFact] + public void SettingDayOfWeekStyleOfMultupleCultures() + { + string[] cultureNames = { "en-001", "en-150" }; + CalendarFormatInfo.SetDayOfWeekStyle(cultureNames, new CalendarFormatInfo.DayOfWeekStyle("Z", "@", true)); + foreach (var cultureName in cultureNames) + { + var result = CalendarFormatInfo.FromCultureInfo(CultureInfo.GetCultureInfo(cultureName)); + Assert.Equal("d MMM", result.ComponentOnePattern); + Assert.Equal("Z@", result.ComponentTwoPattern); + } + } + + [StaFact] + public void ResettingDayOfWeekStyle() + { + const string cultureName = "en-001"; + CalendarFormatInfo.SetDayOfWeekStyle(cultureName, new CalendarFormatInfo.DayOfWeekStyle("Z", "@", true)); + CalendarFormatInfo.ResetDayOfWeekStyle(cultureName); + var result = CalendarFormatInfo.FromCultureInfo(CultureInfo.GetCultureInfo(cultureName)); + Assert.Equal("d MMM", result.ComponentOnePattern); + Assert.Equal("ddd,", result.ComponentTwoPattern); + } + + [StaFact] + public void ResettingDayOfWeekStyleOfMultupleCultures() + { + string[] cultureNames = { "en-001", "en-150" }; + CalendarFormatInfo.SetDayOfWeekStyle(cultureNames, new CalendarFormatInfo.DayOfWeekStyle("Z", "@", true)); + CalendarFormatInfo.ResetDayOfWeekStyle(cultureNames); + foreach (var cultureName in cultureNames) + { + var result = CalendarFormatInfo.FromCultureInfo(CultureInfo.GetCultureInfo(cultureName)); + Assert.Equal("d MMM", result.ComponentOnePattern); + Assert.Equal("ddd,", result.ComponentTwoPattern); + } + } + } +} diff --git a/MaterialDesignThemes.Wpf/CalendarFormatInfo.cs b/MaterialDesignThemes.Wpf/CalendarFormatInfo.cs new file mode 100644 index 0000000000..a4fd40159a --- /dev/null +++ b/MaterialDesignThemes.Wpf/CalendarFormatInfo.cs @@ -0,0 +1,282 @@ +using System; +using System.Collections.Generic; +using System.Globalization; + +namespace MaterialDesignThemes.Wpf +{ + /// + /// Provides culture-specific information about the format of calendar. + /// + public class CalendarFormatInfo + { + /// + /// Gets the custom format string for a year and month value. + /// + public string YearMonthPattern { get; } + + /// + /// Gets the custom format string for a component one value. + /// + public string ComponentOnePattern { get; } + + /// + /// Gets the custom format string for a component two value. + /// + public string ComponentTwoPattern { get; } + + /// + /// Gets the custom format string for a component three value. + /// + public string ComponentThreePattern { get; } + + private const string ShortDayOfWeek = "ddd"; + private const string LongDayOfWeek = "dddd"; + + private static readonly Dictionary _formatInfoCache = new Dictionary(); + private static readonly Dictionary _cultureYearPatterns = new Dictionary(); + private static readonly Dictionary _cultureDayOfWeekStyles = new Dictionary(); + + private static readonly string[] JapaneseCultureNames = { "ja", "ja-JP" }; + private static readonly string[] ZhongwenCultureNames = { "zh", "zh-CN", "zh-Hans", "zh-Hans-HK", "zh-Hans-MO", "zh-Hant", "zh-HK", "zh-MO", "zh-SG", "zh-TW" }; + private static readonly string[] KoreanCultureNames = { "ko", "ko-KR", "ko-KP" }; + + private const string CJKYearSuffix = "\u5e74"; + private const string KoreanYearSuffix = "\ub144"; + + static CalendarFormatInfo() + { + SetYearPattern(JapaneseCultureNames, "yyyy" + CJKYearSuffix); + SetYearPattern(ZhongwenCultureNames, "yyyy" + CJKYearSuffix); + SetYearPattern(KoreanCultureNames, "yyyy" + KoreanYearSuffix); + + var dayOfWeekStyle = new DayOfWeekStyle(LongDayOfWeek, string.Empty, false); + SetDayOfWeekStyle(JapaneseCultureNames, dayOfWeekStyle); + SetDayOfWeekStyle(ZhongwenCultureNames, dayOfWeekStyle); + } + + /// + /// Sets the culture-specific custom format string for a year value. + /// + /// An array of string that specify the name of culture to set the for. + /// The custom format string for a year value. If null, culture-specific custom format string for a year value is removed. + /// is null. + public static void SetYearPattern(string[] cultureNames, string yearPattern) + { + if (cultureNames == null) + throw new ArgumentNullException(nameof(cultureNames)); + + foreach (var cultureName in cultureNames) + SetYearPattern(cultureName, yearPattern); + } + + /// + /// Sets the culture-specific custom format string for a year value. + /// + /// A string that specify the name of culture to set the for. + /// The custom format string for a year value. If null, culture-specific custom format string for a year value is removed. + /// is null. + public static void SetYearPattern(string cultureName, string yearPattern) + { + if (cultureName == null) + throw new ArgumentNullException(nameof(cultureName)); + + if (yearPattern != null) + _cultureYearPatterns[cultureName] = yearPattern; + else + _cultureYearPatterns.Remove(cultureName); + DiscardFormatInfoCache(cultureName); + } + + /// + /// Sets the culture-specific day of week style. + /// + /// An array of string that specify the name of culture to set the for. + /// A to be set. + /// is null. + public static void SetDayOfWeekStyle(string[] cultureNames, DayOfWeekStyle dayOfWeekStyle) + { + if (cultureNames == null) + throw new ArgumentNullException(nameof(cultureNames)); + + foreach (var cultureName in cultureNames) + SetDayOfWeekStyle(cultureName, dayOfWeekStyle); + } + + /// + /// Sets the culture-specific day of week style. + /// + /// A string that specify the name of culture to set the for. + /// A to be set. + /// is null. + public static void SetDayOfWeekStyle(string cultureName, DayOfWeekStyle dayOfWeekStyle) + { + if (cultureName == null) + throw new ArgumentNullException(nameof(cultureName)); + + _cultureDayOfWeekStyles[cultureName] = dayOfWeekStyle; + DiscardFormatInfoCache(cultureName); + } + + /// + /// Resets the culture-specific day of week style to default value. + /// + /// An array of string that specify the name of culture to reset. + /// is null. + public static void ResetDayOfWeekStyle(string[] cultureNames) + { + if (cultureNames == null) + throw new ArgumentNullException(nameof(cultureNames)); + + foreach (var cultureName in cultureNames) + ResetDayOfWeekStyle(cultureName); + } + + /// + /// Resets the culture-specific day of week style to default value. + /// + /// A string that specify the name of culture to reset. + /// is null. + public static void ResetDayOfWeekStyle(string cultureName) + { + if (cultureName == null) + throw new ArgumentNullException(nameof(cultureName)); + + if (_cultureDayOfWeekStyles.Remove(cultureName)) + DiscardFormatInfoCache(cultureName); + } + + private static void DiscardFormatInfoCache(string cultureName) + { + _formatInfoCache.Remove(cultureName); + } + + private CalendarFormatInfo(string yearMonthPattern, string componentOnePattern, string componentTwoPattern, string componentThreePattern) + { + YearMonthPattern = yearMonthPattern; + ComponentOnePattern = componentOnePattern; + ComponentTwoPattern = componentTwoPattern; + ComponentThreePattern = componentThreePattern; + } + + /// + /// Creates a from the . + /// + /// A that specifies the culture to get the date format. + /// The object that this method creates. + /// is null. + public static CalendarFormatInfo FromCultureInfo(CultureInfo cultureInfo) + { + if (cultureInfo == null) + throw new ArgumentNullException(nameof(cultureInfo)); + + CalendarFormatInfo calendarInfo; + if (_formatInfoCache.TryGetValue(cultureInfo.Name, out calendarInfo)) + return calendarInfo; + + var dateTimeFormat = cultureInfo.DateTimeFormat; + + string yearPattern; + if (!_cultureYearPatterns.TryGetValue(cultureInfo.Name, out yearPattern)) + yearPattern = "yyyy"; + + DayOfWeekStyle dayOfWeekStyle; + if (!_cultureDayOfWeekStyles.TryGetValue(cultureInfo.Name, out dayOfWeekStyle)) + dayOfWeekStyle = DayOfWeekStyle.Parse(dateTimeFormat.LongDatePattern); + + var monthDayPattern = dateTimeFormat.MonthDayPattern.Replace("MMMM", "MMM"); + if (dayOfWeekStyle.IsFirst) + calendarInfo = new CalendarFormatInfo(dateTimeFormat.YearMonthPattern, + monthDayPattern, + dayOfWeekStyle.Pattern + dayOfWeekStyle.Separator, + yearPattern); + else + calendarInfo = new CalendarFormatInfo(dateTimeFormat.YearMonthPattern, + dayOfWeekStyle.Pattern, + monthDayPattern + dayOfWeekStyle.Separator, + yearPattern); + + _formatInfoCache[cultureInfo.Name] = calendarInfo; + return calendarInfo; + } + + /// + /// Represents a day of week style. + /// + public struct DayOfWeekStyle + { + /// + /// Gets the custom format string for a day of week value. + /// + public string Pattern { get; } + + /// + /// Gets the string that separates MonthDay and DayOfWeek. + /// + public string Separator { get; } + + /// + /// Gets a value indicating whether DayOfWeek is before MonthDay. + /// + public bool IsFirst { get; } + + private const char EthiopicWordspace = '\u1361'; + private const char EthiopicComma = '\u1363'; + private const char EthiopicColon = '\u1365'; + private const char ArabicComma = '\u060c'; + + private static readonly string SeparatorChars = + new string(new char[] { ',', ArabicComma, EthiopicWordspace, EthiopicComma, EthiopicColon }); + + /// + /// Initializes a new instance of the struct. + /// + /// A custom format string for a day of week value. + /// A string that separates MonthDay and DayOfWeek. + /// A value indicating whether DayOfWeek is before MonthDay. + public DayOfWeekStyle(string pattern, string separator, bool isFirst) + { + this.Pattern = pattern ?? string.Empty; + this.Separator = separator ?? string.Empty; + this.IsFirst = isFirst; + } + + /// + /// Extracts the from the date format string. + /// + /// the date format string. + /// The struct. + /// is null. + public static DayOfWeekStyle Parse(string s) + { + if (s == null) + throw new ArgumentNullException(nameof(s)); + + if (s.StartsWith(ShortDayOfWeek, StringComparison.Ordinal)) + { + var index = 3; + if (index < s.Length && s[index] == 'd') + index++; + for (; index < s.Length && IsSpace(s[index]); index++) + ; + var separator = index < s.Length && IsSeparator(s[index]) ? s[index].ToString() : string.Empty; + return new DayOfWeekStyle(ShortDayOfWeek, separator, true); + } + else if (s.EndsWith(ShortDayOfWeek, StringComparison.Ordinal)) + { + var index = s.Length - 4; + if (index >= 0 && s[index] == 'd') + index--; + for (; index >= 0 && IsSpace(s[index]); index--) + ; + var separator = index >= 0 && IsSeparator(s[index]) ? s[index].ToString() : string.Empty; + return new DayOfWeekStyle(ShortDayOfWeek, separator, false); + } + return new DayOfWeekStyle(ShortDayOfWeek, string.Empty, true); + } + + private static bool IsSpace(char c) => c == ' ' || c == '\''; + + private static bool IsSeparator(char c) => SeparatorChars.IndexOf(c) >= 0; + } + } +} diff --git a/MaterialDesignThemes.Wpf/Converters/CalendarYearMonthConverter.cs b/MaterialDesignThemes.Wpf/Converters/CalendarYearMonthConverter.cs new file mode 100644 index 0000000000..fd4a5721f1 --- /dev/null +++ b/MaterialDesignThemes.Wpf/Converters/CalendarYearMonthConverter.cs @@ -0,0 +1,31 @@ +using System; +using System.Globalization; +using System.Windows.Data; +using System.Windows.Markup; + +namespace MaterialDesignThemes.Wpf.Converters +{ + public sealed class CalendarYearMonthConverter: IMultiValueConverter + { + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + long ticks = long.MaxValue; + foreach (var value in values) + { + if (value is DateTime dt) + ticks = dt.Ticks; + else if (value is XmlLanguage language) + culture = language.GetSpecificCulture(); + } + if (ticks == long.MaxValue) + return null; + + return new DateTime(ticks).ToString(CalendarFormatInfo.FromCultureInfo(culture).YearMonthPattern, culture); + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/MaterialDesignThemes.Wpf/MaterialDateDisplay.cs b/MaterialDesignThemes.Wpf/MaterialDateDisplay.cs index cdb8d784c3..432f2fb7db 100644 --- a/MaterialDesignThemes.Wpf/MaterialDateDisplay.cs +++ b/MaterialDesignThemes.Wpf/MaterialDateDisplay.cs @@ -130,9 +130,16 @@ private void UpdateComponents() return; } - ComponentOneContent = DisplayDate.ToString(dateTimeFormatInfo.MonthDayPattern.Replace("MMMM", "MMM"), culture).ToTitleCase(culture); //Day Month following culture order. We don't want the month to take too much space - ComponentTwoContent = DisplayDate.ToString("ddd,", culture).ToTitleCase(culture); // Day of week first - ComponentThreeContent = DisplayDate.ToString("yyyy", culture).ToTitleCase(culture); // Year always top + var calendarFormatInfo = CalendarFormatInfo.FromCultureInfo(culture); + var displayDate = DisplayDate; + ComponentOneContent = FormatDate(calendarFormatInfo.ComponentOnePattern, displayDate, culture); + ComponentTwoContent = FormatDate(calendarFormatInfo.ComponentTwoPattern, displayDate, culture); + ComponentThreeContent = FormatDate(calendarFormatInfo.ComponentThreePattern, displayDate, culture); + } + + private static string FormatDate(string format, DateTime displayDate, CultureInfo culture) + { + return string.IsNullOrEmpty(format) ? string.Empty : displayDate.ToString(format, culture).ToTitleCase(culture); } private void SetDisplayDateOfCalendar(DateTime displayDate) diff --git a/MaterialDesignThemes.Wpf/Themes/MaterialDesignTheme.Calendar.xaml b/MaterialDesignThemes.Wpf/Themes/MaterialDesignTheme.Calendar.xaml index 29f27f7c30..b37b23d8b5 100644 --- a/MaterialDesignThemes.Wpf/Themes/MaterialDesignTheme.Calendar.xaml +++ b/MaterialDesignThemes.Wpf/Themes/MaterialDesignTheme.Calendar.xaml @@ -384,6 +384,7 @@ + @@ -413,8 +414,13 @@ FontSize="14" Grid.Row="1" Grid.Column="1" FontWeight="SemiBold" - RenderTransformOrigin="0, 0.5" - Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Calendar}}, Path=DisplayDate, StringFormat=MMMM yyyy}"> + RenderTransformOrigin="0, 0.5"> + + + + + + From e44cba42fb55cc4a2b84367cd446816782a6a873 Mon Sep 17 00:00:00 2001 From: Kevin Bost Date: Thu, 11 Jun 2020 22:20:32 -0700 Subject: [PATCH 2/2] Some minor code cleanup. --- .../CalendarFormatInfo.cs | 72 +++++++++++-------- 1 file changed, 42 insertions(+), 30 deletions(-) diff --git a/MaterialDesignThemes.Wpf/CalendarFormatInfo.cs b/MaterialDesignThemes.Wpf/CalendarFormatInfo.cs index a4fd40159a..364c0b2cc3 100644 --- a/MaterialDesignThemes.Wpf/CalendarFormatInfo.cs +++ b/MaterialDesignThemes.Wpf/CalendarFormatInfo.cs @@ -62,11 +62,13 @@ static CalendarFormatInfo() /// is null. public static void SetYearPattern(string[] cultureNames, string yearPattern) { - if (cultureNames == null) + if (cultureNames is null) throw new ArgumentNullException(nameof(cultureNames)); foreach (var cultureName in cultureNames) + { SetYearPattern(cultureName, yearPattern); + } } /// @@ -77,13 +79,17 @@ public static void SetYearPattern(string[] cultureNames, string yearPattern) /// is null. public static void SetYearPattern(string cultureName, string yearPattern) { - if (cultureName == null) + if (cultureName is null) throw new ArgumentNullException(nameof(cultureName)); if (yearPattern != null) + { _cultureYearPatterns[cultureName] = yearPattern; + } else + { _cultureYearPatterns.Remove(cultureName); + } DiscardFormatInfoCache(cultureName); } @@ -95,11 +101,13 @@ public static void SetYearPattern(string cultureName, string yearPattern) /// is null. public static void SetDayOfWeekStyle(string[] cultureNames, DayOfWeekStyle dayOfWeekStyle) { - if (cultureNames == null) + if (cultureNames is null) throw new ArgumentNullException(nameof(cultureNames)); foreach (var cultureName in cultureNames) + { SetDayOfWeekStyle(cultureName, dayOfWeekStyle); + } } /// @@ -110,7 +118,7 @@ public static void SetDayOfWeekStyle(string[] cultureNames, DayOfWeekStyle dayOf /// is null. public static void SetDayOfWeekStyle(string cultureName, DayOfWeekStyle dayOfWeekStyle) { - if (cultureName == null) + if (cultureName is null) throw new ArgumentNullException(nameof(cultureName)); _cultureDayOfWeekStyles[cultureName] = dayOfWeekStyle; @@ -124,11 +132,13 @@ public static void SetDayOfWeekStyle(string cultureName, DayOfWeekStyle dayOfWee /// is null. public static void ResetDayOfWeekStyle(string[] cultureNames) { - if (cultureNames == null) + if (cultureNames is null) throw new ArgumentNullException(nameof(cultureNames)); foreach (var cultureName in cultureNames) + { ResetDayOfWeekStyle(cultureName); + } } /// @@ -138,17 +148,17 @@ public static void ResetDayOfWeekStyle(string[] cultureNames) /// is null. public static void ResetDayOfWeekStyle(string cultureName) { - if (cultureName == null) + if (cultureName is null) throw new ArgumentNullException(nameof(cultureName)); if (_cultureDayOfWeekStyles.Remove(cultureName)) + { DiscardFormatInfoCache(cultureName); + } } private static void DiscardFormatInfoCache(string cultureName) - { - _formatInfoCache.Remove(cultureName); - } + => _ = _formatInfoCache.Remove(cultureName); private CalendarFormatInfo(string yearMonthPattern, string componentOnePattern, string componentTwoPattern, string componentThreePattern) { @@ -166,7 +176,7 @@ private CalendarFormatInfo(string yearMonthPattern, string componentOnePattern, /// is null. public static CalendarFormatInfo FromCultureInfo(CultureInfo cultureInfo) { - if (cultureInfo == null) + if (cultureInfo is null) throw new ArgumentNullException(nameof(cultureInfo)); CalendarFormatInfo calendarInfo; @@ -185,16 +195,19 @@ public static CalendarFormatInfo FromCultureInfo(CultureInfo cultureInfo) var monthDayPattern = dateTimeFormat.MonthDayPattern.Replace("MMMM", "MMM"); if (dayOfWeekStyle.IsFirst) + { calendarInfo = new CalendarFormatInfo(dateTimeFormat.YearMonthPattern, - monthDayPattern, - dayOfWeekStyle.Pattern + dayOfWeekStyle.Separator, - yearPattern); + monthDayPattern, + dayOfWeekStyle.Pattern + dayOfWeekStyle.Separator, + yearPattern); + } else + { calendarInfo = new CalendarFormatInfo(dateTimeFormat.YearMonthPattern, - dayOfWeekStyle.Pattern, - monthDayPattern + dayOfWeekStyle.Separator, - yearPattern); - + dayOfWeekStyle.Pattern, + monthDayPattern + dayOfWeekStyle.Separator, + yearPattern); + } _formatInfoCache[cultureInfo.Name] = calendarInfo; return calendarInfo; } @@ -219,13 +232,12 @@ public struct DayOfWeekStyle /// public bool IsFirst { get; } - private const char EthiopicWordspace = '\u1361'; - private const char EthiopicComma = '\u1363'; - private const char EthiopicColon = '\u1365'; - private const char ArabicComma = '\u060c'; + private const string EthiopicWordspace = "\u1361"; + private const string EthiopicComma = "\u1363"; + private const string EthiopicColon = "\u1365"; + private const string ArabicComma = "\u060c"; - private static readonly string SeparatorChars = - new string(new char[] { ',', ArabicComma, EthiopicWordspace, EthiopicComma, EthiopicColon }); + private const string SeparatorChars = "," + ArabicComma + EthiopicWordspace + EthiopicComma + EthiopicColon; /// /// Initializes a new instance of the struct. @@ -235,9 +247,9 @@ public struct DayOfWeekStyle /// A value indicating whether DayOfWeek is before MonthDay. public DayOfWeekStyle(string pattern, string separator, bool isFirst) { - this.Pattern = pattern ?? string.Empty; - this.Separator = separator ?? string.Empty; - this.IsFirst = isFirst; + Pattern = pattern ?? string.Empty; + Separator = separator ?? string.Empty; + IsFirst = isFirst; } /// @@ -248,7 +260,7 @@ public DayOfWeekStyle(string pattern, string separator, bool isFirst) /// is null. public static DayOfWeekStyle Parse(string s) { - if (s == null) + if (s is null) throw new ArgumentNullException(nameof(s)); if (s.StartsWith(ShortDayOfWeek, StringComparison.Ordinal)) @@ -272,11 +284,11 @@ public static DayOfWeekStyle Parse(string s) return new DayOfWeekStyle(ShortDayOfWeek, separator, false); } return new DayOfWeekStyle(ShortDayOfWeek, string.Empty, true); - } - private static bool IsSpace(char c) => c == ' ' || c == '\''; + static bool IsSpace(char c) => c == ' ' || c == '\''; - private static bool IsSeparator(char c) => SeparatorChars.IndexOf(c) >= 0; + static bool IsSeparator(char c) => SeparatorChars.IndexOf(c) >= 0; + } } } }