[英]The given DateTime key was not present in the dictionary
I am a very beginner of C# and programming. 我是C#和编程的初学者。 I am trying to calculate a few
DateTime
variables. 我正在尝试计算一些
DateTime
变量。 The first one is called dDate
and second dDate1
(the previous day of dDate
), third dDate2
(the second previous day of dDate
, ie, the previous day of dDate1
), the fourth dDate3
(the third previous day of dDate
, ie, the second previous day of dDate1
and the previous day of dDate2
). 第一种被称为
dDate
和第二dDate1
(前一天dDate
),第三dDate2
(第二前一天dDate
,即,前一天dDate1
,第四) dDate3
(第三前一天dDate
,即dDate1
的前第二天和dDate2
的前一天)。 They must be not holidays or weekends! 他们一定不是假期或周末!
I've had all holidays and weekends stored in a dictionary called nd<DateTime, string>
. 我已经将所有节假日和周末存储在名为
nd<DateTime, string>
的字典中。 The key DateTime
has a series of date from 2011-01-01
to 2013-01-01
, step by one day and the value string
is either TR
or NT
, a string variable but not boolean. 关键的
DateTime
具有从一系列日期2011-01-01
至2013-01-01
,一步一天,值string
或者是TR
或NT
,一个字符串变量而不是布尔值。 If it is weekend or holiday, string is NT
, otherwise TR
. 如果是周末或假日,则字符串为
NT
,否则为TR
。
What I am trying to do is when dDate
is weekend or holiday, minus one day. 我想做的是
dDate
是周末或假日,减去一天。 For example, dDate
is 2012-01-02
which is a holiday, change dDate
to 2012-01-01
, and because it is weekend (Sunday), change it to 2011-12-31
, and it is weekend again, change dDate
to 2011-12-30
. 例如,
dDate
是假期的2012-01-02
,将dDate
更改为2012-01-01
,并且由于它是周末(星期日),所以将其更改为2011-12-31
,再次是周末,则更改dDate
到2011-12-30
。 Same to dDate1
, dDate2
and dDate3
. 与
dDate1
, dDate2
和dDate3
。
The problem here is my code works fine for dDate
. 这里的问题是我的代码对于
dDate
可以正常工作。 But it gives an error: 但是它给出了一个错误:
the given key was not present in the dictionary
给定的键在字典中不存在
when I am doing the same thing for dDate1
, dDate2
or dDate3
. 当我为
dDate1
, dDate2
或dDate3
做同样的事情时。 The code is attached below: 该代码附在下面:
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);
}
}
}
From your description it looks like what you are trying to do is for a given date find the first non holiday date. 从您的描述看来,您要针对给定的日期尝试查找第一个非假期日期。
Using a dictionary and storing every possible date is not the correct solution for this. 使用字典并存储每个可能的日期不是解决此问题的正确方法。
Personally I think a HashSet<DateTime>
plus a little math would be the best solution. 我个人认为
HashSet<DateTime>
加上一些数学运算将是最佳解决方案。 In fact I was bored so I wrote it up 实际上我很无聊,所以我写下来
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);
}
}
}
Now it does not follow your rules exactly, this code tests if a day is a work day and keeps walking backwards till it hits the first non work day. 现在,它不完全遵循您的规则,此代码测试一天是否为工作日,并一直向后走,直到遇到第一个非工作日为止。 It would be easy enough to modify, however I did not want to solve your problem exactly so you could learn a little (Unless I misunderstood the algorithm and I did solve the problem, in that case... your welcome)
修改起来很容易,但是我不想完全解决您的问题,因此您可以学习一些(除非我误解了算法,并且确实解决了问题,在这种情况下……不客气)
The way you would use it is simply put in a date and then use that to decide if you are going to return TR
or NT
您将其使用的方式只是放在一个日期中,然后使用该日期来决定要返回
TR
还是NT
public static string GetDateLabel(DateTime testDate)
{
if(HolidayTester.IsDayOff(testDate))
return "NT";
else
return "TR";
}
If you want to know the last working day you can call that directly from HolidayTester.GetLastWorkday(DateTime)
如果您想知道最后一个工作日,可以直接从
HolidayTester.GetLastWorkday(DateTime)
致电
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.