Simplify date time code

This CL removes the CFX_DateTime class and moves the one used method
into the CFX_Unitime class.

Change-Id: I89f6d099b2c436d8f12b9dc2c5f10ac236ad56ef
Reviewed-on: https://pdfium-review.googlesource.com/3104
Reviewed-by: Nicolás Peña <npm@chromium.org>
Commit-Queue: dsinclair <dsinclair@chromium.org>
diff --git a/xfa/fgas/localization/cfx_formatstring.h b/xfa/fgas/localization/cfx_formatstring.h
index 19764da..b93771d 100644
--- a/xfa/fgas/localization/cfx_formatstring.h
+++ b/xfa/fgas/localization/cfx_formatstring.h
@@ -30,7 +30,7 @@
   bool ParseDateTime(const CFX_WideString& wsSrcDateTime,
                      const CFX_WideString& wsPattern,
                      FX_DATETIMETYPE eDateTimeType,
-                     CFX_Unitime& dtValue);
+                     CFX_Unitime* dtValue);
   bool ParseZero(const CFX_WideString& wsSrcText,
                  const CFX_WideString& wsPattern);
   bool ParseNull(const CFX_WideString& wsSrcText,
diff --git a/xfa/fgas/localization/fgas_datetime.cpp b/xfa/fgas/localization/fgas_datetime.cpp
index 0d5b2b9..973fb3b 100644
--- a/xfa/fgas/localization/fgas_datetime.cpp
+++ b/xfa/fgas/localization/fgas_datetime.cpp
@@ -25,22 +25,6 @@
                                              182, 213, 244, 274, 305, 335};
 const int32_t g_FXDaysPerYear = 365;
 const int32_t g_FXDaysPerLeapYear = 366;
-const int32_t g_FXDaysPer4Years = 1461;
-const int32_t g_FXDaysPer100Years = 36524;
-const int32_t g_FXDaysPer400Years = 146097;
-const int64_t g_FXMillisecondsPerSecond = 1000;
-const int64_t g_FXMillisecondsPerMinute = 60000;
-const int64_t g_FXMillisecondsPerHour = 3600000;
-const int64_t g_FXMillisecondsPerDay = 86400000;
-
-int64_t GetDayOfAD(int64_t unitime) {
-  bool bBC = unitime < 0;
-  int64_t iDays = unitime / g_FXMillisecondsPerDay;
-  iDays += bBC ? -1 : 0;
-  if (bBC && (unitime % g_FXMillisecondsPerDay) == 0)
-    iDays++;
-  return iDays;
-}
 
 int32_t DaysBeforeMonthInYear(int32_t iYear, uint8_t iMonth) {
   ASSERT(iYear != 0);
@@ -79,64 +63,6 @@
          iYear / 400;
 }
 
-void DaysToDate(int64_t iDays,
-                int32_t* retYear,
-                uint8_t* retMonth,
-                uint8_t* retDay) {
-  bool bBC = iDays < 0;
-  if (bBC)
-    iDays = -iDays;
-
-  int32_t iYear = 1;
-  uint8_t iMonth = 1;
-  uint8_t iDay = 1;
-  if (iDays >= g_FXDaysPer400Years) {
-    iYear += static_cast<int32_t>(iDays / g_FXDaysPer400Years * 400);
-    iDays %= g_FXDaysPer400Years;
-  }
-
-  if (iDays >= g_FXDaysPer100Years) {
-    if (iDays == g_FXDaysPer100Years * 4) {
-      iYear += 300;
-      iDays -= g_FXDaysPer100Years * 3;
-    } else {
-      iYear += static_cast<int32_t>(iDays / g_FXDaysPer100Years * 100);
-      iDays %= g_FXDaysPer100Years;
-    }
-  }
-
-  if (iDays >= g_FXDaysPer4Years) {
-    iYear += static_cast<int32_t>(iDays / g_FXDaysPer4Years * 4);
-    iDays %= g_FXDaysPer4Years;
-  }
-
-  while (true) {
-    int32_t iYearDays = DaysInYear(iYear);
-    if (iDays < iYearDays) {
-      if (bBC) {
-        iYear = -iYear;
-        iDays = iYearDays - iDays;
-      }
-      break;
-    }
-    iYear++;
-    iDays -= iYearDays;
-  }
-  while (true) {
-    int32_t iMonthDays = FX_DaysInMonth(iYear, iMonth);
-    if (iDays < iMonthDays)
-      break;
-
-    iMonth++;
-    iDays -= iMonthDays;
-  }
-  iDay += static_cast<uint8_t>(iDays);
-
-  *retYear = iYear;
-  *retMonth = iMonth;
-  *retDay = iDay;
-}
-
 struct FXUT_SYSTEMTIME {
   uint16_t wYear;
   uint16_t wMonth;
@@ -145,7 +71,7 @@
   uint16_t wHour;
   uint16_t wMinute;
   uint16_t wSecond;
-  uint16_t wMilliseconds;
+  uint16_t wMillisecond;
 };
 
 }  // namespace
