【问题标题】:The given DateTime key was not present in the dictionary字典中不存在给定的 DateTime 键
【发布时间】:2013-09-30 21:49:51
【问题描述】:

我是 C# 和编程的初学者。我正在尝试计算一些DateTime 变量。第一个叫dDate,第二个叫dDate1dDate的前一天),第三个dDate2dDate的前一天,即dDate1的前一天),第四个dDate3dDate的前三天,即dDate1的前第二天和dDate2的前一天)。他们一定不是假期或周末!

我已将所有假期和周末都存储在名为nd<DateTime, string> 的字典中。键DateTime 有一系列日期,从2011-01-012013-01-01,一步一步,值stringTRNT,一个字符串变量但不是布尔值。如果是周末或节假日,则字符串为NT,否则为TR

我想做的是当dDate 是周末或假期时,减去一天。比如dDate2012-01-02是假期,把dDate改成2012-01-01,又因为是周末(Sunday),改成2011-12-31,又是周末,改成dDate2011-12-30。与dDate1dDate2dDate3 相同。

这里的问题是我的代码适用于dDate。但它给出了一个错误:

给定的键不在字典中

当我为dDate1dDate2dDate3 做同样的事情时。下面附上代码:

 private Dictionary<DateTime, string> noDates;
 ...
 noDates = new Dictionary<DateTime, string>();

 public void ImportNoDate()
 {
      string str;
      string[] line = new string[0];
      while ((str = reader.ReadLine()) != null) 
      {
         line = str.Split(',');
         String date = line[1];
         String flag = line[2];//flag is "NT" or "TR"
         String[] tmp = date.Split('-');
         date = Convert.ToInt32(tmp[0]) + "-" + Convert.ToInt32(tmp[1]) + "-" + Convert.ToInt32(tmp[2]);

         DateTime noDate = DateTime.Parse(date);
         noDates.Add(noDate, flag);
     }
  }

public void ImportdDate()
{
    ...
    DDates dd = new DDates(dDate, noDates); //dDate is defined similar to noDate, it is just another //series of date
}

    //DDates is an auxiliary cs file called DDates.cs
    public DDates(DateTime dd, Dictionary<DateTime, string> nd)
    {
         dDate1 = dDate.AddDays(-1);
         dDate1 = dDate.AddDays(-2);
         dDate3 = dDate.AddDays(-3);

       // dDate is imported from data file and has been Parse
      // to DateTime and it is something like
      // 2012-01-01 12:00:00 AM

     if (nd.ContainsKey(dDate))
     {
        while (nd[dDate].Contains("NT"))
       {
          dDate = dDate.AddDays(-1);
       }
    }

   //It works fine till here:
   if (nd.ContainsKey(dDate1))
   {
      //It gives "the given key was not present in the dictionary" here:
      while (nd[dDate1].Contains("NT"))
      {
        dDate1 = dDate1.AddDays(-1);
      }
   }
}

【问题讨论】:

  • 你在使用多线程吗?
  • 你应该展示你是如何填充你的字典的。
  • 是你所有的代码,还是中间缺少部分
  • 您似乎在第一部分的检查和循环中都使用了dDate,但在第二部分中,您在ifwhile 检查中使用了dDate1,但您使用dDate2 在数学中。这是故意的吗?
  • 我不确定您的整个逻辑是否有效,但这是不同的问题。如果您使用日期作为字典的键,通常不是一个好主意。显然,您试图找到此密钥,但“日期时间”是一种非常灵活的数据类型,您会遇到问题。使用字符串作为字典的键。

标签: c# dictionary key containskey


【解决方案1】:

从您的描述看来,您正在尝试为给定日期找到第一个非假日日期。

使用字典并存储所有可能的日期并不是解决此问题的正确方法。

我个人认为HashSet&lt;DateTime&gt; 加上一点数学是最好的解决方案。其实我很无聊所以我写了它

