没有标点符号的希腊月份使用 Date.ParseExact 转换为日期
Greek month with no punctuation convert to Date using Date.ParseExact
我有一个希腊日期 "08 Ιουνιου 2021"
,我想将其转换为 Date
。这是不可能的,因为月份缺少一些标点符号。正确的月份是 "Ιουνίου"
,实际上通过下面的代码可以正常工作
var greek = new CultureInfo("el-GR").DateTimeFormat;
var dtFormat = DateTime.ParseExact("08 Ιουνίου 2021", "dd' 'MMMM' 'yyyy", greek, DateTimeStyles.None);
关于如何正确设置月份格式的任何想法?
我不知道这里问题的确切扩展 - 这些值是否来自数据库,或者这是否只是一次出现,或者是否需要比最初建立的更多 -
想法是在变音符号(在本例中为月)和非变音符号之间创建映射。
传递日期值 08 Ιουνιου 2021
后,我们会根据包含变音符号的月份映射对其进行检查。
比较由
完成
string.Compare(firstString, secondString, new CultureInfo("el-GR"), CompareOptions.IgnoreNonSpace);
来自 Msdn 文档 - IgnoreNonSpace:
表示字符串比较必须忽略非间距组合字符,如变音符号。 Unicode 标准将组合字符定义为与基本字符组合以产生新字符的字符。非间距组合字符在呈现时不会自行占据间距位置。
这 could/would 是一个潜在的修复方法:
static string originalValue = "08 Ιουνιου 2021";
static string[] currentMonth = originalValue.Split(' ');
static List<string> monthMapping = new List<string>
{
//add others months mapping - I dont know how they are spelt -
"Ιουνίου"
};
static void Main(string[] args)
{
DateTimeFormatInfo greek = new CultureInfo("el-GR").DateTimeFormat;
foreach (string month in monthMapping)
{
if( string.Compare(currentMonth[1], month, new CultureInfo("el-GR") , CompareOptions.IgnoreNonSpace) == 0)
{
var dtFormat = DateTime.ParseExact($"08 {month} 2021", "dd' 'MMMM' 'yyyy", greek, DateTimeStyles.None);
}
}
}
您可以尝试规范化月份名称,使用不区分变音符号的比较从 CultureInfo.DateTimeFormat.MonthGenitiveNames 集合中检索正确的月份名称,因为在某些文化中,属格名称与主格名称不同(日期是以以下形式呈现:8th of June, 2021
).
一个String.Compare() overload accepts both CultureInfo and CompareOptions个参数。
IgnoreNonSpace
标志:表示字符串比较必须忽略非间距组合字符,例如变音符号。 [...]。
这允许在 MonthGenitiveNames
集合和 return 相应的专有名称中搜索月份名称,忽略缺失的变音符号。
然后可以将 标准化的 日期与提供的 CultureInfo 一起传递给 DateTime.TryParse(),以提取 DateTime 对象。
示例方法调用:
var normalizedDateTime = NormalizeMonthDiacritics(new CultureInfo("el-GR"), "08 Ιουνιου 2021");
using System.Globalization;
using System.Linq;
internal DateTime NormalizeMonthDiacritics(CultureInfo culture, string date)
{
string[] inputDateParts = date.Split();
inputDateParts[1] = culture.DateTimeFormat.MonthGenitiveNames.FirstOrDefault(month =>
string.Compare(inputDateParts[1], month, culture, CompareOptions.IgnoreNonSpace) == 0)
?? inputDateParts[1];
string normalizedDate = string.Join(" ", inputDateParts);
if (DateTime.TryParse(normalizedDate, culture, DateTimeStyles.None, out DateTime dtm)) {
return dtm;
}
else {
throw new ArgumentException("The provided date cannot be normalized",
new Exception("Month Genitive form not available"));
}
}
由于至少有 37 种文化使用由 2 个或更多部分组成的月份名称,为了使该方法更通用并将相同的过程应用于 Abbreviated Month Genitive 名称,可以修改此方法以解析输入日期的方式略有不同,还允许指定是否以短格式提供月份名称。
日期格式可以由这三部分组成:
- 代表月中日或年的数值
- 月份部分,属名,长格式字符串 (
MMMM
) 或短格式字符串 (MMM
)
- 表示年或月日的数值
DateTime.TryParse()
可以用两种方式处理 DateTime 格式。
像这样调用这个修改后的方法:
var culture = new CultureInfo("sah-RU");
string date = "2020 атырдьах ыиын 08"; // <= Should be атырдьах ыйын
var normalizedDateTime = NormalizeMonthDiacritics(culture, date, false);
修改方法:
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
internal DateTime NormalizeMonthDiacritics(CultureInfo culture, string date, bool monthShortForm = false)
{
string pattern = @"(\d+)\s+(.*?)\s+(\d+)";
var parts = Regex.Match(date, pattern, RegexOptions.CultureInvariant | RegexOptions.Singleline)
.Groups.OfType<Capture>().Skip(1).Take(3).Select(c => c.Value).ToArray();
var monthNames = monthShortForm
? culture.DateTimeFormat.AbbreviatedMonthGenitiveNames
: culture.DateTimeFormat.MonthGenitiveNames;
parts[1] = monthNames.FirstOrDefault(month =>
string.Compare(parts[1], month, culture, CompareOptions.IgnoreNonSpace) == 0)
?? parts[1];
string normalizedDate = string.Join(" ", parts);
if (DateTime.TryParse(normalizedDate, culture, DateTimeStyles.None, out DateTime dtm)) {
return dtm;
}
else {
throw new ArgumentException("The provided date cannnot be normalized",
new Exception("Month Genitive form not available"));
}
}
我有一个希腊日期 "08 Ιουνιου 2021"
,我想将其转换为 Date
。这是不可能的,因为月份缺少一些标点符号。正确的月份是 "Ιουνίου"
,实际上通过下面的代码可以正常工作
var greek = new CultureInfo("el-GR").DateTimeFormat;
var dtFormat = DateTime.ParseExact("08 Ιουνίου 2021", "dd' 'MMMM' 'yyyy", greek, DateTimeStyles.None);
关于如何正确设置月份格式的任何想法?
我不知道这里问题的确切扩展 - 这些值是否来自数据库,或者这是否只是一次出现,或者是否需要比最初建立的更多 -
想法是在变音符号(在本例中为月)和非变音符号之间创建映射。
传递日期值 08 Ιουνιου 2021
后,我们会根据包含变音符号的月份映射对其进行检查。
比较由
完成string.Compare(firstString, secondString, new CultureInfo("el-GR"), CompareOptions.IgnoreNonSpace);
来自 Msdn 文档 - IgnoreNonSpace:
表示字符串比较必须忽略非间距组合字符,如变音符号。 Unicode 标准将组合字符定义为与基本字符组合以产生新字符的字符。非间距组合字符在呈现时不会自行占据间距位置。
这 could/would 是一个潜在的修复方法:
static string originalValue = "08 Ιουνιου 2021";
static string[] currentMonth = originalValue.Split(' ');
static List<string> monthMapping = new List<string>
{
//add others months mapping - I dont know how they are spelt -
"Ιουνίου"
};
static void Main(string[] args)
{
DateTimeFormatInfo greek = new CultureInfo("el-GR").DateTimeFormat;
foreach (string month in monthMapping)
{
if( string.Compare(currentMonth[1], month, new CultureInfo("el-GR") , CompareOptions.IgnoreNonSpace) == 0)
{
var dtFormat = DateTime.ParseExact($"08 {month} 2021", "dd' 'MMMM' 'yyyy", greek, DateTimeStyles.None);
}
}
}
您可以尝试规范化月份名称,使用不区分变音符号的比较从 CultureInfo.DateTimeFormat.MonthGenitiveNames 集合中检索正确的月份名称,因为在某些文化中,属格名称与主格名称不同(日期是以以下形式呈现:8th of June, 2021
).
一个String.Compare() overload accepts both CultureInfo and CompareOptions个参数。
IgnoreNonSpace
标志:表示字符串比较必须忽略非间距组合字符,例如变音符号。 [...]。
这允许在 MonthGenitiveNames
集合和 return 相应的专有名称中搜索月份名称,忽略缺失的变音符号。
然后可以将 标准化的 日期与提供的 CultureInfo 一起传递给 DateTime.TryParse(),以提取 DateTime 对象。
示例方法调用:
var normalizedDateTime = NormalizeMonthDiacritics(new CultureInfo("el-GR"), "08 Ιουνιου 2021");
using System.Globalization;
using System.Linq;
internal DateTime NormalizeMonthDiacritics(CultureInfo culture, string date)
{
string[] inputDateParts = date.Split();
inputDateParts[1] = culture.DateTimeFormat.MonthGenitiveNames.FirstOrDefault(month =>
string.Compare(inputDateParts[1], month, culture, CompareOptions.IgnoreNonSpace) == 0)
?? inputDateParts[1];
string normalizedDate = string.Join(" ", inputDateParts);
if (DateTime.TryParse(normalizedDate, culture, DateTimeStyles.None, out DateTime dtm)) {
return dtm;
}
else {
throw new ArgumentException("The provided date cannot be normalized",
new Exception("Month Genitive form not available"));
}
}
由于至少有 37 种文化使用由 2 个或更多部分组成的月份名称,为了使该方法更通用并将相同的过程应用于 Abbreviated Month Genitive 名称,可以修改此方法以解析输入日期的方式略有不同,还允许指定是否以短格式提供月份名称。
日期格式可以由这三部分组成:
- 代表月中日或年的数值
- 月份部分,属名,长格式字符串 (
MMMM
) 或短格式字符串 (MMM
) - 表示年或月日的数值
DateTime.TryParse()
可以用两种方式处理 DateTime 格式。
像这样调用这个修改后的方法:
var culture = new CultureInfo("sah-RU");
string date = "2020 атырдьах ыиын 08"; // <= Should be атырдьах ыйын
var normalizedDateTime = NormalizeMonthDiacritics(culture, date, false);
修改方法:
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
internal DateTime NormalizeMonthDiacritics(CultureInfo culture, string date, bool monthShortForm = false)
{
string pattern = @"(\d+)\s+(.*?)\s+(\d+)";
var parts = Regex.Match(date, pattern, RegexOptions.CultureInvariant | RegexOptions.Singleline)
.Groups.OfType<Capture>().Skip(1).Take(3).Select(c => c.Value).ToArray();
var monthNames = monthShortForm
? culture.DateTimeFormat.AbbreviatedMonthGenitiveNames
: culture.DateTimeFormat.MonthGenitiveNames;
parts[1] = monthNames.FirstOrDefault(month =>
string.Compare(parts[1], month, culture, CompareOptions.IgnoreNonSpace) == 0)
?? parts[1];
string normalizedDate = string.Join(" ", parts);
if (DateTime.TryParse(normalizedDate, culture, DateTimeStyles.None, out DateTime dtm)) {
return dtm;
}
else {
throw new ArgumentException("The provided date cannnot be normalized",
new Exception("Month Genitive form not available"));
}
}