@@ -182,107 +108,21 @@
   utLocal.wHour = st.tm_hour;
   utLocal.wMinute = st.tm_min;
   utLocal.wSecond = st.tm_sec;
-  utLocal.wMilliseconds = curTime.tv_usec / 1000;
+  utLocal.wMillisecond = curTime.tv_usec / 1000;
 #endif  // _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN32_MOBILE_ || \
         // _FX_OS_ == _FX_WIN64_
-  Set(utLocal.wYear, static_cast<uint8_t>(utLocal.wMonth),
-      static_cast<uint8_t>(utLocal.wDay), static_cast<uint8_t>(utLocal.wHour),
-      static_cast<uint8_t>(utLocal.wMinute),
-      static_cast<uint8_t>(utLocal.wSecond),
-      static_cast<uint16_t>(utLocal.wMilliseconds));
+
+  year_ = utLocal.wYear;
+  month_ = static_cast<uint8_t>(utLocal.wMonth);
+  day_ = static_cast<uint8_t>(utLocal.wDay);
+  hour_ = static_cast<uint8_t>(utLocal.wHour);
+  minute_ = static_cast<uint8_t>(utLocal.wMinute);
+  second_ = static_cast<uint8_t>(utLocal.wSecond);
+  millisecond_ = static_cast<uint16_t>(utLocal.wMillisecond);
 }
 