static class HolidayTester
{
    private static HashSet<DateTime> fixedHolidays = new HashSet<DateTime>(new DayOnlyComparer())
        {
            new DateTime(1900,1,1), //New Years
            new DateTime(1900,7,4), //4th of july
            new DateTime(1900,12, 25) //Christmas
        };


    /// <summary>
    /// Finds the most recent workday from a given date.
    /// </summary>
    /// <param name="date">The date to test.</param>
    /// <returns>The most recent workday.</returns>
    public static DateTime GetLastWorkday(DateTime date)
    {
        //Test for a non working day
        if (IsDayOff(date))
        {
            //We hit a non working day, recursively call this function again on yesterday.
            return GetLastWorkday(date.AddDays(-1));
        }

        //Not a holiday or a weekend, return the current date.
        return date;
    }


    /// <summary>
    /// Returns if the date is work day or not.
    /// </summary>
    /// <param name="testDate">Date to test</param>
    /// <returns>True if the date is a holiday or weekend</returns>
    public static bool IsDayOff(DateTime testDate)
    {
      return date.DayOfWeek == DayOfWeek.Saturday ||
             date.DayOfWeek == DayOfWeek.Sunday || //Test for weekend
             IsMovingHolidy(testDate) || //Test for a moving holiday
             fixedHolidays.Contains(testDate); //Test for a fixed holiday
    }


    /// <summary>
    /// Tests for each of the "dynamic" holidays that do not fall on the same date every year.
    /// </summary>
    private static bool IsMovingHolidy(DateTime testDate)
    {
        //Memoral day is the last Monday in May
        if (testDate.Month == 5 && //The month is May 
                testDate.DayOfWeek == DayOfWeek.Monday && //It is a Monday
                testDate.Day > (31 - 7)) //It lands within the last week of the month.
            return true;

        //Labor day is the first Monday in September
        if (testDate.Month == 9 && //The month is september
                testDate.DayOfWeek == DayOfWeek.Monday &&
                testDate.Day <= 7) //It lands within the first week of the month
            return true;


        //Thanksgiving is the 4th Thursday in November
        if (testDate.Month == 11 && //The month of November
            testDate.DayOfWeek == DayOfWeek.Thursday &&
            testDate.Day > (7*3) && testDate.Day <= (7*4)) //Only durning the 4th week
            return true;

        return false;
    }


    /// <summary>
    /// This comparer only tests the day and month of a date time for equality
    /// </summary>
    private class DayOnlyComparer : IEqualityComparer<DateTime>
    {
        public bool Equals(DateTime x, DateTime y)
        {
            return x.Day == y.Day && x.Month == y.Month;
        }

        public int GetHashCode(DateTime obj)
        {
            return obj.Month + (obj.Day * 12);
        }
    }
}

现在它不完全遵循您的规则,此代码测试一天是否是工作日并一直向后走,直到遇到第一个非工作日。修改起来很容易,但是我不想完全解决你的问题,所以你可以学习一点(除非我误解了算法并且我确实解决了问题,在这种情况下......欢迎您)

你使用它的方式是简单地输入一个日期,然后用它来决定你是要返回TR还是NT

public static string GetDateLabel(DateTime testDate)
{
    if(HolidayTester.IsDayOff(testDate))
        return "NT";
    else
        return "TR";
}

如果您想知道最后一个工作日,您可以直接拨打HolidayTester.GetLastWorkday(DateTime)

【讨论】:

  • 这真是花哨的代码!非常感谢!我正在对其进行测试并根据自己的需要对其进行修改。会让你知道:)
  • 嗨,斯科特,我已经解决了这个问题。这本质上非常容易。我所做的是将所有假期日期存储在 List 变量中并设置一个 while 循环。当 dDate 在列表中时,dDate = dDate.AddDays(-1)。再次感谢你!接下来我将尝试将您的代码集成到我的程序中,以使该过程更加自动化和智能!
  • @BeginnedCSharp 您可能希望使用HashSet 而不是List,查找速度会快得多。
猜你喜欢
  • 2012-02-18
  • 2016-08-14
  • 2022-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多