The application uses local time to calculate the number of days between 2 dates. If a Daylight Saving Time takes place during this period of time (only Clocks Forward 2am->3am), the application will miss 1 day and fail to calculate the number of days/weeks/months between the 2 dates. image Description of the changes: DateCalculationEngine uses local time to modify dates, however, AddDays, AddWeeks,... won't add 24 hours or 7 days if DST happens between the 2 dates, but instead add ~23.9/24.1 hours or ~6.9/7.1 days (depends if it's the DST clock backward or clock forward). When the DST is clock forward, DateCalculationEngine will miss one day. Solution use UTC dates to calculate date difference. Extra Fix: use calendar->FirstPeriodInThisDay and calendar->FirstHourInThisPeriod in ClipTime (else it will set the time to 12PM (noon) in some regions. replace OBSERVABLE_PROPERTY_RW by OBSERVABLE_PROPERTY_R when possible. remove the definition of CheckClipTimeSameDay (implementation missing) How changes were validated: Tested manually with different regions (FR, US, ES, JP). Fixes #178
151 lines
6.3 KiB
C++
151 lines
6.3 KiB
C++
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
|
|
#pragma once
|
|
|
|
#include "Common/Utils.h"
|
|
#include "Common/DateCalculator.h"
|
|
|
|
const int c_maxOffsetValue = 999;
|
|
|
|
namespace CalculatorApp
|
|
{
|
|
namespace ViewModel
|
|
{
|
|
[Windows::UI::Xaml::Data::Bindable]
|
|
public ref class DateCalculatorViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
|
|
{
|
|
public:
|
|
DateCalculatorViewModel();
|
|
|
|
OBSERVABLE_OBJECT_CALLBACK(OnPropertyChanged);
|
|
|
|
// Input Properties
|
|
OBSERVABLE_PROPERTY_RW(bool, IsDateDiffMode);
|
|
OBSERVABLE_PROPERTY_RW(bool, IsAddMode);
|
|
OBSERVABLE_PROPERTY_R(bool, IsDiffInDays); // If diff is only in days or the dates are the same,
|
|
// then show only one result and avoid redundancy
|
|
|
|
OBSERVABLE_PROPERTY_RW(int, DaysOffset);
|
|
OBSERVABLE_PROPERTY_RW(int, MonthsOffset);
|
|
OBSERVABLE_PROPERTY_RW(int, YearsOffset);
|
|
|
|
// Read only property for offset values
|
|
property Windows::Foundation::Collections::IVector<Platform::String^>^ OffsetValues
|
|
{
|
|
Windows::Foundation::Collections::IVector<Platform::String^>^ get() { return m_offsetValues; }
|
|
}
|
|
|
|
// From date for Date Diff
|
|
property Windows::Foundation::DateTime FromDate
|
|
{
|
|
Windows::Foundation::DateTime get() { return m_fromDate; }
|
|
|
|
void set(Windows::Foundation::DateTime value)
|
|
{
|
|
if (m_fromDate.UniversalTime != value.UniversalTime)
|
|
{
|
|
m_fromDate = value;
|
|
RaisePropertyChanged("FromDate");
|
|
}
|
|
}
|
|
}
|
|
|
|
// To date for Date Diff
|
|
property Windows::Foundation::DateTime ToDate
|
|
{
|
|
Windows::Foundation::DateTime get() { return m_toDate; }
|
|
|
|
void set(Windows::Foundation::DateTime value)
|
|
{
|
|
if (m_toDate.UniversalTime != value.UniversalTime)
|
|
{
|
|
m_toDate = value;
|
|
RaisePropertyChanged("ToDate");
|
|
}
|
|
}
|
|
}
|
|
|
|
// Start date for Add/Subtract date
|
|
property Windows::Foundation::DateTime StartDate
|
|
{
|
|
Windows::Foundation::DateTime get() { return m_startDate; }
|
|
|
|
void set(Windows::Foundation::DateTime value)
|
|
{
|
|
if (m_startDate.UniversalTime != value.UniversalTime)
|
|
{
|
|
m_startDate = value;
|
|
RaisePropertyChanged("StartDate");
|
|
}
|
|
}
|
|
}
|
|
|
|
// Output Properties
|
|
OBSERVABLE_PROPERTY_R(Platform::String^, StrDateDiffResult);
|
|
OBSERVABLE_PROPERTY_R(Platform::String^, StrDateDiffResultAutomationName);
|
|
OBSERVABLE_PROPERTY_R(Platform::String^, StrDateDiffResultInDays);
|
|
OBSERVABLE_PROPERTY_R(Platform::String^, StrDateResult);
|
|
OBSERVABLE_PROPERTY_R(Platform::String^, StrDateResultAutomationName);
|
|
|
|
COMMAND_FOR_METHOD(CopyCommand, DateCalculatorViewModel::OnCopyCommand);
|
|
|
|
void OnCopyCommand(Platform::Object^ parameter);
|
|
|
|
private:
|
|
void OnPropertyChanged(_In_ Platform::String^ prop);
|
|
void OnInputsChanged();
|
|
void UpdateDisplayResult();
|
|
void UpdateStrDateDiffResultAutomationName();
|
|
void UpdateStrDateResultAutomationName();
|
|
void InitializeDateOutputFormats(Platform::String^ calendarIdentifier);
|
|
Platform::String^ GetDateDiffString() const;
|
|
Platform::String^ GetDateDiffStringInDays() const;
|
|
Platform::String^ GetLocalizedNumberString(int value) const;
|
|
static Windows::Foundation::DateTime ClipTime(Windows::Foundation::DateTime dateTime);
|
|
|
|
property bool IsOutOfBound
|
|
{
|
|
bool get() { return m_isOutOfBound; }
|
|
void set(bool value) { m_isOutOfBound = value; UpdateDisplayResult(); }
|
|
}
|
|
|
|
property CalculatorApp::Common::DateCalculation::DateDifference DateDiffResult
|
|
{
|
|
CalculatorApp::Common::DateCalculation::DateDifference get() { return m_dateDiffResult; }
|
|
void set(CalculatorApp::Common::DateCalculation::DateDifference value) { m_dateDiffResult = value; UpdateDisplayResult(); }
|
|
}
|
|
|
|
property CalculatorApp::Common::DateCalculation::DateDifference DateDiffResultInDays
|
|
{
|
|
CalculatorApp::Common::DateCalculation::DateDifference get() { return m_dateDiffResultInDays; }
|
|
void set(CalculatorApp::Common::DateCalculation::DateDifference value) { m_dateDiffResultInDays = value; UpdateDisplayResult(); }
|
|
}
|
|
|
|
property Windows::Foundation::DateTime DateResult
|
|
{
|
|
Windows::Foundation::DateTime get() { return m_dateResult; }
|
|
void set(Windows::Foundation::DateTime value) { m_dateResult = value; UpdateDisplayResult();}
|
|
}
|
|
|
|
private:
|
|
// Property variables
|
|
bool m_isOutOfBound;
|
|
Platform::Collections::Vector<Platform::String^>^ m_offsetValues;
|
|
Windows::Foundation::DateTime m_fromDate;
|
|
Windows::Foundation::DateTime m_toDate;
|
|
Windows::Foundation::DateTime m_startDate;
|
|
Windows::Foundation::DateTime m_dateResult;
|
|
CalculatorApp::Common::DateCalculation::DateDifference m_dateDiffResult;
|
|
CalculatorApp::Common::DateCalculation::DateDifference m_dateDiffResultInDays;
|
|
|
|
// Private members
|
|
std::shared_ptr<CalculatorApp::Common::DateCalculation::DateCalculationEngine> m_dateCalcEngine;
|
|
CalculatorApp::Common::DateCalculation::DateUnit m_daysOutputFormat;
|
|
CalculatorApp::Common::DateCalculation::DateUnit m_allDateUnitsOutputFormat;
|
|
Windows::Globalization::DateTimeFormatting::DateTimeFormatter^ m_dateTimeFormatter;
|
|
std::wstring m_listSeparator;
|
|
};
|
|
}
|
|
}
|