-void CFX_Unitime::Set(int32_t year,
-                      uint8_t month,
-                      uint8_t day,
-                      uint8_t hour,
-                      uint8_t minute,
-                      uint8_t second,
-                      uint16_t millisecond) {
-  ASSERT(hour <= 23);
-  ASSERT(minute <= 59);
-  ASSERT(second <= 59);
-  ASSERT(millisecond <= 999);
-
-  m_iUnitime = static_cast<int64_t>(hour) * g_FXMillisecondsPerHour +
-               static_cast<int64_t>(minute) * g_FXMillisecondsPerMinute +
-               static_cast<int64_t>(second) * g_FXMillisecondsPerSecond +
-               millisecond;
-  if (year <= 0)
-    return;
-
-  m_iUnitime += DateToDays(year, month, day, false) * g_FXMillisecondsPerDay;
-}
-
-int32_t CFX_Unitime::GetYear() const {
-  int32_t iYear;
-  uint8_t iMonth, iDay;
-  DaysToDate(GetDayOfAD(m_iUnitime), &iYear, &iMonth, &iDay);
-  return iYear;
-}
-
-uint8_t CFX_Unitime::GetMonth() const {
-  int32_t iYear;
-  uint8_t iMonth, iDay;
-  DaysToDate(GetDayOfAD(m_iUnitime), &iYear, &iMonth, &iDay);
-  return iMonth;
-}
-
-uint8_t CFX_Unitime::GetDay() const {
-  int32_t iYear;
-  uint8_t iMonth, iDay;
-  DaysToDate(GetDayOfAD(m_iUnitime), &iYear, &iMonth, &iDay);
-  return iDay;
-}
-
-uint8_t CFX_Unitime::GetHour() const {
-  int32_t v = static_cast<int32_t>(m_iUnitime % g_FXMillisecondsPerDay);
-  if (v < 0)
-    v += g_FXMillisecondsPerDay;
-  return static_cast<uint8_t>(v / g_FXMillisecondsPerHour);
-}
-
-uint8_t CFX_Unitime::GetMinute() const {
-  int32_t v = static_cast<int32_t>(m_iUnitime % g_FXMillisecondsPerHour);
-  if (v < 0)
-    v += g_FXMillisecondsPerHour;
-  return static_cast<uint8_t>(v / g_FXMillisecondsPerMinute);
-}
-
-uint8_t CFX_Unitime::GetSecond() const {
-  int32_t v = static_cast<int32_t>(m_iUnitime % g_FXMillisecondsPerMinute);
-  if (v < 0)
-    v += g_FXMillisecondsPerMinute;
-  return static_cast<uint8_t>(v / g_FXMillisecondsPerSecond);
-}
-
-uint16_t CFX_Unitime::GetMillisecond() const {
-  int32_t v = static_cast<int32_t>(m_iUnitime % g_FXMillisecondsPerSecond);
-  if (v < 0)
-    v += g_FXMillisecondsPerSecond;
-  return static_cast<uint16_t>(v);
-}
-
-bool CFX_DateTime::Set(int32_t year, uint8_t month, uint8_t day) {
-  ASSERT(year != 0);
-  ASSERT(month >= 1 && month <= 12);
-  ASSERT(day >= 1 && day <= FX_DaysInMonth(year, month));
-
-  m_DateTime.Date.sDate.year = year;
-  m_DateTime.Date.sDate.month = month;
-  m_DateTime.Date.sDate.day = day;
-  m_DateTime.Time.sTime.hour = 0;
-  m_DateTime.Time.sTime.minute = 0;
-  m_DateTime.Time.sTime.second = 0;
-  m_DateTime.Time.sTime.millisecond = 0;
-  return true;
-}
-
-int32_t CFX_DateTime::GetDayOfWeek() const {
-  int32_t v = static_cast<int32_t>(DateToDays(m_DateTime.Date.sDate.year,
-                                              m_DateTime.Date.sDate.month,
-                                              m_DateTime.Date.sDate.day, true) %
-                                   7);
+int32_t CFX_Unitime::GetDayOfWeek() const {
+  int32_t v = static_cast<int32_t>(DateToDays(year_, month_, day_, true) % 7);
   if (v < 0)
     v += 7;
   return v;
diff --git a/xfa/fgas/localization/fgas_datetime.h b/xfa/fgas/localization/fgas_datetime.h
index 1f9f19d..9225dcc 100644
--- a/xfa/fgas/localization/fgas_datetime.h
+++ b/xfa/fgas/localization/fgas_datetime.h
@@ -17,35 +17,79 @@
 
 class CFX_Unitime {
  public:
-  CFX_Unitime() { m_iUnitime = 0; }
-  explicit CFX_Unitime(int64_t iUnitime) { m_iUnitime = iUnitime; }
-
-  int64_t ToInt64() const { return m_iUnitime; }
+  CFX_Unitime()
+      : year_(0),
+        month_(0),
+        day_(0),
+        hour_(0),
+        minute_(0),
+        second_(0),
+        millisecond_(0) {}
+  CFX_Unitime(int32_t year,
+              uint8_t month,
+              uint8_t day,
+              uint8_t hour,
+              uint8_t minute,
+              uint8_t second,
+              uint16_t millisecond)
+      : year_(year),
+        month_(month),
+        day_(day),
+        hour_(hour),
+        minute_(minute),
+        second_(second),
+        millisecond_(millisecond) {}
 
   void Now();
-  void Set(int32_t year,
-           uint8_t month,
-           uint8_t day,
-           uint8_t hour,
-           uint8_t minute,
-           uint8_t second,
-           uint16_t millisecond);
-  void Set(int64_t t) { m_iUnitime = t; }
 
-  int32_t GetYear() const;
-  uint8_t GetMonth() const;
-  uint8_t GetDay() const;
-  uint8_t GetHour() const;
-  uint8_t GetMinute() const;
-  uint8_t GetSecond() const;
-  uint16_t GetMillisecond() const;
-
-  CFX_Unitime operator+(const CFX_Unitime& t2) const {
-    return CFX_Unitime(m_iUnitime + t2.m_iUnitime);
+  void Reset() {
+    year_ = 0;
+    month_ = 0;
+    day_ = 0;
+    hour_ = 0;
+    minute_ = 0;
+    second_ = 0;
+    millisecond_ = 0;
   }
 
+  bool IsSet() const {
+    return year_ != 0 || month_ != 0 || day_ != 0 || hour_ != 0 ||
+           minute_ != 0 || second_ != 0 || millisecond_ != 0;
+  }
+
+  void SetDate(int32_t year, uint8_t month, uint8_t day) {
+    year_ = year;
+    month_ = month;
+    day_ = day;
+  }
+
+  void SetTime(uint8_t hour,
+               uint8_t minute,
+               uint8_t second,
+               uint16_t millisecond) {
+    hour_ = hour;
+    minute_ = minute;
+    second_ = second;
+    millisecond_ = millisecond;
+  }
+
+  int32_t GetYear() const { return year_; }
+  uint8_t GetMonth() const { return month_; }
+  uint8_t GetDay() const { return day_; }
+  uint8_t GetHour() const { return hour_; }
+  uint8_t GetMinute() const { return minute_; }
+  uint8_t GetSecond() const { return second_; }
+  uint16_t GetMillisecond() const { return millisecond_; }
+  int32_t GetDayOfWeek() const;
+
  private:
-  int64_t m_iUnitime;
+  int32_t year_;
+  uint8_t month_;
+  uint8_t day_;
+  uint8_t hour_;
+  uint8_t minute_;
+  uint8_t second_;
+  uint16_t millisecond_;
 };
 
 #if _FX_OS_ != _FX_ANDROID_
@@ -59,46 +103,4 @@
 #pragma pack(pop)
 #endif
 
-class CFX_DateTime {
- public:
-  CFX_DateTime() {}
-  ~CFX_DateTime() {}
-
-  bool Set(int32_t year, uint8_t month, uint8_t day);
-  int32_t GetDayOfWeek() const;
-
- private:
-#if _FX_OS_ != _FX_ANDROID_
-#pragma pack(push, 1)
-#endif
-  struct FX_DATE {
-    int32_t year;
-    uint8_t month;
-    uint8_t day;
-  };
-
-  struct FX_TIME {
-    uint8_t hour;
-    uint8_t minute;
-    uint8_t second;
-    uint16_t millisecond;
-  };
-
-  struct FX_DATETIME {
-    union {
-      FX_DATE sDate;
-      FX_DATE aDate;
-    } Date;
-    union {
-      FX_TIME sTime;
-      FX_TIME aTime;
-    } Time;
-  };
-
-#if _FX_OS_ != _FX_ANDROID_
-#pragma pack(pop)
-#endif
-  FX_DATETIME m_DateTime;
-};
-
 #endif  // XFA_FGAS_LOCALIZATION_FGAS_DATETIME_H_
diff --git a/xfa/fgas/localization/fgas_locale.cpp b/xfa/fgas/localization/fgas_locale.cpp
index 253e851..7fddbb4 100644
--- a/xfa/fgas/localization/fgas_locale.cpp
+++ b/xfa/fgas/localization/fgas_locale.cpp
@@ -205,7 +205,7 @@
 bool ParseLocaleDate(const CFX_WideString& wsDate,
                      const CFX_WideString& wsDatePattern,
                      IFX_Locale* pLocale,
-                     CFX_Unitime& datetime,
+                     CFX_Unitime* datetime,
                      int32_t& cc) {
   int32_t year = 1900;
   int32_t month = 1;
@@ -393,9 +393,7 @@
   if (cc < len)
     return false;
 
-  CFX_Unitime ut;
-  ut.Set(year, month, day, 0, 0, 0, 0);
-  datetime = datetime + ut;
+  datetime->SetDate(year, month, day);
   return !!cc;
 }
 
@@ -423,7 +421,7 @@
 bool ParseLocaleTime(const CFX_WideString& wsTime,
                      const CFX_WideString& wsTimePattern,
                      IFX_Locale* pLocale,
-                     CFX_Unitime& datetime,
+                     CFX_Unitime* datetime,
                      int32_t& cc) {
   uint8_t hour = 0;
   uint8_t minute = 0;
@@ -611,9 +609,7 @@
       }
     }
   }
-  CFX_Unitime ut;
-  ut.Set(0, 0, 0, hour, minute, second, millisecond);
-  datetime = datetime + ut;
+  datetime->SetTime(hour, minute, second, millisecond);
   return !!cc;
 }
 
