WPF를 이용해 네이버가 제공하는 날짜 계산 기능을 구현해 보려 합니다.
(날짜 계산은 
기준일을 1일로 포함하여 계산 됩니다)
위와 비슷한 형태로 구현을 하기 위해 필요한 기능이 무엇인지 확인 해볼께요.
- 달력에서 날짜 선택 시 [기준년월일]에 자동 입력
- [기준년월일] 유효성 검사
- [기준년월일]로 부터 날짜 더하기
- [기준년월일]로 부터 날짜 빼기
- [기준년월일]로 부터 기간 구하기
이렇게 필요할 듯 합니다.
이제 하나 하나 알아보도록 하겠습니다.
달력에서 날짜 선택 시 [기준년월일]에 자동 입력
Calendar 컨트롤과 기준년월일 입력에 필요한 텍스트 박스를 XAML 마크업을 이용해 선언 한 뒤 Calendar 컨트롤에서 SelectedDatesChanged 이벤트를 등록 합니다.
1:  <Calendar x:Name="calendar" BorderThickness="0" SelectedDatesChanged="Calendar_SelectedDatesChanged"/>  
 
유저가 날짜 선택 시 기준년월일에 선택 된 날짜를 텍스트 박스 Text 속성에 대입합니다.
1:  /// <summary>  
2:      /// 달력 컨트롤의 선택 날짜가 변경 되었을 경우 지정일에 선택된 날짜를 입력 합니다.  
3:      /// </summary>  
4:      /// <param name="sender"></param>  
5:      /// <param name="e"></param>  
6:      private void Calendar_SelectedDatesChanged(object sender, SelectionChangedEventArgs e)  
7:      {  
8:        if (calendar.SelectedDate.HasValue)  
9:        {  
10:          DateTime selectedItem = calendar.SelectedDate.Value;  
11:          txtBaseDate.Text = selectedItem.ToString(VALID_DATE_FORMAT);  
12:        }  
13:      }  
[기준년월일] 유효성 검사
- 최대 길이 10
- 유효한 문자("숫자", ".")만 입력 가능
- 유요한 포맷("yyyy.MM.dd")만 가능
- "숫자"(ex: 20180218) 형식으로 입력 되었을 경우 지정 날짜 포맷으로 변경
유효성에 필요한 상수 선언
 
1:   // 지정 날짜 문자열 최대 길이  
2:      private const Int32 VALID_DATE_MAX_LENGTH = 10;  
3:      // 지정 날짜 문자열 포맷  
4:      private const String VALID_DATE_FORMAT = "yyyy.MM.dd";  
5:      // 주(Week) 문자열 포맷  
6:      private const String VALID_DAY_OF_WEEK_FORMAT = "dddd";  
7:      // 숫자와 .만 가능 패턴  
8:      private const String VALID_INPUT_PATTERN = @"[\d.]$";  
9:      // 유효 날짜 패턴  
10:      private const String VALID_DATE_PATTERN = @"^\d{4}.\d{2}.\d{2}$";  
11:      // 날짜 입력 옵션 지원 패턴  
12:      private const String OPTION_DATE_PATTERN = @"^\d{8}$";  
 
최대 입력 길이 제한
1:  txtBaseDate.MaxLength = VALID_DATE_MAX_LENGTH;  
문자 입력 시 유효성 체크를 위해 TextChanged 이벤트 선언
1:  <TextBox x:Name="txtBaseDate" Grid.Row="1" Grid.Column="0" Margin="0,10" TextChanged="textBox_TextChanged"  />  
유효하지 않은 문자열 확인
1:  /// <summary>  
2:      /// 입력 후 발생되는 이벤트이다.   
3:      /// 숫자 또는 .만 가능하도록 확인한다.  
4:      /// </summary>  
5:      /// <param name="sender"></param>  
6:      /// <param name="e"></param>  
7:      private void textBox_TextChanged(object sender, TextChangedEventArgs e)  
8:      {  
9:        TextBox textBox = sender as TextBox;  
10:        string input = textBox.Text;  
11:        // 유효한 문자열 확인  
12:        if (Regex.IsMatch(input, VALID_INPUT_PATTERN) == false)  
13:        {  
14:          // 이전 문자열로 변경  
15:          textBox.Text = StringToPrevPosition(input);  
16:          textBox.CaretIndex = textBox.Text.Length;  
17:        }  
18:      }  
이전 문자열로 변경
1:  /// <summary>  
2:      /// 문자열을 이전으로 되돌립니다.  
3:      /// </summary>  
4:      /// <returns></returns>  
5:      private string StringToPrevPosition(string str)  
6:      {  
7:        return str.Substring(0, str.Length - 1);  
8:      }  
유효한 포맷 확인 및 옵션 지원 포맷 확인
1:  // 입력 문자열이 비어있는지 확인  
2:        if (string.IsNullOrEmpty(txtBaseDate.Text))  
3:        {  
4:          List<Inline> textBlockString = CreateGuideText();  
5:          txtResult.Inlines.AddRange(textBlockString);  
6:          return;  
7:        }  
8:        // yyyyMMdd 포맷인지 확인  
9:        if (Regex.IsMatch(txtBaseDate.Text, OPTION_DATE_PATTERN))  
10:        {  
11:          string validDateString = OptionDateStringToValidDateString(txtBaseDate.Text);  
12:          // 텍스트 박스의 문자열을 유요한 문자열로 변경  
13:          txtBaseDate.Text = validDateString;  
14:          txtBaseDate.CaretIndex = validDateString.Length;  
15:        }  
16:        // 유요한 포맷인지 확인  
17:        if (Regex.IsMatch(txtBaseDate.Text, VALID_DATE_PATTERN))  
18:        {  
19:          // 이 곳에서 날짜 계산 처리  
20:        }  
오늘 기준으로 [기준년월일] 기간 확인
기준년월일 문자열 속성 정의
1:  /// <summary>  
2:      /// 지정일 문자열을 날짜 형식으로 변경합니다.  
3:      /// </summary>  
4:      public DateTime? InputDate  
5:      {  
6:        get  
7:        {  
8:          if (string.IsNullOrEmpty(txtBaseDate.Text)) return null;  
9:          DateTime date = DateTime.MinValue;  
10:          if (DateTime.TryParse(txtBaseDate.Text, out date)) return date;  
11:          else return null;  
12:        }  
13:      }  
 
