2013-09-30 2 views
0

저는 C#과 프로그래밍의 초보자입니다. 몇 가지 DateTime 변수를 계산하려고합니다. 첫번째는 dDate 및 제 dDate1 (dDate 전날) 제 dDate2 (dDate 번째 전날, 즉 dDate1 전날) dDate의 제 dDate3 (제 전날, 즉이라고 두 번째 전날은 dDate1이고 전날은 dDate2입니다. 휴일이나 주말이 아니어야합니다!주어진 DateTime 키가 사전에 없습니다.

나는 모든 휴일과 주말을 nd<DateTime, string>이라는 사전에 저장했습니다. DateTime 키의 날짜는 2011-01-01에서 2013-01-01까지 1 일 단위이고 값은 string이며 TR 또는 NT입니다. 문자열 변수이지만 부울은 아닙니다. 주말이나 공휴일 인 경우 문자열은 NT이며 그렇지 않은 경우 TR입니다.

내가하려는 것은 dDate이 주말 또는 공휴일 인 경우 하루를 뺀 것입니다. 예를 들어, dDate2012-01-01dDate을 변경, 휴일이며, 주말 (일요일)이기 때문에, 2011-12-31로 변경하고, 다시 주말, 2011-12-30dDate을 변경하는 2012-01-02이다. dDate1, dDate2dDate3과 동일합니다.

문제는 내 코드가 dDate에 적합합니다. 내가 dDate1, dDate2 또는 dDate3을 위해 같은 일을하고 있어요

the given key was not present in the dictionary

:하지만 오류가 있습니다. 이 코드는 아래에 첨부되어 있습니다 :

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); 
     } 
    } 
} 
+0

여러 스레드를 사용하고 있습니까? –

+1

사전을 채우는 방법을 보여줘야합니다. –

+0

은 여러분의 모든 코드이거나, inbetween 부분이없는 부분입니다 –

답변

1

귀하의 설명에서 당신이하려는 것은 주어진 날짜에 첫 번째 비 휴일 날짜를 찾는 것 같습니다.

사전을 사용하여 가능한 모든 날짜를 저장하는 것은 올바른 해결책이 아닙니다.

개인적으로는 HashSet<DateTime>에 약간의 수학을 더한 것이 가장 좋은 해결책이라고 생각합니다. 나는 하루 작업 일이며이 아닌 첫 번째 작업 일 히트까지 뒤로 걷는 유지하면 지금은 정확히이 코드 검사를 규칙을 따르지 않는

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

그것을 쓴 그래서 사실 나는 지루했다. 수정하기는 쉽지만 문제를 정확히 풀기를 원하지 않았습니다. 알고리즘을 잘못 이해하고 문제를 해결하지 않는 한 ... 환영합니다.

당신이 그것을 사용하는 것이 방법은 단순히 날짜에 넣고 마지막 근무일 알고 싶다면 다음 HolidayTester.GetLastWorkday(DateTime)에서 직접 그를 호출 할 수 있습니다 당신이 TR 또는 NT

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

을 반환하려는 경우를 결정하는 것을 사용한다

+0

이것은 정말 멋진 코드입니다! 고마워요! 나는 그것을 테스트하고 내 자신의 필요에 맞게 수정하고있다. 윌 알려 : – BeginnedCSharp

+0

안녕 스콧,이 문제를 해결했습니다. 그것은 본질적으로 매우 쉽습니다. 내가 한 것은 모든 휴일 날짜를 List 변수에 저장하고 while 루프를 설정하는 것이 었습니다. dDate가 List에있는 동안, dDate = dDate.AddDays (-1). 다시 감사합니다! 다음으로 코드를 내 프로그램에 통합하여 프로세스를보다 자동 및 지능적으로 만들어 보겠습니다! – BeginnedCSharp

+0

@BeginnedCSharp'List' 대신에'HashSet'을 사용하면 검색이 훨씬 빨라집니다. –

관련 문제