@@ -953,7 +949,7 @@
 
 }  // namespace
 
-bool FX_DateFromCanonical(const CFX_WideString& wsDate, CFX_Unitime& datetime) {
+bool FX_DateFromCanonical(const CFX_WideString& wsDate, CFX_Unitime* datetime) {
   int32_t year = 1900;
   int32_t month = 1;
   int32_t day = 1;
@@ -1026,14 +1022,12 @@
       }
     }
   }
-  CFX_Unitime ut;
-  ut.Set(year, month, day, 0, 0, 0, 0);
-  datetime = datetime + ut;
+  datetime->SetDate(year, month, day);
   return true;
 }
 
 bool FX_TimeFromCanonical(const CFX_WideStringC& wsTime,
-                          CFX_Unitime& datetime,
+                          CFX_Unitime* datetime,
                           IFX_Locale* pLocale) {
   if (wsTime.GetLength() == 0)
     return false;
@@ -1099,17 +1093,14 @@
           FX_TIMEZONE tzDiff;
           tzDiff.tzHour = 0;
           tzDiff.tzMinute = 0;
-          if (str[cc] != 'Z') {
+          if (str[cc] != 'Z')
             cc += ParseTimeZone(str + cc, len - cc, tzDiff);
-          }
           ResolveZone(hour, minute, tzDiff, pLocale);
         }
       }
     }
   }