시작 날짜가 종료 날짜보다 크거나 같은지 여부
1:  /// <summary>  
2:      /// 시작 날짜가 종료 날짜보다 크거나 같은지 여부  
3:      /// </summary>  
4:      /// <param name="startDate"></param>  
5:      /// <param name="endDate"></param>  
6:      /// <returns></returns>  
7:      private bool IsSwap(DateTime startDate, DateTime endDate)  
8:      {  
9:        return (startDate >= endDate);  
10:      }  
시작 날짜와 종료 날짜의 기간을 계산합니다.
1:  /// <summary>  
2:      /// 시작 날짜와 종료 날짜의 기간을 계산합니다.  
3:      /// </summary>  
4:      /// <param name="startDate"></param>  
5:      /// <param name="endDate"></param>  
6:      /// <returns></returns>  
7:      private TimeSpan CalculatorDateTerm(DateTime startDate, DateTime endDate)  
8:      {  
9:        if (IsSwap(startDate, endDate))  
10:        {  
11:          DateTime tempDate = startDate;  
12:          startDate = endDate;  
13:          endDate = tempDate;  
14:        }  
15:        return endDate.Subtract(startDate);  
16:      }  
기준일로부터 ?일째 되는 날 구하기
1:  /// <summary>  
2:      /// 지정일로부터 날짜를 더합니다.  
3:      /// </summary>  
4:      /// <param name="sender"></param>  
5:      /// <param name="e"></param>  
6:      private void btnAddDay_Click(object sender, RoutedEventArgs e)  
7:      {  
8:        DateTime? dt = InputDate;  
9:        string addDay = txtAddDay.Text;  
10:        if (dt.HasValue && !string.IsNullOrEmpty(addDay))  
11:        {  
12:          DateTime addDate = dt.Value.AddDays(Convert.ToDouble(addDay));  
13:          txtAddDayResult.Text = addDate.ToString("yyyy.MM.dd");  
14:        }  
15:      }  
기준일로부터 D-?일 구하기
1:  /// <summary>  
2:      /// 지정일로부터 날짜를 뺍니다.  
3:      /// </summary>  
4:      /// <param name="sender"></param>  
5:      /// <param name="e"></param>  
6:      private void btnSubtract_Click(object sender, RoutedEventArgs e)  
7:      {  
8:        // 지정일부터 몇 일전  
9:        DateTime? dt = InputDate;  
10:        string subtractDay = txtSubtractDay.Text;  
11:        if (dt.HasValue && !string.IsNullOrEmpty(subtractDay))  
12:        {  
13:          DateTime subtractDate = dt.Value.AddDays(-Convert.ToDouble(subtractDay));  
14:          txtSubtractResult.Text = subtractDate.ToString("yyyy.MM.dd");  
15:        }  
16:      }  
기준일로부터 ?까지는 며칠 째 구하기
1:  /// <summary>  
2:      /// 지정일과 입력된 날짜의 일 간격을 계산 합니다.  
3:      /// </summary>  
4:      /// <param name="sender"></param>  
5:      /// <param name="e"></param>  
6:      private void btnTerm_Click(object sender, RoutedEventArgs e)  
7:      {  
8:        // 지정일로부터 기간  
9:        if (Regex.IsMatch(txtTermDay.Text, VALID_DATE_PATTERN))  
10:        {  
11:          DateTime? dt = InputDate;  
12:          DateTime startDate = DateTime.MinValue;  
13:          if (DateTime.TryParse(txtTermDay.Text, out startDate) && dt.HasValue)  
14:          {  
15:            TimeSpan term = CalculatorDateTerm(startDate, dt.Value);  
16:            int totalDay = term.Days;  
17:            totalDay = IsSwap(startDate, dt.Value) ? (totalDay += 1) : (totalDay * -1);  
18:            txtTermResult.Text = string.Format("{0}일째", totalDay);  
19:          }  
20:        }  
21:      }  
최종 결과
댓글
댓글 쓰기