将工作日缩写字符串(包括范围)转换为列表<DayOfWeek>
Convert a string of weekday abbreviations, including ranges, into a List<DayOfWeek>
我有字符串“Mon-Thu, Sun
”。
我需要把它转换成new List<DayOfWeek>{DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Sunday}
我考虑将此字符串拆分为字符串数组,然后将字符串解析为具有日期格式 "ddd" 的 DateTime。但我需要以某种方式检测“-”符号在哪里,“,”在哪里。
但是下一个代码失败了
var str = "Mon-Thu, Sun";
var split = str.Split(new []{',', '-'});
foreach(var item in split){
Console.WriteLine(item.Trim());
var day = DateTime.ParseExact(item.Trim(), "ddd", CultureInfo.InvariantCulture);
Console.WriteLine(day.ToShortDateString());
}
有错误"String was not recognized as a valid DateTime because the day of week was incorrect."
Mon
不是 C# 的标准日期输入。首先,您必须根据您希望支持的所有格式,手动将其转换为 DayOfWeek
枚举中正确的等效日期值。比如 Mon 应该是 Monday 等等。一旦你有了正确的等价物,你就可以轻松地将它映射到 DayOfWeek
枚举。
这是因为当您在解析时仅指定星期几时,它默认为 DateTime.Now
,因为您是 运行 程序的那一天。因此,如果您度过了与今天今天不同的一天,您会收到错误消息。你必须自己解析它,例如通过
Dictionary<string, DayOfWeek> days = new Dictionary<string, DayOfWeek>
{
["Mon"] = DayOfWeek.Monday,
["Tue"] = DayOfWeek.Tuesday,
["Wed"] = DayOfWeek.Wednesday,
["Thu"] = DayOfWeek.Thursday,
["Fri"] = DayOfWeek.Friday,
["Sat"] = DayOfWeek.Saturday,
["Sun"] = DayOfWeek.Sunday
};
//Get the next day in the week by calculating modulo 7
DayOfWeek NextDay(DayOfWeek day) => (DayOfWeek)(((int)day + 1) % 7);
List<DayOfWeek> GetDays(string input)
{
var ranges = input.Split(',');
var daysList = new List<DayOfWeek>();
foreach(var range in ranges)
{
var bounds = range.Split('-').Select(s => s.Trim()).ToList();
if(bounds.Count == 1)
{
if(days.TryGetValue(bounds[0], out var day))
daysList.Add(day);
else
throw new FormatException("Couldn't find day");
}
else if(bounds.Count == 2)
{
if(days.TryGetValue(bounds[0], out var begin) && days.TryGetValue(bounds[1], out var end))
{
if(begin == NextDay(end)) // whole week in one range
{
daysList.AddRange(days.Values);
break;
}
for(var i = begin; i != NextDay(end); i = NextDay(i))
{
daysList.Add(i);
}
}
else
throw new FormatException("Couldn't find day");
}
else
throw new FormatException("Too many hyphens in one range");
}
var set = new SortedSet<DayOfWeek>(daysList); //remove duplicates and sort
return set.ToList();
}
var input = "Mon-Thu, Sun";
foreach(var day in GetDays(input))
{
Console.WriteLine(day);
}
编辑:添加答案:)
以下代码适用于您提到的格式。
Input : "Mon-Thu, Sun"
OutPut: Monday, Tuesday, Wednesday, Thursday, Sunday
Input : "Mon, Wed-Thu, Sun"
OutPut: Monday, Wednesday, Thursday, Sunday
List<DayOfWeek> ListOfDays()
{
var str = "Mon-Thu, Sun";
string[] split = str.Split(',');
var days = new List<DayOfWeek>();
foreach (var item in split)
{
if (item.IndexOf('-') < 0)
{
days.Add(GetDayOfWeek(item.Trim()));
continue;
}
var consecutiveDays = item.Split('-');
DayOfWeek startDay = GetDayOfWeek(consecutiveDays[0].Trim());
DayOfWeek endDay = GetDayOfWeek(consecutiveDays[1].Trim());
for (DayOfWeek day = startDay; day <= endDay; day++)
days.Add(day);
}
return days;
}
DayOfWeek GetDayOfWeek(string day)
{
switch (day.ToUpper())
{
case "MON":
return DayOfWeek.Monday;
break;
case "TUE":
return DayOfWeek.Tuesday;
break;
case "WED":
return DayOfWeek.Wednesday;
break;
case "THU":
return DayOfWeek.Thursday;
break;
case "FRI":
return DayOfWeek.Friday;
break;
case "SAT":
return DayOfWeek.Saturday;
break;
case "SUN":
return DayOfWeek.Sunday;
break;
default:
throw new ArgumentException("Invalid day");
break;
}
}
一种方法是首先将字符串拆分为 "chunks",我将其定义为一天或多天的范围,以逗号分隔。然后,对于每个块,获取开始日期,将其添加到列表中,然后递增直到我们到达结束日期。
我们可以编写代码来增加天数,这样它们将 "wrap around" 一周。例如,如果我们要表示我们将从 "Fri-Mon" 开始休假的时间,那么这些天将是星期五、星期六、星期日和星期一。仅仅递增将以无效值结束,因为星期日是 0
.
我们可以使用Enum.GetValues
结合System.LinqCast
的方法得到星期几的字符串值,然后比较一下星期几开始根据我们的意见。
static void Main(string[] args)
{
var input = "Fri-Thu, Sun";
var consecutiveChunks = input.Split(new[] { ',' },
StringSplitOptions.RemoveEmptyEntries);
var output = new List<DayOfWeek>();
var daysOfWeek = Enum.GetValues(typeof(DayOfWeek)).Cast<DayOfWeek>();
foreach (var chunk in consecutiveChunks)
{
var chunkRange = chunk.Split('-').Select(i => i.Trim()).ToList();
DayOfWeek currentDay = daysOfWeek
.First(d => d.ToString().StartsWith(chunkRange[0]));
DayOfWeek lastDay = chunkRange.Count > 1
? daysOfWeek.First(d => d.ToString().StartsWith(chunkRange[1]))
: currentDay;
output.Add(currentDay);
// If we have a range of days, add the rest of them
while (currentDay != lastDay)
{
// Increment to the next day
if (currentDay == DayOfWeek.Saturday)
{
currentDay = DayOfWeek.Sunday;
}
else
{
currentDay++;
}
output.Add(currentDay);
}
}
// Output our results:
Console.WriteLine($"The ranges, \"{input}\" resolve to:");
output.ForEach(i => Console.WriteLine(i.ToString()));
Console.Write("\nDone!\nPress any key to exit...");
Console.ReadKey();
}
输出
事实证明,C# 库确实维护了一个日期缩写列表,如果您不喜欢它们,您甚至可以更改它们。具体来说,我指的是 CultureInfo.[culture].DateTimeFormat.AbbreviatedDayNames
.
InvariantCulture
对星期一、星期四和星期日使用的缩写与您在问题中列出的相同。
给定日期名称的缩写,您应该能够导出 AbbreviatedDayNames
数组中缩写名称的索引,该索引与 DayOfWeek
.[=16= 使用的索引相匹配]
对我来说,这种方法似乎比将文字字符串嵌入代码要好。
public static void Main()
{
var dayList = new List<DayOfWeek>();
var str = "Mon-Thu, Sun";
str = str.Replace(" ", string.Empty); // remove spaces
// split groups by comma
var split = str.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var item in split) // process each group
{
// split ranges by hyphen
var elements = item.Split(new[] {'-'}, StringSplitOptions.RemoveEmptyEntries); // split group into elements
switch (elements.Length)
{
case 1:
// add single element
dayList.Add((DayOfWeek) GetDayIndex(elements[0]));
break;
case 2:
// add range of elements
dayList.AddRange(GetDayRange(elements[0], elements[1]));
break;
default:
Console.WriteLine($"Input line does not match required format: \"{str}\"");
break;
}
}
// prove it works
Console.WriteLine(string.Join(", ", dayList));
}
private static int GetDayIndex(string dayNameAbbreviation)
{
return Array.IndexOf(CultureInfo.InvariantCulture.DateTimeFormat.AbbreviatedDayNames, dayNameAbbreviation);
}
private static IEnumerable<DayOfWeek> GetDayRange(string beginDayNameAbbrev, string endDayNameAbbrev)
{
var dayRange = new List<DayOfWeek>();
for (var i = GetDayIndex(beginDayNameAbbrev); i <= GetDayIndex(endDayNameAbbrev); i++)
{
dayRange.Add((DayOfWeek) i);
}
return dayRange;
}
编辑
如上所述,如果您不喜欢特定文化使用的日期缩写,您可以暂时更改它们。要了解如何操作,请查看这个 Stack Overflow 问题:How to change DateTimeFormatInfo.CurrentInfo AbbreviatedDayNames collection.
我有字符串“Mon-Thu, Sun
”。
我需要把它转换成new List<DayOfWeek>{DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Sunday}
我考虑将此字符串拆分为字符串数组,然后将字符串解析为具有日期格式 "ddd" 的 DateTime。但我需要以某种方式检测“-”符号在哪里,“,”在哪里。
但是下一个代码失败了
var str = "Mon-Thu, Sun";
var split = str.Split(new []{',', '-'});
foreach(var item in split){
Console.WriteLine(item.Trim());
var day = DateTime.ParseExact(item.Trim(), "ddd", CultureInfo.InvariantCulture);
Console.WriteLine(day.ToShortDateString());
}
有错误"String was not recognized as a valid DateTime because the day of week was incorrect."
Mon
不是 C# 的标准日期输入。首先,您必须根据您希望支持的所有格式,手动将其转换为 DayOfWeek
枚举中正确的等效日期值。比如 Mon 应该是 Monday 等等。一旦你有了正确的等价物,你就可以轻松地将它映射到 DayOfWeek
枚举。
这是因为当您在解析时仅指定星期几时,它默认为 DateTime.Now
,因为您是 运行 程序的那一天。因此,如果您度过了与今天今天不同的一天,您会收到错误消息。你必须自己解析它,例如通过
Dictionary<string, DayOfWeek> days = new Dictionary<string, DayOfWeek>
{
["Mon"] = DayOfWeek.Monday,
["Tue"] = DayOfWeek.Tuesday,
["Wed"] = DayOfWeek.Wednesday,
["Thu"] = DayOfWeek.Thursday,
["Fri"] = DayOfWeek.Friday,
["Sat"] = DayOfWeek.Saturday,
["Sun"] = DayOfWeek.Sunday
};
//Get the next day in the week by calculating modulo 7
DayOfWeek NextDay(DayOfWeek day) => (DayOfWeek)(((int)day + 1) % 7);
List<DayOfWeek> GetDays(string input)
{
var ranges = input.Split(',');
var daysList = new List<DayOfWeek>();
foreach(var range in ranges)
{
var bounds = range.Split('-').Select(s => s.Trim()).ToList();
if(bounds.Count == 1)
{
if(days.TryGetValue(bounds[0], out var day))
daysList.Add(day);
else
throw new FormatException("Couldn't find day");
}
else if(bounds.Count == 2)
{
if(days.TryGetValue(bounds[0], out var begin) && days.TryGetValue(bounds[1], out var end))
{
if(begin == NextDay(end)) // whole week in one range
{
daysList.AddRange(days.Values);
break;
}
for(var i = begin; i != NextDay(end); i = NextDay(i))
{
daysList.Add(i);
}
}
else
throw new FormatException("Couldn't find day");
}
else
throw new FormatException("Too many hyphens in one range");
}
var set = new SortedSet<DayOfWeek>(daysList); //remove duplicates and sort
return set.ToList();
}
var input = "Mon-Thu, Sun";
foreach(var day in GetDays(input))
{
Console.WriteLine(day);
}
编辑:添加答案:)
以下代码适用于您提到的格式。
Input : "Mon-Thu, Sun"
OutPut: Monday, Tuesday, Wednesday, Thursday, Sunday
Input : "Mon, Wed-Thu, Sun"
OutPut: Monday, Wednesday, Thursday, Sunday
List<DayOfWeek> ListOfDays()
{
var str = "Mon-Thu, Sun";
string[] split = str.Split(',');
var days = new List<DayOfWeek>();
foreach (var item in split)
{
if (item.IndexOf('-') < 0)
{
days.Add(GetDayOfWeek(item.Trim()));
continue;
}
var consecutiveDays = item.Split('-');
DayOfWeek startDay = GetDayOfWeek(consecutiveDays[0].Trim());
DayOfWeek endDay = GetDayOfWeek(consecutiveDays[1].Trim());
for (DayOfWeek day = startDay; day <= endDay; day++)
days.Add(day);
}
return days;
}
DayOfWeek GetDayOfWeek(string day)
{
switch (day.ToUpper())
{
case "MON":
return DayOfWeek.Monday;
break;
case "TUE":
return DayOfWeek.Tuesday;
break;
case "WED":
return DayOfWeek.Wednesday;
break;
case "THU":
return DayOfWeek.Thursday;
break;
case "FRI":
return DayOfWeek.Friday;
break;
case "SAT":
return DayOfWeek.Saturday;
break;
case "SUN":
return DayOfWeek.Sunday;
break;
default:
throw new ArgumentException("Invalid day");
break;
}
}
一种方法是首先将字符串拆分为 "chunks",我将其定义为一天或多天的范围,以逗号分隔。然后,对于每个块,获取开始日期,将其添加到列表中,然后递增直到我们到达结束日期。
我们可以编写代码来增加天数,这样它们将 "wrap around" 一周。例如,如果我们要表示我们将从 "Fri-Mon" 开始休假的时间,那么这些天将是星期五、星期六、星期日和星期一。仅仅递增将以无效值结束,因为星期日是 0
.
我们可以使用Enum.GetValues
结合System.LinqCast
的方法得到星期几的字符串值,然后比较一下星期几开始根据我们的意见。
static void Main(string[] args)
{
var input = "Fri-Thu, Sun";
var consecutiveChunks = input.Split(new[] { ',' },
StringSplitOptions.RemoveEmptyEntries);
var output = new List<DayOfWeek>();
var daysOfWeek = Enum.GetValues(typeof(DayOfWeek)).Cast<DayOfWeek>();
foreach (var chunk in consecutiveChunks)
{
var chunkRange = chunk.Split('-').Select(i => i.Trim()).ToList();
DayOfWeek currentDay = daysOfWeek
.First(d => d.ToString().StartsWith(chunkRange[0]));
DayOfWeek lastDay = chunkRange.Count > 1
? daysOfWeek.First(d => d.ToString().StartsWith(chunkRange[1]))
: currentDay;
output.Add(currentDay);
// If we have a range of days, add the rest of them
while (currentDay != lastDay)
{
// Increment to the next day
if (currentDay == DayOfWeek.Saturday)
{
currentDay = DayOfWeek.Sunday;
}
else
{
currentDay++;
}
output.Add(currentDay);
}
}
// Output our results:
Console.WriteLine($"The ranges, \"{input}\" resolve to:");
output.ForEach(i => Console.WriteLine(i.ToString()));
Console.Write("\nDone!\nPress any key to exit...");
Console.ReadKey();
}
输出
事实证明,C# 库确实维护了一个日期缩写列表,如果您不喜欢它们,您甚至可以更改它们。具体来说,我指的是 CultureInfo.[culture].DateTimeFormat.AbbreviatedDayNames
.
InvariantCulture
对星期一、星期四和星期日使用的缩写与您在问题中列出的相同。
给定日期名称的缩写,您应该能够导出 AbbreviatedDayNames
数组中缩写名称的索引,该索引与 DayOfWeek
.[=16= 使用的索引相匹配]
对我来说,这种方法似乎比将文字字符串嵌入代码要好。
public static void Main()
{
var dayList = new List<DayOfWeek>();
var str = "Mon-Thu, Sun";
str = str.Replace(" ", string.Empty); // remove spaces
// split groups by comma
var split = str.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var item in split) // process each group
{
// split ranges by hyphen
var elements = item.Split(new[] {'-'}, StringSplitOptions.RemoveEmptyEntries); // split group into elements
switch (elements.Length)
{
case 1:
// add single element
dayList.Add((DayOfWeek) GetDayIndex(elements[0]));
break;
case 2:
// add range of elements
dayList.AddRange(GetDayRange(elements[0], elements[1]));
break;
default:
Console.WriteLine($"Input line does not match required format: \"{str}\"");
break;
}
}
// prove it works
Console.WriteLine(string.Join(", ", dayList));
}
private static int GetDayIndex(string dayNameAbbreviation)
{
return Array.IndexOf(CultureInfo.InvariantCulture.DateTimeFormat.AbbreviatedDayNames, dayNameAbbreviation);
}
private static IEnumerable<DayOfWeek> GetDayRange(string beginDayNameAbbrev, string endDayNameAbbrev)
{
var dayRange = new List<DayOfWeek>();
for (var i = GetDayIndex(beginDayNameAbbrev); i <= GetDayIndex(endDayNameAbbrev); i++)
{
dayRange.Add((DayOfWeek) i);
}
return dayRange;
}
编辑
如上所述,如果您不喜欢特定文化使用的日期缩写,您可以暂时更改它们。要了解如何操作,请查看这个 Stack Overflow 问题:How to change DateTimeFormatInfo.CurrentInfo AbbreviatedDayNames collection.