void CXFA_FFDateTimeEdit::OnSelectChanged(IFWL_Widget* pWidget,
                                          int32_t iYear,
                                          int32_t iMonth,
                                          int32_t iDay) {
  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);
  date.SetDate(dt);
  CFX_WideString wsDate;
  date.FormatPatterns(wsDate, wsPicture, m_pDataAcc->GetLocal(),
                      XFA_VALUEPICTURE_Edit);
  CFWL_DateTimePicker* pDateTime = (CFWL_DateTimePicker*)m_pNormalWidget;
  pDateTime->SetEditText(wsDate);
  pDateTime->Update();
  GetDoc()->GetDocEnvironment()->SetFocusWidget(GetDoc(), nullptr);
  CXFA_EventParam eParam;
  eParam.m_eType = XFA_EVENT_Change;
  eParam.m_pTarget = m_pDataAcc;
  m_pDataAcc->GetValue(eParam.m_wsNewText, XFA_VALUEPICTURE_Raw);
  m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Change, &eParam);
}
FX_BOOL CXFA_LocaleValue::ValidateCanonicalDate(const CFX_WideString& wsDate,
                                                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();
  if (nLen < wCountY || nLen > wCountY + wCountM + wCountD + 2) {
    return FALSE;
  }
  const bool bSymbol = wsDate.Find(0x2D) != -1;
  uint16_t wYear = 0;
  uint16_t wMonth = 0;
  uint16_t wDay = 0;
  const FX_WCHAR* pDate = wsDate.c_str();
  int nIndex = 0, nStart = 0;
  while (pDate[nIndex] != '\0' && nIndex < wCountY) {
    if (!FXSYS_isDecimalDigit(pDate[nIndex])) {
      return FALSE;
    }
    wYear = (pDate[nIndex] - '0') + wYear * 10;
    nIndex++;
  }
  if (bSymbol) {
    if (pDate[nIndex] != 0x2D) {
      return FALSE;
    }
    nIndex++;
  }
  nStart = nIndex;
  while (pDate[nIndex] != '\0' && nIndex - nStart < wCountM && nIndex < nLen) {
    if (!FXSYS_isDecimalDigit(pDate[nIndex])) {
      return FALSE;
    }
    wMonth = (pDate[nIndex] - '0') + wMonth * 10;
    nIndex++;
  }
  if (bSymbol) {
    if (pDate[nIndex] != 0x2D) {
      return FALSE;
    }
    nIndex++;
  }
  nStart = nIndex;
  while (pDate[nIndex] != '\0' && nIndex - nStart < wCountD && nIndex < nLen) {
    if (!FXSYS_isDecimalDigit(pDate[nIndex])) {
      return FALSE;
    }
    wDay = (pDate[nIndex] - '0') + wDay * 10;
    nIndex++;
  }
  if (nIndex != nLen) {
    return FALSE;
  }
  if (wYear < 1900 || wYear > 2029) {
    return FALSE;
  }
  if (wMonth < 1 || wMonth > 12) {
    if (wMonth == 0 && nLen == wCountY) {
      return TRUE;
    }
    return FALSE;
  }
  if (wDay < 1) {
    if (wDay == 0 && (nLen == wCountY + wCountM)) {
      return TRUE;
    }
    return FALSE;
  }
  if (wMonth == 2) {
    if (wYear % 400 == 0 || (wYear % 100 != 0 && wYear % 4 == 0)) {
      if (wDay > 29) {
        return FALSE;
      }
    } else {
      if (wDay > 28) {
        return FALSE;
      }
    }
  } else if (wDay > LastDay[wMonth - 1]) {
    return FALSE;
  }
  CFX_Unitime ut;
  ut.Set(wYear, static_cast<uint8_t>(wMonth), static_cast<uint8_t>(wDay));
  unDate = unDate + ut;
  return TRUE;
}