簡體   English   中英

將一連串的工作日縮寫(包括范圍)轉換為列表<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());
        }

出現錯誤“因為星期幾不正確,所以無法將字符串識別為有效的DateTime”。

事實證明,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;
}

編輯

如上所述,如果您不喜歡特定文化所使用的日期縮寫,則可以臨時更改它們。 若要查看操作方法,請查看以下堆棧溢出問題: 如何更改DateTimeFormatInfo.CurrentInfo AbbreviatedDayNames集合

以下代碼適用於您提到的格式。

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

一種實現方法是首先將字符串拆分為“塊”,我將其定義為一天或幾天的范圍,並用逗號分隔。 然后,對於每個塊,抓住開始的日子,將其添加到列表中,然后遞增直到結束。

我們可以編寫代碼來增加天數,以使它們“繞”一周。 例如,如果我們要表示要從“周五星期一”開始的一些休假時間,則日期為星期五,星期六,星期日和星期一。 由於星期日是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();
}

產量

在此處輸入圖片說明

這是因為當您在解析時僅指定星期幾時,它默認為DateTime.Now 。現在與運行程序的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);
}

編輯:添加的答案:)

Mon不是C#的標准日期輸入。 首先,您必須根據要支持的所有格式手動將其轉換為DayOfWeek枚舉中的正確的等效日值。 像星期一應該是星期一,等等。一旦有了正確的等值,就可以輕松地將其映射到DayOfWeek枚舉。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM