没有标点符号的希腊月份使用 Date.ParseExact转换为日期



我有一个希腊日期"08 Ιουνιου 2021"我想将其转换为Date。这是不可能的,因为月份缺少一些标点符号。正确的月份是"Ιουνίου"它实际上通过下面的代码正常工作

var greek = new CultureInfo("el-GR").DateTimeFormat;
var dtFormat = DateTime.ParseExact("08 Ιουνίου 2021", "dd' 'MMMM' 'yyyy", greek, DateTimeStyles.None);

任何想法如何正确格式化月份?

您可以尝试规范化月份名称,使用不敏感的音调符号比较从 CultureInfo.DateTimeFormat.MonthGenitiveNames 集合中检索正确的月份名称,因为在某些区域性中,属名与主格不同(日期以以下形式表示:8th of June, 2021(。

String.Compare(( 重载同时接受 CultureInfo 和 CompareOptions 参数。
IgnoreNonSpace标志:指示字符串比较必须忽略非空格组合字符,如音调符号。[...]. 这允许在MonthGenitiveNames集合中搜索月份名称,忽略缺少的变音符号并返回相应的正确名称。

然后,可以将规范化的日期与提供的 CultureInformation 一起传递给 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 个或更多部分组成的月份名称,为了使该方法更加通用,并将相同的过程应用于缩写的月份属名称,因此可以修改此方法以稍微不同的方式解析输入日期,并允许指定是否以短格式提供月份名称。

然后,日期格式可以由以下 3 个部分组成:

  1. 表示月中的某天或年份的数值
  2. 月份部分,属名,长格式字符串 (MMMM( 或短格式 (MMM
  3. (
  4. 表示年份或日期的数值

DateTime.TryParse()可以通过两种方式处理日期时间格式。

调用此修改后的方法,如下所示:

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时,我们会根据包含音调符号的月份映射对其进行检查。

比较由

string.Compare(firstString, secondString, new CultureInfo("el-GR"), CompareOptions.IgnoreNonSpace);

来自 Msdn 文档 - IgnoreNonSpace:

指示字符串比较必须忽略非空格组合字符,如音调符号。Unicode 标准将组合字符定义为与基本字符组合以生成新字符的字符。非间距组合字符在呈现时不会单独占用间距位置。

这可能是/将是一个潜在的修复:

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);
}
}
}

最新更新