-  CFX_Unitime ut;
-  ut.Set(0, 0, 0, hour, minute, second, millisecond);
-  datetime = datetime + ut;
+  datetime->SetTime(hour, minute, second, millisecond);
   return true;
 }
 
@@ -2077,8 +2068,9 @@
 bool CFX_FormatString::ParseDateTime(const CFX_WideString& wsSrcDateTime,
                                      const CFX_WideString& wsPattern,
                                      FX_DATETIMETYPE eDateTimeType,
-                                     CFX_Unitime& dtValue) {
-  dtValue.Set(0);
+                                     CFX_Unitime* dtValue) {
+  dtValue->Reset();
+
   if (wsSrcDateTime.IsEmpty() || wsPattern.IsEmpty()) {
     return false;
   }
@@ -2711,15 +2703,16 @@
   if (eCategory == FX_DATETIMETYPE_Unknown) {
     return false;
   }
-  CFX_Unitime dt(0);
+  CFX_Unitime dt;
   int32_t iT = wsSrcDateTime.Find(L"T");
   if (iT < 0) {
     if (eCategory == FX_DATETIMETYPE_Date &&
-        FX_DateFromCanonical(wsSrcDateTime, dt)) {
+        FX_DateFromCanonical(wsSrcDateTime, &dt)) {
       return FormatDateTimeInternal(dt, wsDatePattern, wsTimePattern, true,
                                     pLocale, wsOutput);
-    } else if (eCategory == FX_DATETIMETYPE_Time &&
-               FX_TimeFromCanonical(wsSrcDateTime.AsStringC(), dt, pLocale)) {
+    }
+    if (eCategory == FX_DATETIMETYPE_Time &&
+        FX_TimeFromCanonical(wsSrcDateTime.AsStringC(), &dt, pLocale)) {
       return FormatDateTimeInternal(dt, wsDatePattern, wsTimePattern, true,
                                     pLocale, wsOutput);
     }
@@ -2727,11 +2720,11 @@
     CFX_WideString wsSrcDate(wsSrcDateTime.c_str(), iT);
     CFX_WideStringC wsSrcTime(wsSrcDateTime.c_str() + iT + 1,
                               wsSrcDateTime.GetLength() - iT - 1);
-    if (wsSrcDate.IsEmpty() || wsSrcTime.IsEmpty()) {
+    if (wsSrcDate.IsEmpty() || wsSrcTime.IsEmpty())
       return false;
-    }
-    if (FX_DateFromCanonical(wsSrcDate, dt) &&
-        FX_TimeFromCanonical(wsSrcTime, dt, pLocale)) {
+
+    if (FX_DateFromCanonical(wsSrcDate, &dt) &&
+        FX_TimeFromCanonical(wsSrcTime, &dt, pLocale)) {
       return FormatDateTimeInternal(dt, wsDatePattern, wsTimePattern,
                                     eCategory != FX_DATETIMETYPE_TimeDate,
                                     pLocale, wsOutput);
diff --git a/xfa/fgas/localization/fgas_locale.h b/xfa/fgas/localization/fgas_locale.h
index ffcbb36..449430b 100644
--- a/xfa/fgas/localization/fgas_locale.h
+++ b/xfa/fgas/localization/fgas_locale.h
@@ -80,9 +80,9 @@
                              CFX_WideString& wsPattern) const = 0;
 };
 
-bool FX_DateFromCanonical(const CFX_WideString& wsDate, CFX_Unitime& datetime);
+bool FX_DateFromCanonical(const CFX_WideString& wsDate, CFX_Unitime* datetime);
 bool FX_TimeFromCanonical(const CFX_WideStringC& wsTime,
-                          CFX_Unitime& datetime,
+                          CFX_Unitime* datetime,
                           IFX_Locale* pLocale);
 class CFX_Decimal {
  public:
diff --git a/xfa/fwl/cfwl_monthcalendar.cpp b/xfa/fwl/cfwl_monthcalendar.cpp
index 6d60663..b167141 100644
--- a/xfa/fwl/cfwl_monthcalendar.cpp
+++ b/xfa/fwl/cfwl_monthcalendar.cpp
@@ -90,7 +90,6 @@
     CFWL_Widget* pOuter)
     : CFWL_Widget(app, std::move(properties), pOuter),
       m_bInitialized(false),
-      m_pDateTime(new CFX_DateTime),
       m_iCurYear(2011),
       m_iCurMonth(1),
       m_iYear(2011),
@@ -570,9 +569,9 @@
 }
 
 void CFWL_MonthCalendar::ResetDateItem() {
-  m_pDateTime->Set(m_iCurYear, m_iCurMonth, 1);
   int32_t iDays = FX_DaysInMonth(m_iCurYear, m_iCurMonth);
-  int32_t iDayOfWeek = m_pDateTime->GetDayOfWeek();
+  int32_t iDayOfWeek =
+      CFX_Unitime(m_iCurYear, m_iCurMonth, 1, 0, 0, 0, 0).GetDayOfWeek();
   for (int32_t i = 0; i < iDays; i++) {
     if (iDayOfWeek >= 7)
       iDayOfWeek = 0;
diff --git a/xfa/fwl/cfwl_monthcalendar.h b/xfa/fwl/cfwl_monthcalendar.h
index a110ee8..164e339 100644
--- a/xfa/fwl/cfwl_monthcalendar.h
+++ b/xfa/fwl/cfwl_monthcalendar.h
@@ -165,7 +165,6 @@
   CFX_RectF m_rtWeekNumSep;
   CFX_WideString m_wsHead;
   CFX_WideString m_wsToday;
-  std::unique_ptr<CFX_DateTime> m_pDateTime;
   std::vector<std::unique_ptr<DATEINFO>> m_arrDates;
   int32_t m_iCurYear;
   int32_t m_iCurMonth;
diff --git a/xfa/fxfa/app/xfa_ffnotify.cpp b/xfa/fxfa/app/xfa_ffnotify.cpp
index ce6d7db..fb154d8 100644
--- a/xfa/fxfa/app/xfa_ffnotify.cpp
+++ b/xfa/fxfa/app/xfa_ffnotify.cpp
@@ -264,6 +264,7 @@
 CFX_WideString CXFA_FFNotify::GetCurrentDateTime() {
   CFX_Unitime dataTime;
   dataTime.Now();
+
   CFX_WideString wsDateTime;
   wsDateTime.Format(L"%d%02d%02dT%02d%02d%02d", dataTime.GetYear(),
                     dataTime.GetMonth(), dataTime.GetDay(), dataTime.GetHour(),
diff --git a/xfa/fxfa/app/xfa_fftextedit.cpp b/xfa/fxfa/app/xfa_fftextedit.cpp
index 50685c7..b4560c8 100644
--- a/xfa/fxfa/app/xfa_fftextedit.cpp
+++ b/xfa/fxfa/app/xfa_fftextedit.cpp
@@ -522,7 +522,7 @@
         if (!wsText.IsEmpty()) {
           CXFA_LocaleValue lcValue = XFA_GetLocaleValue(m_pDataAcc);
           CFX_Unitime date = lcValue.GetDate();
-          if (date.ToInt64() != 0)
+          if (date.IsSet())
             pWidget->SetCurSel(date.GetYear(), date.GetMonth(), date.GetDay());
         }
       } break;
@@ -619,8 +619,8 @@
     CXFA_LocaleValue lcValue = XFA_GetLocaleValue(m_pDataAcc);
     CFX_Unitime date = lcValue.GetDate();
     if (lcValue.IsValid()) {
-      if (date.ToInt64() != 0) {
-        ((CFWL_DateTimePicker*)m_pNormalWidget)
+      if (date.IsSet()) {
+        static_cast<CFWL_DateTimePicker*>(m_pNormalWidget)
             ->SetCurSel(date.GetYear(), date.GetMonth(), date.GetDay());
       }
     }
@@ -646,9 +646,8 @@
   CFX_WideString wsPicture;
   m_pDataAcc->GetPictureContent(wsPicture, XFA_VALUEPICTURE_Edit);
   CXFA_LocaleValue date(XFA_VT_DATE, GetDoc()->GetXFADoc()->GetLocalMgr());
-  CFX_Unitime dt;
-  dt.Set(iYear, iMonth, iDay, 0, 0, 0, 0);
-  date.SetDate(dt);
+  date.SetDate(CFX_Unitime(iYear, iMonth, iDay, 0, 0, 0, 0));
+
   CFX_WideString wsDate;
   date.FormatPatterns(wsDate, wsPicture, m_pDataAcc->GetLocal(),
                       XFA_VALUEPICTURE_Edit);
diff --git a/xfa/fxfa/parser/xfa_localevalue.cpp b/xfa/fxfa/parser/xfa_localevalue.cpp
index cddfff3..770b87e 100644
--- a/xfa/fxfa/parser/xfa_localevalue.cpp
+++ b/xfa/fxfa/parser/xfa_localevalue.cpp
@@ -132,10 +132,10 @@
         break;
       case FX_LOCALECATEGORY_Date: {
         CFX_Unitime dt;
-        bRet = ValidateCanonicalDate(wsValue, dt);
+        bRet = ValidateCanonicalDate(wsValue, &dt);
         if (!bRet) {
           bRet = pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Date,
-                                        dt);
+                                        &dt);
           if (!bRet) {
             bRet = pFormat->FormatDateTime(wsValue, wsFormat, wsOutput,
                                            FX_DATETIMETYPE_Date);
@@ -145,8 +145,8 @@
       }
       case FX_LOCALECATEGORY_Time: {
         CFX_Unitime dt;
-        bRet =
-            pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Time, dt);
+        bRet = pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Time,
+                                      &dt);
         if (!bRet) {
           bRet = pFormat->FormatDateTime(wsValue, wsFormat, wsOutput,
                                          FX_DATETIMETYPE_Time);
@@ -156,7 +156,7 @@
       case FX_LOCALECATEGORY_DateTime: {
         CFX_Unitime dt;
         bRet = pFormat->ParseDateTime(wsValue, wsFormat,
-                                      FX_DATETIMETYPE_DateTime, dt);
+                                      FX_DATETIMETYPE_DateTime, &dt);
         if (!bRet) {
           bRet = pFormat->FormatDateTime(wsValue, wsFormat, wsOutput,
                                          FX_DATETIMETYPE_DateTime);
@@ -351,7 +351,7 @@
 CFX_Unitime CXFA_LocaleValue::GetDate() const {
   if (m_bValid && m_dwType == XFA_VT_DATE) {
     CFX_Unitime dt;
-    FX_DateFromCanonical(m_wsValue, dt);
+    FX_DateFromCanonical(m_wsValue, &dt);
     return dt;
   }
   return CFX_Unitime();
@@ -359,9 +359,10 @@
 
 CFX_Unitime CXFA_LocaleValue::GetTime() const {
   if (m_bValid && m_dwType == XFA_VT_TIME) {
-    CFX_Unitime dt(0);
     ASSERT(m_pLocaleMgr);
-    FX_TimeFromCanonical(m_wsValue.AsStringC(), dt,
+
+    CFX_Unitime dt;
+    FX_TimeFromCanonical(m_wsValue.AsStringC(), &dt,
                          m_pLocaleMgr->GetDefLocale());
     return dt;
   }
@@ -372,10 +373,10 @@
   if (m_bValid && m_dwType == XFA_VT_DATETIME) {
     int32_t index = m_wsValue.Find('T');
     CFX_Unitime dt;
-    FX_DateFromCanonical(m_wsValue.Left(index), dt);
+    FX_DateFromCanonical(m_wsValue.Left(index), &dt);
     ASSERT(m_pLocaleMgr);
     FX_TimeFromCanonical(
-        m_wsValue.Right(m_wsValue.GetLength() - index - 1).AsStringC(), dt,
+        m_wsValue.Right(m_wsValue.GetLength() - index - 1).AsStringC(), &dt,
         m_pLocaleMgr->GetDefLocale());
     return dt;
   }
@@ -560,20 +561,20 @@
   CFX_Unitime dt;
   switch (dwVType) {
     case XFA_VT_DATE: {
-      if (ValidateCanonicalDate(wsValue, dt)) {
+      if (ValidateCanonicalDate(wsValue, &dt))
         return true;
-      }
+
       CFX_WideString wsDate, wsTime;
       if (XFA_ValueSplitDateTime(wsValue, wsDate, wsTime) &&
-          ValidateCanonicalDate(wsDate, dt)) {
+          ValidateCanonicalDate(wsDate, &dt)) {
         return true;
       }
       return false;
     }
     case XFA_VT_TIME: {
-      if (ValidateCanonicalTime(wsValue)) {
+      if (ValidateCanonicalTime(wsValue))
         return true;
-      }
+
       CFX_WideString wsDate, wsTime;
       if (XFA_ValueSplitDateTime(wsValue, wsDate, wsTime) &&
           ValidateCanonicalTime(wsTime)) {
@@ -584,7 +585,7 @@
     case XFA_VT_DATETIME: {
       CFX_WideString wsDate, wsTime;
       if (XFA_ValueSplitDateTime(wsValue, wsDate, wsTime) &&
-          ValidateCanonicalDate(wsDate, dt) && ValidateCanonicalTime(wsTime)) {
+          ValidateCanonicalDate(wsDate, &dt) && ValidateCanonicalTime(wsTime)) {
         return true;
       }
     } break;
@@ -592,7 +593,7 @@
   return true;
 }
 bool CXFA_LocaleValue::ValidateCanonicalDate(const CFX_WideString& wsDate,
-                                             CFX_Unitime& unDate) {
+                                             CFX_Unitime* unDate) {
   const uint16_t LastDay[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
   const uint16_t wCountY = 4, wCountM = 2, wCountD = 2;
   int nLen = wsDate.GetLength();
@@ -671,12 +672,12 @@
   } else if (wDay > LastDay[wMonth - 1]) {
     return false;
   }
-  CFX_Unitime ut;
-  ut.Set(wYear, static_cast<uint8_t>(wMonth), static_cast<uint8_t>(wDay), 0, 0,
-         0, 0);
-  unDate = unDate + ut;
+
+  unDate->SetDate(wYear, static_cast<uint8_t>(wMonth),
+                  static_cast<uint8_t>(wDay));
   return true;
 }
+
 bool CXFA_LocaleValue::ValidateCanonicalTime(const CFX_WideString& wsTime) {
   int nLen = wsTime.GetLength();
   if (nLen < 2)
@@ -768,25 +769,26 @@
   return nIndex == nLen && wHour < 24 && wMinute < 60 && wSecond < 60 &&
          wFraction <= 999;
 }
+
 bool CXFA_LocaleValue::ValidateCanonicalDateTime(
     const CFX_WideString& wsDateTime) {
   CFX_WideString wsDate, wsTime;
-  if (wsDateTime.IsEmpty()) {
+  if (wsDateTime.IsEmpty())
     return false;
-  }
+
   int nSplitIndex = -1;
   nSplitIndex = wsDateTime.Find('T');
-  if (nSplitIndex < 0) {
+  if (nSplitIndex < 0)
     nSplitIndex = wsDateTime.Find(' ');
-  }
-  if (nSplitIndex < 0) {
+  if (nSplitIndex < 0)
     return false;
-  }
+
   wsDate = wsDateTime.Left(nSplitIndex);
   wsTime = wsDateTime.Right(wsDateTime.GetLength() - nSplitIndex - 1);
   CFX_Unitime dt;
-  return ValidateCanonicalDate(wsDate, dt) && ValidateCanonicalTime(wsTime);
+  return ValidateCanonicalDate(wsDate, &dt) && ValidateCanonicalTime(wsTime);
 }
+
 bool CXFA_LocaleValue::ParsePatternValue(const CFX_WideString& wsValue,
                                          const CFX_WideString& wsPattern,
                                          IFX_Locale* pLocale) {
@@ -828,32 +830,29 @@
         break;
       case FX_LOCALECATEGORY_Date: {
         CFX_Unitime dt;
-        bRet = ValidateCanonicalDate(wsValue, dt);
+        bRet = ValidateCanonicalDate(wsValue, &dt);
         if (!bRet) {
           bRet = pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Date,
-                                        dt);
+                                        &dt);
         }
-        if (bRet) {
+        if (bRet)
           SetDate(dt);
-        }
         break;
       }
       case FX_LOCALECATEGORY_Time: {
         CFX_Unitime dt;
-        bRet =
-            pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Time, dt);
-        if (bRet) {
+        bRet = pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Time,
+                                      &dt);
+        if (bRet)
           SetTime(dt);
-        }
         break;
       }
       case FX_LOCALECATEGORY_DateTime: {
         CFX_Unitime dt;
         bRet = pFormat->ParseDateTime(wsValue, wsFormat,
-                                      FX_DATETIMETYPE_DateTime, dt);
-        if (bRet) {
+                                      FX_DATETIMETYPE_DateTime, &dt);
+        if (bRet)
           SetDateTime(dt);
-        }
         break;
       }
       default:
diff --git a/xfa/fxfa/parser/xfa_localevalue.h b/xfa/fxfa/parser/xfa_localevalue.h
index a239fa7..cea5eb1 100644
--- a/xfa/fxfa/parser/xfa_localevalue.h
+++ b/xfa/fxfa/parser/xfa_localevalue.h
@@ -54,7 +54,7 @@
                            IFX_Locale* pLocale,
                            XFA_VALUEPICTURE eValueType) const;
   bool ValidateCanonicalValue(const CFX_WideString& wsValue, uint32_t dwVType);
-  bool ValidateCanonicalDate(const CFX_WideString& wsDate, CFX_Unitime& unDate);
+  bool ValidateCanonicalDate(const CFX_WideString& wsDate, CFX_Unitime* unDate);
   bool ValidateCanonicalTime(const CFX_WideString& wsTime);
   bool ValidateCanonicalDateTime(const CFX_WideString& wsDateTime);
   void GetNumbericFormat(CFX_WideString& wsFormat,