将一系列工作日缩写(包括范围)转换为List <dayofweek>

时间:2017-08-08 22:41:12

标签: c# string parsing datetime dayofweek

我有字符串“Mon-Thu, Sun”。

我需要将其转换为new List<DayOfWeek>{DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Sunday}

我考虑将此字符串拆分为字符串数组,然后使用dateformat“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());
        }

出现错误“字符串未被识别为有效的DateTime,因为星期几不正确。”

5 个答案:

答案 0 :(得分:1)

以下代码适用于您提到的格式。

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

答案 1 :(得分:1)

执行此操作的一种方法是首先将字符串拆分为&#34; chunk&#34;,我将其定义为一天或多天的范围,由逗号字符分隔。然后,对于每个块,抓住开始日期,将其添加到列表中,然后递增它直到我们到达结束日。

我们可以将代码编写为增量天数,以便它们将包围&#34;星期。例如,如果我们代表我们将从&#34;周五和周三拍摄一些休假时间,那么日子将是周五,周六,周日和周一。由于星期日为0,因此单独增加最终会产生无效值。

我们可以使用Enum.GetValues结合System.Linq Cast方法获取星期几的字符串值,然后进行比较以查找一周中哪一天以我们的输入开头。

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

<强>输出

enter image description here

答案 2 :(得分:1)

事实证明,C#库确实维护了一天的缩写列表,如果你不喜欢它们,你甚至可以改变它们。具体来说,我指的是CultureInfo.[culture].DateTimeFormat.AbbreviatedDayNames

InvariantCulture使用与您在问题中列出的周一,周四和周日相同的缩写。

给定日期名称的缩写,您应该能够在AbbreviatedDayNames数组中派生缩写名称的索引,该索引与DayOfWeek使用的索引相匹配。

对我来说,这种方法似乎比将文字字符串嵌入代码要好。

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

答案 3 :(得分:-1)

这是因为当您在解析时仅指定星期几时,它默认为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);
}
编辑:补充答案:)

答案 4 :(得分:-2)

Mon不是C#的标准日输入。首先,您必须根据您希望支持的所有格式,在DayOfWeek枚举中将其转换为正确的等效日值。就像周一应该是星期一等。一旦你有正确的等价物,你可以很容易地将它映射到DayOfWeek枚号。