diff --git a/src/CalcViewModel/Common/DateCalculator.cpp b/src/CalcViewModel/Common/DateCalculator.cpp index a614907..19d3c49 100644 --- a/src/CalcViewModel/Common/DateCalculator.cpp +++ b/src/CalcViewModel/Common/DateCalculator.cpp @@ -119,7 +119,7 @@ bool DateCalculationEngine::SubtractDuration(_In_ DateTime startDate, _In_ const } // Calculate the difference between two dates -void DateCalculationEngine::GetDateDifference(_In_ DateTime date1, _In_ DateTime date2, _In_ DateUnit outputFormat, _Out_ DateDifference* difference) +bool DateCalculationEngine::TryGetDateDifference(_In_ DateTime date1, _In_ DateTime date2, _In_ DateUnit outputFormat, _Out_ DateDifference* difference) { DateTime startDate; DateTime endDate; @@ -176,8 +176,9 @@ void DateCalculationEngine::GetDateDifference(_In_ DateTime date1, _In_ DateTime catch (Platform::InvalidArgumentException ^) { // Operation failed due to out of bound result - // Do nothing - differenceInDates[unitIndex] = 0; + // For example: 31st Dec, 9999 - last valid date + *difference = DateDifferenceUnknown; + return false; } } @@ -190,6 +191,12 @@ void DateCalculationEngine::GetDateDifference(_In_ DateTime date1, _In_ DateTime if (tempDaysDiff < 0) { // pivotDate has gone over the end date; start from the beginning of this unit + if (differenceInDates[unitIndex] == 0) + { + // differenceInDates[unitIndex] is unsigned, the value can't be negative + *difference = DateDifferenceUnknown; + return false; + } differenceInDates[unitIndex] -= 1; pivotDate = tempPivotDate; pivotDate = AdjustCalendarDate(pivotDate, dateUnit, static_cast(differenceInDates[unitIndex])); @@ -211,16 +218,25 @@ void DateCalculationEngine::GetDateDifference(_In_ DateTime date1, _In_ DateTime } catch (Platform::InvalidArgumentException ^) { - // handling for 31st Dec, 9999 last valid date - // Do nothing - break out - break; + // Operation failed due to out of bound result + // For example: 31st Dec, 9999 - last valid date + *difference = DateDifferenceUnknown; + return false; } } } while (tempDaysDiff != 0); // dates are the same - exit the loop tempPivotDate = AdjustCalendarDate(tempPivotDate, dateUnit, static_cast(differenceInDates[unitIndex])); pivotDate = tempPivotDate; - daysDiff = GetDifferenceInDays(pivotDate, endDate); + int signedDaysDiff = GetDifferenceInDays(pivotDate, endDate); + if (signedDaysDiff < 0) + { + // daysDiff is unsigned, the value can't be negative + *difference = DateDifferenceUnknown; + return false; + } + + daysDiff = signedDaysDiff; } } } @@ -232,6 +248,7 @@ void DateCalculationEngine::GetDateDifference(_In_ DateTime date1, _In_ DateTime difference->month = differenceInDates[1]; difference->week = differenceInDates[2]; difference->day = differenceInDates[3]; + return true; } // Private Methods diff --git a/src/CalcViewModel/Common/DateCalculator.h b/src/CalcViewModel/Common/DateCalculator.h index e71f02f..fdd885e 100644 --- a/src/CalcViewModel/Common/DateCalculator.h +++ b/src/CalcViewModel/Common/DateCalculator.h @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #pragma once @@ -35,8 +35,15 @@ namespace CalculatorApp int month = 0; int week = 0; int day = 0; + + bool operator==(const DateDifference& dd) const + { + return year == dd.year && month == dd.month && week == dd.week && day == day; + } }; + const DateDifference DateDifferenceUnknown{ INT_MIN, INT_MIN, INT_MIN, INT_MIN }; + class DateCalculationEngine { public: @@ -50,7 +57,7 @@ namespace CalculatorApp _In_ Windows::Foundation::DateTime startDate, _In_ const DateDifference& duration, _Out_ Windows::Foundation::DateTime* endDate); - void __nothrow GetDateDifference( + bool __nothrow TryGetDateDifference( _In_ Windows::Foundation::DateTime date1, _In_ Windows::Foundation::DateTime date2, _In_ DateUnit outputFormat, diff --git a/src/CalcViewModel/DateCalculatorViewModel.cpp b/src/CalcViewModel/DateCalculatorViewModel.cpp index 21f5b88..471d5df 100644 --- a/src/CalcViewModel/DateCalculatorViewModel.cpp +++ b/src/CalcViewModel/DateCalculatorViewModel.cpp @@ -122,11 +122,24 @@ void DateCalculatorViewModel::OnInputsChanged() DateTime clippedToDate = ClipTime(ToDate, true); // Calculate difference between two dates - m_dateCalcEngine->GetDateDifference(clippedFromDate, clippedToDate, m_allDateUnitsOutputFormat, &dateDiff); - DateDiffResult = dateDiff; - - m_dateCalcEngine->GetDateDifference(clippedFromDate, clippedToDate, m_daysOutputFormat, &dateDiff); - DateDiffResultInDays = dateDiff; + if (m_dateCalcEngine->TryGetDateDifference(clippedFromDate, clippedToDate, m_daysOutputFormat, &dateDiff)) + { + DateDiffResultInDays = dateDiff; + if (m_dateCalcEngine->TryGetDateDifference(clippedFromDate, clippedToDate, m_allDateUnitsOutputFormat, &dateDiff)) + { + DateDiffResult = dateDiff; + } + else + { + // TryGetDateDifference wasn't able to calculate the difference in days/weeks/months/years, we will instead display the difference in days. + DateDiffResult = DateDiffResultInDays; + } + } + else + { + DateDiffResult = DateDifferenceUnknown; + DateDiffResultInDays = DateDifferenceUnknown; + } } else { @@ -158,14 +171,21 @@ void DateCalculatorViewModel::UpdateDisplayResult() { if (m_IsDateDiffMode) { - // Are to and from dates the same - if (m_dateDiffResultInDays.day == 0) + if (m_dateDiffResultInDays == DateDifferenceUnknown) { + IsDiffInDays = false; + StrDateDiffResultInDays = L""; + StrDateDiffResult = AppResourceProvider::GetInstance().GetResourceString(L"CalculationFailed"); + } + else if (m_dateDiffResultInDays.day == 0) + { + // to and from dates the same IsDiffInDays = true; StrDateDiffResultInDays = L""; StrDateDiffResult = AppResourceProvider::GetInstance().GetResourceString(L"Date_SameDates"); } - else if ((m_dateDiffResult.year == 0) && (m_dateDiffResult.month == 0) && (m_dateDiffResult.week == 0)) + else if (m_dateDiffResult == DateDifferenceUnknown || + (m_dateDiffResult.year == 0 && m_dateDiffResult.month == 0 && m_dateDiffResult.week == 0)) { IsDiffInDays = true; StrDateDiffResultInDays = L""; diff --git a/src/Calculator/Resources/en-US/Resources.resw b/src/Calculator/Resources/en-US/Resources.resw index 7db00ae..09ae7ca 100644 --- a/src/Calculator/Resources/en-US/Resources.resw +++ b/src/Calculator/Resources/en-US/Resources.resw @@ -3399,4 +3399,8 @@ Scroll Calculation Result Right Automation label for the "Scroll Right" button that appears when a calculation result is too large to fit in calculation result text box. - \ No newline at end of file + + Calculation failed + Text displayed when the application is not able to do a calculation + + diff --git a/src/CalculatorUnitTests/DateCalculatorUnitTests.cpp b/src/CalculatorUnitTests/DateCalculatorUnitTests.cpp index e21e638..9d10074 100644 --- a/src/CalculatorUnitTests/DateCalculatorUnitTests.cpp +++ b/src/CalculatorUnitTests/DateCalculatorUnitTests.cpp @@ -300,7 +300,7 @@ TEST_METHOD(TestDateDiff) // } // // Calculate the difference - // m_DateCalcEngine.GetDateDifference(DateUtils::SystemTimeToDateTime(datetimeDifftest[testIndex].startDate), + // m_DateCalcEngine.TryGetDateDifference(DateUtils::SystemTimeToDateTime(datetimeDifftest[testIndex].startDate), // DateUtils::SystemTimeToDateTime(datetimeDifftest[testIndex].endDate), dateOutputFormat, &diff); // // Assert for the result @@ -1050,8 +1050,7 @@ TEST_METHOD(JaEraTransitionDifference) auto endTime = cal->GetDateTime(); DateDifference diff; - viewModel->GetDateDifference(startTime, endTime, DateUnit::Day, &diff); - + VERIFY_IS_TRUE(viewModel->TryGetDateDifference(startTime, endTime, DateUnit::Day, &diff)); VERIFY_ARE_EQUAL(diff.day, 19); } }